Merge branch 'dev' of https://gitee.com/log4j/pig into dev

This commit is contained in:
寻欢·李 2018-01-19 12:19:02 +08:00
commit 0649a60c7d
49 changed files with 1273 additions and 184 deletions

1
.gitignore vendored
View File

@ -1,6 +1,5 @@
# maven ignore
target/
*.jar
*.war
*.ear
*.zip

View File

@ -14,6 +14,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@ -27,7 +28,7 @@ import java.io.PrintWriter;
* 手机号登录成功返回oauth token
*/
@Component
public class MobileLoginSuccessHandler implements org.springframework.security.web.authentication.AuthenticationSuccessHandler {
public class MobileLoginSuccessHandler implements AuthenticationSuccessHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ObjectMapper objectMapper;

View File

@ -6,6 +6,7 @@ import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
@ -17,7 +18,7 @@ import org.springframework.stereotype.Component;
@Component
public class MobileSecurityConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
@Autowired
private MobileLoginSuccessHandler mobileLoginSuccessHandler;
private AuthenticationSuccessHandler mobileLoginSuccessHandler;
@Autowired
private UserService userService;

View File

@ -0,0 +1,31 @@
package com.github.pig.auth.component.social;
import com.github.pig.common.constant.SecurityConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.social.security.SocialAuthenticationFilter;
import org.springframework.social.security.SpringSocialConfigurer;
import org.springframework.stereotype.Component;
/**
* 继承默认的社交登录配置加入自定义的后处理逻辑
* Created on 2018/1/8 0008.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
@Component
public class PigSocialConfigurer extends SpringSocialConfigurer {
@Autowired
private AuthenticationSuccessHandler socialLoginSuccessHandler;
@Override
protected <T> T postProcess(T object) {
SocialAuthenticationFilter filter = (SocialAuthenticationFilter) super.postProcess(object);
filter.setFilterProcessesUrl(SecurityConstants.DEFAULT_SOCIAL_PROCESS_URL);
filter.setAlwaysUsePostLoginUrl(true);
filter.setAuthenticationSuccessHandler(socialLoginSuccessHandler);
return (T) filter;
}
}

View File

@ -0,0 +1,34 @@
package com.github.pig.auth.component.social;
import com.github.pig.common.constant.SecurityConstants;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.social.config.annotation.EnableSocial;
import org.springframework.social.config.annotation.SocialConfigurerAdapter;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.web.ProviderSignInUtils;
import org.springframework.social.security.SpringSocialConfigurer;
/**
* 社交登录配置主类
* Created on 2018/1/8 0008.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
@Configuration
@EnableSocial
public class SocialConfig extends SocialConfigurerAdapter {
/**
* 处理注册流程的工具类
*
* @param factoryLocator
* @return
*/
@Bean
public ProviderSignInUtils providerSignInUtils(ConnectionFactoryLocator factoryLocator) {
return new ProviderSignInUtils(factoryLocator, getUsersConnectionRepository(factoryLocator));
}
}

View File

@ -0,0 +1,27 @@
package com.github.pig.auth.component.social;
import org.springframework.web.servlet.view.AbstractView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* Created on 2018/1/11 0011.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
public class SocialConnectView extends AbstractView {
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
response.setContentType("text/html;charset=UTF-8");
if (model.get("connection") == null) {
response.getWriter().write("<h3>解绑成功</h3>");
} else {
response.getWriter().write("<h3>绑定成功</h3>");
}
}
}

View File

@ -0,0 +1,45 @@
package com.github.pig.auth.component.social;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionRepository;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.view.AbstractView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 访问/connect会获取所有绑定社交的信息(显示是否绑定第三方社交信息)
* Created on 2018/1/11 0011.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
@Component("connect/status")
public class SocialConnectionStatusView extends AbstractView {
@Autowired
private ObjectMapper objectMapper;
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, List<Connection<?>>> connections = (Map<String, List<Connection<?>>>) model.get("connectionMap");
Map<String, Boolean> result = new HashMap<>();
for (String key : connections.keySet()) {
result.put(key, CollectionUtils.isNotEmpty(connections.get(key)));
}
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(objectMapper.writeValueAsString(result));
}
}

View File

@ -0,0 +1,80 @@
package com.github.pig.auth.component.social;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pig.auth.config.AuthServerConfig;
import com.github.pig.auth.config.PigAuthorizationConfig;
import com.github.pig.common.constant.CommonConstant;
import com.xiaoleilu.hutool.util.MapUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.codec.Base64;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author lengleng
* @date 2018年01月18日09:44:16
* 社交登录成功返回oauth token
*/
@Component
public class SocialLoginSuccessHandler implements AuthenticationSuccessHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ObjectMapper objectMapper;
@Autowired
private AuthServerConfig AuthServerConfig;
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private AuthorizationServerTokenServices authorizationServerTokenServices;
/**
* Called when a user has been successfully authenticated.
* 调用spring security oauth API 生成 oAuth2AccessToken
*
* @param request the request which caused the successful authentication
* @param response the response
* @param authentication the <tt>Authentication</tt> object which was created during
*/
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
try {
String clientId = AuthServerConfig.getClientId();
String clientSecret = AuthServerConfig.getClientSecret();
JSONObject params = new JSONObject();
params.put("clientId", clientId);
params.put("clientSecret", clientSecret);
params.put("authentication", authentication);
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
TokenRequest tokenRequest = new TokenRequest(MapUtil.newHashMap(), clientId, clientDetails.getScope(), "social");
OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
OAuth2AccessToken oAuth2AccessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
logger.info("获取token 成功:{}", oAuth2AccessToken.getValue());
String url = String.format("http://localhost:9527/#/login?access_token=%s&refresh_token=%s"
, oAuth2AccessToken.getValue(), oAuth2AccessToken.getRefreshToken().getValue());
logger.info("social登录回调地址{}",url);
response.sendRedirect(url);
} catch (IOException e) {
throw new BadCredentialsException(
"Failed to decode basic authentication token");
}
}
}

View File

@ -0,0 +1,23 @@
package com.github.pig.auth.component.social;
import lombok.Data;
/**
* Created on 2018/1/8 0008.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
@Data
public class SocialUserInfo {
private String providerId;
private String providerUserId;
private String nickname;
private String headImg;
}

View File

@ -0,0 +1,16 @@
package com.github.pig.auth.component.social.qq.api;
/**
* Created on 2018/1/8 0008.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
public interface QQ {
/**
* 获取用户信息
* @return
*/
QQUserInfo getUserInfo();
}

View File

@ -0,0 +1,91 @@
package com.github.pig.auth.component.social.qq.api;
import lombok.Data;
/**
* qq互联http://wiki.connect.qq.com/get_user_info
* Created on 2018/1/8 0008.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
@Data
public class QQUserInfo {
/**
* 返回码
*/
private String ret;
/**
* 如果ret<0会有相应的错误信息提示返回数据全部用UTF-8编码
*/
private String msg;
/**
*
*/
private String openId;
/**
* 不知道什么东西文档上没写但是实际api返回里有
*/
private String is_lost;
/**
* (直辖市)
*/
private String province;
/**
* (直辖市区)
*/
private String city;
/**
* 出生年月
*/
private String year;
/**
* 用户在QQ空间的昵称
*/
private String nickname;
/**
* 大小为30×30像素的QQ空间头像URL
*/
private String figureurl;
/**
* 大小为50×50像素的QQ空间头像URL
*/
private String figureurl_1;
/**
* 大小为100×100像素的QQ空间头像URL
*/
private String figureurl_2;
/**
* 大小为40×40像素的QQ头像URL
*/
private String figureurl_qq_1;
/**
* 大小为100×100像素的QQ头像URL需要注意不是所有的用户都拥有QQ的100×100的头像但40×40像素则是一定会有
*/
private String figureurl_qq_2;
/**
* 性别 如果获取不到则默认返回
*/
private String gender;
/**
* 标识用户是否为黄钻用户0不是1
*/
private String is_yellow_vip;
/**
* 标识用户是否为黄钻用户0不是1
*/
private String vip;
/**
* 黄钻等级
*/
private String yellow_vip_level;
/**
* 黄钻等级
*/
private String level;
/**
* 标识是否为年费黄钻用户0不是 1
*/
private String is_yellow_year_vip;
}

View File

@ -0,0 +1,69 @@
package com.github.pig.auth.component.social.qq.api.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pig.auth.component.social.qq.api.QQ;
import com.github.pig.auth.component.social.qq.api.QQUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.social.oauth2.AbstractOAuth2ApiBinding;
import org.springframework.social.oauth2.TokenStrategy;
/**
* Created on 2018/1/8 0008.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
@Slf4j
public class QQImpl extends AbstractOAuth2ApiBinding implements QQ {
private static final String QQ_URL_GET_OPENID = "https://graph.qq.com/oauth2.0/me?access_token=%s";
private static final String QQ_URL_GET_USER_INFO = "https://graph.qq.com/user/get_user_info?oauth_consumer_key=%s&openid=%s";
/**
* appId 配置文件读取
*/
private String appId;
/**
* openId 请求QQ_URL_GET_OPENID返回
*/
private String openId;
/**
* 工具类
*/
private ObjectMapper objectMapper = new ObjectMapper();
/**
* 构造方法获取openId
*/
public QQImpl(String accessToken, String appId) {
//access_token作为查询参数来携带
super(accessToken, TokenStrategy.ACCESS_TOKEN_PARAMETER);
this.appId = appId;
String url = String.format(QQ_URL_GET_OPENID, accessToken);
String result = getRestTemplate().getForObject(url, String.class);
log.info("【QQImpl】 QQ_URL_GET_OPENID={} result={}", QQ_URL_GET_OPENID, result);
this.openId = StringUtils.substringBetween(result, "\"openid\":\"", "\"}");
}
@Override
public QQUserInfo getUserInfo() {
String url = String.format(QQ_URL_GET_USER_INFO, appId, openId);
String result = getRestTemplate().getForObject(url, String.class);
log.info("【QQImpl】 QQ_URL_GET_USER_INFO={} result={}", QQ_URL_GET_USER_INFO, result);
QQUserInfo userInfo = null;
try {
userInfo = objectMapper.readValue(result, QQUserInfo.class);
userInfo.setOpenId(openId);
return userInfo;
} catch (Exception e) {
throw new RuntimeException("获取用户信息失败", e);
}
}
}

View File

@ -0,0 +1,40 @@
package com.github.pig.auth.component.social.qq.config;
import com.github.pig.auth.component.social.qq.connect.QQConnectionFactory;
import com.github.pig.auth.component.social.repository.PigUsersConnectionRepository;
import com.github.pig.common.constant.SecurityConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.social.SocialAutoConfigurerAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.social.connect.ConnectionFactory;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.ConnectionSignUp;
import org.springframework.social.connect.UsersConnectionRepository;
/**
* Created on 2018/1/8 0008.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
@Configuration
public class QQAuthConfig extends SocialAutoConfigurerAdapter {
@Autowired
private ConnectionSignUp myConnectionSignUp;
@Override
protected ConnectionFactory<?> createConnectionFactory() {
return new QQConnectionFactory(SecurityConstants.DEFAULT_SOCIAL_QQ_PROVIDER_ID, SecurityConstants.DEFAULT_SOCIAL_QQ_APP_ID, SecurityConstants.DEFAULT_SOCIAL_QQ_APP_SECRET);
}
@Bean(name = "usersConnectionRepository")
@Override
public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
PigUsersConnectionRepository repository = new PigUsersConnectionRepository();
repository.setConnectionSignUp(myConnectionSignUp);
return repository;
}
}

View File

@ -0,0 +1,21 @@
package com.github.pig.auth.component.social.qq.connect;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionSignUp;
import org.springframework.stereotype.Component;
/**
* Created on 2018/1/8 0008.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
@Component
public class MyConnectionSignUp implements ConnectionSignUp {
@Override
public String execute(Connection<?> connection) {
//根据社交用户信息默认创建用户并返回用户唯一标识
return connection.getKey().getProviderUserId();
}
}

View File

@ -0,0 +1,42 @@
package com.github.pig.auth.component.social.qq.connect;
import com.github.pig.auth.component.social.qq.api.QQ;
import com.github.pig.auth.component.social.qq.api.QQUserInfo;
import org.springframework.social.connect.ApiAdapter;
import org.springframework.social.connect.ConnectionValues;
import org.springframework.social.connect.UserProfile;
/**
* qq返回的信息为spring social提供的适配器
* Created on 2018/1/8 0008.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
public class QQAdapter implements ApiAdapter<QQ> {
@Override
public boolean test(QQ api) {
return true;
}
@Override
public void setConnectionValues(QQ api, ConnectionValues values) {
QQUserInfo userInfo = api.getUserInfo();
values.setProviderUserId(userInfo.getOpenId());
values.setDisplayName(userInfo.getNickname());
values.setImageUrl(userInfo.getFigureurl_qq_1());
values.setProfileUrl(null);
}
@Override
public UserProfile fetchUserProfile(QQ api) {
return null;
}
@Override
public void updateStatus(QQ api, String message) {
}
}

View File

@ -0,0 +1,18 @@
package com.github.pig.auth.component.social.qq.connect;
import com.github.pig.auth.component.social.qq.api.QQ;
import org.springframework.social.connect.support.OAuth2ConnectionFactory;
/**
* Created on 2018/1/8 0008.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
public class QQConnectionFactory extends OAuth2ConnectionFactory<QQ> {
public QQConnectionFactory(String providerId, String appId, String appSecret) {
super(providerId, new QQServiceProvider(appId, appSecret), new QQAdapter());
}
}

View File

@ -0,0 +1,55 @@
package com.github.pig.auth.component.social.qq.connect;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.oauth2.OAuth2Template;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.Charset;
/**
* Created on 2018/1/8 0008.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
@Slf4j
public class QQOAuth2Template extends OAuth2Template {
public QQOAuth2Template(String clientId, String clientSecret, String authorizeUrl, String accessTokenUrl) {
super(clientId, clientSecret, authorizeUrl, accessTokenUrl);
setUseParametersForClientAuthentication(true);
}
@Override
protected AccessGrant postForAccessGrant(String accessTokenUrl, MultiValueMap<String, String> parameters) {
String responseStr = getRestTemplate().postForObject(accessTokenUrl, parameters, String.class);
log.info("【QQOAuth2Template】获取accessToke的响应responseStr={}" + responseStr);
String[] items = StringUtils.splitByWholeSeparatorPreserveAllTokens(responseStr, "&");
//http://wiki.connect.qq.com/使用authorization_code获取access_token
//access_token=FE04************************CCE2&expires_in=7776000&refresh_token=88E4************************BE14
String accessToken = StringUtils.substringAfterLast(items[0], "=");
Long expiresIn = new Long(StringUtils.substringAfterLast(items[1], "="));
String refreshToken = StringUtils.substringAfterLast(items[2], "=");
return new AccessGrant(accessToken, null, refreshToken, expiresIn);
}
/**
* 日志debug模式才打印出来 处理qq返回的text/html 类型数据
*
* @return
*/
@Override
protected RestTemplate createRestTemplate() {
RestTemplate restTemplate = super.createRestTemplate();
restTemplate.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
return restTemplate;
}
}

View File

@ -0,0 +1,37 @@
package com.github.pig.auth.component.social.qq.connect;
import com.github.pig.auth.component.social.qq.api.QQ;
import com.github.pig.auth.component.social.qq.api.impl.QQImpl;
import org.springframework.social.oauth2.AbstractOAuth2ServiceProvider;
/**
* http://wiki.connect.qq.com/%E4%BD%BF%E7%94%A8authorization_code%E8%8E%B7%E5%8F%96access_token
* Created on 2018/1/8 0008.
*
* @author zlf
* @email i@merryyou.cn
* @since 1.0
*/
public class QQServiceProvider extends AbstractOAuth2ServiceProvider<QQ> {
/**
* 获取code
*/
private static final String QQ_URL_AUTHORIZE = "https://graph.qq.com/oauth2.0/authorize";
/**
* 获取access_token 也就是令牌
*/
private static final String QQ_URL_ACCESS_TOKEN = "https://graph.qq.com/oauth2.0/token";
private String appId;
public QQServiceProvider(String appId, String appSecret) {
super(new QQOAuth2Template(appId, appSecret, QQ_URL_AUTHORIZE, QQ_URL_ACCESS_TOKEN));
this.appId = appId;
}
@Override
public QQ getApi(String accessToken) {
return new QQImpl(accessToken, appId);
}
}

View File

@ -0,0 +1,173 @@
package com.github.pig.auth.component.social.repository;
import org.springframework.social.connect.*;
import org.springframework.util.MultiValueMap;
import java.util.List;
/**
* @author lengleng
* @date 2018/1/18
*/
public class PigConnectionRepository implements ConnectionRepository {
/**
* Find all connections the current user has across all providers.
* The returned map contains an entry for each provider the user is connected to.
* The key for each entry is the providerId, and the value is the list of {@link Connection}s that exist between the user and that provider.
* For example, if the user is connected once to Facebook and twice to Twitter, the returned map would contain two entries with the following structure:
* <pre>
* {
* "facebook" -&gt; Connection("Keith Donald") ,
* "twitter" -&gt; Connection("kdonald"), Connection("springsource")
* }
* </pre>
* The returned map is sorted by providerId and entry values are ordered by rank.
* Returns an empty map if the user has no connections.
*
* @return all connections the current user has across all providers.
*/
@Override
public MultiValueMap<String, Connection<?>> findAllConnections() {
return null;
}
/**
* Find the connections the current user has to the provider registered by the given id e.g. 'facebook'.
* The returned list is ordered by connection rank.
* Returns an empty list if the user has no connections to the provider.
*
* @param providerId the provider id e.g. "facebook"
* @return the connections the user has to the provider, or an empty list if none
*/
@Override
public List<Connection<?>> findConnections(String providerId) {
return null;
}
/**
* Find the connections the current user has to the provider of the given API e.g. Facebook.class.
* Semantically equivalent to {@link #findConnections(String)}, but uses the apiType as the provider key instead of the providerId.
* Useful for direct use by application code to obtain parameterized Connection instances e.g. <code>List&lt;Connection&lt;Facebook&gt;&gt;</code>.
*
* @param apiType the API type e.g. Facebook.class or Twitter.class
* @return the connections the user has to the provider of the API, or an empty list if none
*/
@Override
public <A> List<Connection<A>> findConnections(Class<A> apiType) {
return null;
}
/**
* Find the connections the current user has to the given provider users.
* The providerUsers parameter accepts a map containing an entry for each provider the caller is interested in.
* The key for each entry is the providerId e.g. "facebook", and the value is a list of provider user ids to fetch connections to e.g. ("126500", "34521", "127243").
* The returned map has the same structure and order, except the provider userId values have been replaced by Connection instances.
* If no connection exists between the current user and a given provider user, a null value is returned for that position.
*
* @param providerUserIds the provider users map
* @return the provider user connection map
*/
@Override
public MultiValueMap<String, Connection<?>> findConnectionsToUsers(MultiValueMap<String, String> providerUserIds) {
return null;
}
/**
* Get a connection for the current user by its key, which consists of the providerId + providerUserId.
*
* @param connectionKey the service provider connection key
* @return the connection
* @throws NoSuchConnectionException if no such connection exists for the current user
*/
@Override
public Connection<?> getConnection(ConnectionKey connectionKey) {
return null;
}
/**
* Get a connection between the current user and the given provider user.
* Semantically equivalent to {@link #getConnection(ConnectionKey)}, but uses the apiType as the provider key instead of the providerId.
* Useful for direct use by application code to obtain a parameterized Connection instance.
*
* @param apiType the API type e.g. Facebook.class or Twitter.class
* @param providerUserId the provider user e.g. "126500".
* @return the connection
* @throws NoSuchConnectionException if no such connection exists for the current user
*/
@Override
public <A> Connection<A> getConnection(Class<A> apiType, String providerUserId) {
return null;
}
/**
* Get the "primary" connection the current user has to the provider of the given API e.g. Facebook.class.
* If the user has multiple connections to the provider associated with the given apiType, this method returns the one with the top rank (or priority).
* Useful for direct use by application code to obtain a parameterized Connection instance.
*
* @param apiType the API type e.g. Facebook.class or Twitter.class
* @return the primary connection
* @throws NotConnectedException if the user is not connected to the provider of the API
*/
@Override
public <A> Connection<A> getPrimaryConnection(Class<A> apiType) {
return null;
}
/**
* Find the "primary" connection the current user has to the provider of the given API e.g. Facebook.class.
* Semantically equivalent to {@link #getPrimaryConnection(Class)} but returns null if no connection is found instead of throwing an exception.
*
* @param apiType the API type e.g. Facebook.class or Twitter.class
* @return the primary connection, or <code>null</code> if not found
*/
@Override
public <A> Connection<A> findPrimaryConnection(Class<A> apiType) {
return null;
}
/**
* Add a new connection to this repository for the current user.
* After the connection is added, it can be retrieved later using one of the finders defined in this interface.
*
* @param connection the new connection to add to this repository
* @throws DuplicateConnectionException if the user already has this connection
*/
@Override
public void addConnection(Connection<?> connection) {
}
/**
* Update a Connection already added to this repository.
* Merges the field values of the given connection object with the values stored in the repository.
*
* @param connection the existing connection to update in this repository
*/
@Override
public void updateConnection(Connection<?> connection) {
}
/**
* Remove all Connections between the current user and the provider from this repository.
* Does nothing if no provider connections exist.
*
* @param providerId the provider id e.g. 'facebook'
*/
@Override
public void removeConnections(String providerId) {
}
/**
* Remove a single Connection for the current user from this repository.
* Does nothing if no such connection exists.
*
* @param connectionKey the connection key
*/
@Override
public void removeConnection(ConnectionKey connectionKey) {
}
}

View File

@ -0,0 +1,42 @@
package com.github.pig.auth.component.social.repository;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionRepository;
import org.springframework.social.connect.ConnectionSignUp;
import org.springframework.social.connect.UsersConnectionRepository;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author lengleng
* @date 2018/1/18
* 覆盖原有的保存的逻辑不保存登录状态
*/
public class PigUsersConnectionRepository implements UsersConnectionRepository {
private ConnectionSignUp connectionSignUp;
public ConnectionSignUp getConnectionSignUp() {
return connectionSignUp;
}
public void setConnectionSignUp(ConnectionSignUp connectionSignUp) {
this.connectionSignUp = connectionSignUp;
}
@Override
public List<String> findUserIdsWithConnection(Connection<?> connection) {
return Collections.singletonList(connection.getKey().getProviderUserId());
}
@Override
public Set<String> findUserIdsConnectedTo(String providerId, Set<String> providerUserIds) {
return providerUserIds;
}
@Override
public ConnectionRepository createConnectionRepository(String userId) {
return new PigConnectionRepository();
}
}

View File

@ -1,6 +1,7 @@
package com.github.pig.auth.config;
import com.github.pig.auth.component.mobile.MobileSecurityConfigurer;
import com.github.pig.auth.component.social.PigSocialConfigurer;
import com.github.pig.common.bean.config.FilterUrlsPropertiesConifg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
@ -21,6 +22,8 @@ public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter
private FilterUrlsPropertiesConifg filterUrlsPropertiesConifg;
@Autowired
private MobileSecurityConfigurer mobileSecurityConfigurer;
@Autowired
private PigSocialConfigurer merryyouSpringSocialConfigurer;
@Override
public void configure(HttpSecurity http) throws Exception {
@ -32,7 +35,9 @@ public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter
registry.anyRequest().authenticated()
.and()
.csrf().disable();
http.apply(mobileSecurityConfigurer);
http.apply(mobileSecurityConfigurer)
.and()
.apply(merryyouSpringSocialConfigurer);
}
}

View File

@ -5,6 +5,7 @@ import com.github.pig.common.util.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@ -23,8 +24,8 @@ public class UserController {
@RequestMapping("/user")
public Object user(Principal user) {
return user;
public Object user(Authentication authentication) {
return authentication.getPrincipal();
}
/**

View File

@ -29,4 +29,12 @@ public interface UserService {
*/
@GetMapping("/user/findUserByMobile/{mobile}")
UserVo findUserByMobile(@PathVariable("mobile") String mobile);
/**
* 根据OpenId查询用户信息
* @param openId openId
* @return UserVo
*/
@GetMapping("/user/findUserByOpenId/{openId}")
UserVo findUserByOpenId(@PathVariable("openId") String openId);
}

View File

@ -32,4 +32,16 @@ public class UserServiceFallbackImpl implements UserService {
logger.error("调用{}异常:{}", "通过手机号查询用户", mobile);
return null;
}
/**
* 根据OpenId查询用户信息
*
* @param openId openId
* @return UserVo
*/
@Override
public UserVo findUserByOpenId(String openId) {
logger.error("调用{}异常:{}", "通过OpenId查询用户", openId);
return null;
}
}

View File

@ -2,13 +2,22 @@ package com.github.pig.auth.serivce;
import com.github.pig.auth.feign.UserService;
import com.github.pig.auth.util.UserDetailsImpl;
import com.github.pig.common.vo.SysRole;
import com.github.pig.common.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.social.security.SocialUser;
import org.springframework.social.security.SocialUserDetails;
import org.springframework.social.security.SocialUserDetailsService;
import org.springframework.stereotype.Service;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* @author lengleng
@ -16,7 +25,7 @@ import java.io.Serializable;
* <p>
*/
@Service("userDetailService")
public class UserDetailServiceImpl implements UserDetailsService, Serializable {
public class UserDetailServiceImpl implements UserDetailsService,SocialUserDetailsService, Serializable {
@Autowired
private UserService userService;
@ -25,4 +34,19 @@ public class UserDetailServiceImpl implements UserDetailsService, Serializable {
UserVo userVo = userService.findUserByUsername(username);
return new UserDetailsImpl(userVo);
}
/**
* @param userId the user ID used to lookup the user details
* @return the SocialUserDetails requested
* @see UserDetailsService#loadUserByUsername(String)
*/
@Override
public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException {
UserVo userVo = userService.findUserByOpenId(userId);
List<GrantedAuthority> authorityList = new ArrayList<>();
for (SysRole role : userVo.getRoleList()) {
authorityList.add(new SimpleGrantedAuthority(role.getRoleCode()));
}
return new SocialUser(userVo.getUsername(),userVo.getPassword(), authorityList);
}
}

View File

@ -90,29 +90,8 @@
<artifactId>fastdfs-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
<!--阿里大于-->
<dependency>
<groupId>com.aliyun.taobao</groupId>
<artifactId>alidayu-sms</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>nexus</id>
<name>nexus Repository</name>
<url>http://218.70.11.118:8081/repository/maven-releases/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
</plugins>

View File

@ -57,4 +57,9 @@ public interface CommonConstant {
* JSON 资源
*/
String CONTENT_TYPE = "application/json; charset=utf-8";
/**
* 阿里大鱼
*/
String ALIYUN_SMS = "aliyun_sms";
}

View File

@ -85,4 +85,23 @@ public interface SecurityConstants {
* 认证服务的SERVICEIDzuul 配置的对应
*/
String AUTH_SERVICE_ID = "auth-service";
/**
* qq appID
*/
String DEFAULT_SOCIAL_QQ_APP_ID = "101322838";
/**
* qq appsECRET
*/
String DEFAULT_SOCIAL_QQ_APP_SECRET = "fe6ec1ed3fc45e664ce8ddbf78376ab7";
/**
* 提供商的ID
*/
String DEFAULT_SOCIAL_QQ_PROVIDER_ID = "qq";
/**
* 默认的social的登录地址
*/
String DEFAULT_SOCIAL_PROCESS_URL = "/social";
}

View File

@ -0,0 +1,39 @@
package com.github.pig.common.constant.enums;
/**
* @author lengleng
* @date 2018/1/16
* 短信通道枚举
*/
public enum EnumSmsChannel {
ALIYUN("ALIYUN_SMS", "阿里大鱼");
/**
* 通道名称
*/
private String name;
/**
* 通道描述
*/
private String description;
EnumSmsChannel(String name, String description) {
this.name = name;
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

View File

@ -1,5 +1,7 @@
package com.github.pig.common.util.template;
import lombok.Data;
import java.io.Serializable;
/**
@ -7,7 +9,8 @@ import java.io.Serializable;
* @date 2018/1/15
* 短信消息模板
*/
public class MobileMsgTemplate implements Serializable{
@Data
public class MobileMsgTemplate implements Serializable {
/**
* 手机号
*/
@ -16,25 +19,14 @@ public class MobileMsgTemplate implements Serializable{
* 文本
*/
private String text;
/**
* 类型通道
*/
private String type;
public MobileMsgTemplate(String mobile, String text) {
public MobileMsgTemplate(String mobile, String text, String type) {
this.mobile = mobile;
this.text = text;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
this.type = type;
}
}

View File

@ -28,6 +28,14 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--阿里大于-->
<dependency>
<groupId>com.aliyun.taobao</groupId>
<artifactId>alidayu-sms</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/src/main/resources/lib/alidayu-sms-1.0.jar</systemPath>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,35 @@
package com.github.pig.mc.config;
import lombok.Data;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
/**
* @author lengleng
* @date 2018/1/16
* 阿里大鱼短息服务配置
*/
@Data
@Configuration
@ConditionalOnExpression("!'${sms.aliyun}'.isEmpty()")
@ConfigurationProperties(prefix = "sms.aliyun")
public class SmsAliyunPropertiesConfig {
/**
* 应用ID
*/
private String accessKey;
/**
* 应用秘钥
*/
private String secretKey;
/**
* 短信模板配置
*/
private Map<String, String> channels;
}

View File

@ -0,0 +1,49 @@
package com.github.pig.mc.handler;
import com.github.pig.common.util.template.MobileMsgTemplate;
/**
* @author lengleng
* @date 2018/1/16
* 抽象hander
*/
public abstract class AbstractMessageHandler implements SmsMessageHandler {
/**
* 执行入口
*
* @param mobileMsgTemplate 信息
*/
@Override
public void execute(MobileMsgTemplate mobileMsgTemplate) {
check(mobileMsgTemplate);
if (!process(mobileMsgTemplate)) {
fail(mobileMsgTemplate);
}
}
/**
* 数据校验
*
* @param mobileMsgTemplate 信息
*/
@Override
public abstract void check(MobileMsgTemplate mobileMsgTemplate);
/**
* 业务处理
*
* @param mobileMsgTemplate 信息
* @return boolean
*/
@Override
public abstract boolean process(MobileMsgTemplate mobileMsgTemplate);
/**
* 失败处理
*
* @param mobileMsgTemplate 信息
*/
@Override
public abstract void fail(MobileMsgTemplate mobileMsgTemplate);
}

View File

@ -1,73 +1,82 @@
package com.github.pig.common.util.sms;
package com.github.pig.mc.handler;
import com.alibaba.fastjson.JSONObject;
import com.github.pig.common.constant.CommonConstant;
import com.github.pig.common.util.Assert;
import com.github.pig.common.util.template.MobileMsgTemplate;
import com.github.pig.mc.config.SmsAliyunPropertiesConfig;
import com.github.pig.mc.utils.constant.SmsChannelTemplateConstant;
import com.github.pig.mc.utils.sms.EnumSmsChannelTemplate;
import com.taobao.api.DefaultTaobaoClient;
import com.taobao.api.TaobaoClient;
import com.taobao.api.request.AlibabaAliqinFcSmsNumSendRequest;
import com.taobao.api.response.AlibabaAliqinFcSmsNumSendResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 阿里大于短信发送工具类
*
* @author 浅梦
* @date 2018年1月16日
* @date 2018/1/16
* 阿里大鱼短息服务处理
*/
@Slf4j
public class AliDaYuSendUtils {
//正式环境
@Component(CommonConstant.ALIYUN_SMS)
public class SmsAliyunMessageHandler extends AbstractMessageHandler {
@Autowired
private SmsAliyunPropertiesConfig smsAliyunPropertiesConfig;
private static final String URL = "http://gw.api.taobao.com/router/rest";
private static final String KEY = "";
private static final String SECRET = "";
public static final String CHANNEL = "";
/**
* 短信签名
*/
public static final String SIGN_NAME_LOGIN = "登录验证";
/**
* 发送短信验证码
* @param channel
* @param sign_name
* @param phone
* @param code
* @return
* 数据校验
*
* @param mobileMsgTemplate 消息
*/
public static boolean sendSmsCode(String channel, String sign_name, String phone, String code){
@Override
public void check(MobileMsgTemplate mobileMsgTemplate) {
Assert.isBlank(mobileMsgTemplate.getMobile(), "手机号不能为空");
Assert.isBlank(mobileMsgTemplate.getText(), "验证码不能为空");
}
/**
* 业务处理
*
* @param mobileMsgTemplate 消息
*/
@Override
public boolean process(MobileMsgTemplate mobileMsgTemplate) {
// 配置连接参数URLKEYSECRET
TaobaoClient taobaoClient = new DefaultTaobaoClient(URL, KEY, SECRET);
TaobaoClient taobaoClient = new DefaultTaobaoClient(URL, smsAliyunPropertiesConfig.getAccessKey(), smsAliyunPropertiesConfig.getSecretKey());
// 配置请求参数
AlibabaAliqinFcSmsNumSendRequest request = new AlibabaAliqinFcSmsNumSendRequest();
/**
* 公共回传参数消息返回中会透传回该参数举例用户可以传入自己下级的会员ID在消息返回时该会员ID会包含在内用户可以根据该会员ID识别是哪位会员使用了你的应用
*/
request.setExtend(phone);
request.setExtend(mobileMsgTemplate.getMobile());
/**
* 短信接收号码支持单个或多个手机号码传入号码为11位手机号码不能入加0或+86群发短信需传多个号码以英文逗号分隔一次调用最多传入200个号码示例18600000000,13911111111,13322222222
*/
request.setRecNum(phone);
request.setRecNum(mobileMsgTemplate.getMobile());
/**
* 短信签名传入的短信签名必须是在阿里大鱼管理中心-短信签名管理中的可用签名阿里大鱼已在短信签名管理中通过审核则可传入阿里大鱼传参时去掉引号作为短信签名短信效果示例阿里大鱼欢迎使用阿里大鱼服务
*/
request.setSmsFreeSignName(sign_name);
request.setSmsFreeSignName(EnumSmsChannelTemplate.LOGIN_NAME_LOGIN.getDescription());
/**
* 短信模板变量传参规则{"key":"value"}key的名字须和申请模板中的变量名一致多个变量之间以逗号隔开示例针对模板验证码${code}您正在进行${product}身份验证打死不要告诉别人哦传参时需传入{"code":"1234","product":"alidayu"}
*/
JSONObject jsonObject = new JSONObject();
jsonObject.put("product","pig_cloud");
jsonObject.put("code",code);
jsonObject.put("code",mobileMsgTemplate.getText());
request.setSmsParamString(jsonObject.toString());
/**
* 短信模板ID传入的模板必须是在阿里大鱼管理中心-短信模板管理中的可用模板示例SMS_585014
*/
request.setSmsTemplateCode(channel);
request.setSmsTemplateCode(smsAliyunPropertiesConfig.getChannels().get(SmsChannelTemplateConstant.LOGIN_NAME_LOGIN));
/**
* 短信类型传入值请填写normal
*/
request.setSmsType("normal");
try {
// 请求接口并获取返回值
AlibabaAliqinFcSmsNumSendResponse response = taobaoClient.execute(request);
return response.getResult().getSuccess();
}catch (Exception e){
@ -75,12 +84,13 @@ public class AliDaYuSendUtils {
}
}
/**
* 测试一哈
* @param args
* 失败处理
*
* @param mobileMsgTemplate 消息
*/
public static void main(String[] args) {
log.info("发送结果:" + sendSmsCode(CHANNEL, SIGN_NAME_LOGIN, "1008611", String.valueOf((int)(Math.random()*9+1)*1000)));
@Override
public void fail(MobileMsgTemplate mobileMsgTemplate) {
log.error("短信发送失败 -> 网关:{} -> 手机号:{}", mobileMsgTemplate.getType(), mobileMsgTemplate.getMobile());
}
}

View File

@ -0,0 +1,38 @@
package com.github.pig.mc.handler;
import com.github.pig.common.util.template.MobileMsgTemplate;
/**
* @author lengleng
* @date 2018/1/16
*/
public interface SmsMessageHandler {
/**
* 执行入口
*
* @param mobileMsgTemplate 信息
*/
void execute(MobileMsgTemplate mobileMsgTemplate);
/**
* 数据校验
*
* @param mobileMsgTemplate 信息
*/
void check(MobileMsgTemplate mobileMsgTemplate);
/**
* 业务处理
*
* @param mobileMsgTemplate 信息
* @return boolean
*/
boolean process(MobileMsgTemplate mobileMsgTemplate);
/**
* 失败处理
*
* @param mobileMsgTemplate 信息
*/
void fail(MobileMsgTemplate mobileMsgTemplate);
}

View File

@ -1,13 +1,16 @@
package com.github.pig.mc.listener;
import com.github.pig.common.constant.MqQueueConstant;
import com.github.pig.common.util.sms.AliDaYuSendUtils;
import com.github.pig.common.util.template.MobileMsgTemplate;
import com.github.pig.mc.handler.SmsMessageHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author lengleng
* @date 2018年01月15日13:51:53
@ -17,14 +20,17 @@ import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = MqQueueConstant.MOBILE_CODE_QUEUE)
public class MobileCodeReceiveListener {
@Autowired
private Map<String, SmsMessageHandler> messageHandlerMap;
@RabbitHandler
public void receive(MobileMsgTemplate mobileMsgTemplate) {
boolean status = AliDaYuSendUtils.sendSmsCode(
AliDaYuSendUtils.CHANNEL,
AliDaYuSendUtils.SIGN_NAME_LOGIN,
mobileMsgTemplate.getMobile(),
mobileMsgTemplate.getText());
log.info("消息中心接收到短信发送请求-> 手机号:{} -> 验证码: {} -> 发送状态:{}", mobileMsgTemplate.getMobile(), mobileMsgTemplate.getText(), status);
long startTime = System.currentTimeMillis();
log.info("消息中心接收到短信发送请求-> 手机号:{} -> 验证码: {} ", mobileMsgTemplate.getMobile(), mobileMsgTemplate.getText());
String type = mobileMsgTemplate.getType();
SmsMessageHandler messageHandler = messageHandlerMap.get(type);
messageHandler.execute(mobileMsgTemplate);
long useTime = System.currentTimeMillis() - startTime;
log.info("调用 {} 短信网关处理完毕,耗时 {}毫秒", type, useTime);
}
}

View File

@ -0,0 +1,13 @@
package com.github.pig.mc.utils.constant;
/**
* @author lengleng
* @date 2018/1/16
* 短信通道模板常量
*/
public interface SmsChannelTemplateConstant {
/**
* 登录验证码
*/
String LOGIN_NAME_LOGIN = "loginCodeChannel";
}

View File

@ -0,0 +1,39 @@
package com.github.pig.mc.utils.sms;
/**
* @author lengleng
* @date 2018/1/16
* 短信通道模板
*/
public enum EnumSmsChannelTemplate {
LOGIN_NAME_LOGIN("loginCodeChannel", "登录验证");
/**
* 模板名称
*/
private String name;
/**
* 模板签名
*/
private String description;
EnumSmsChannelTemplate(String name, String description) {
this.name = name;
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

View File

@ -104,10 +104,6 @@ public class UserController extends BaseController {
* @param userDto 用户信息
* @return R
*/
@ApiOperation(value = "更新用户详细信息", notes = "根据传过来的UserDto信息来更新用户详细信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "userDto", value = "用户详细实体user", required = true, dataType = "UserDto")
})
@PutMapping
public R<Boolean> userUpdate(@RequestBody UserDto userDto) {
SysUser user = userService.selectById(userDto.getUserId());
@ -136,6 +132,15 @@ public class UserController extends BaseController {
return userService.findUserByMobile(mobile);
}
/**
* 通过OpenId查询
* @param openId openid
* @return 对象
*/
@GetMapping("/findUserByOpenId/{openId}")
public UserVo findUserByOpenId(@PathVariable String openId){
return userService.findUserByOpenId(openId);
}
/**
* 分页查询用户
*

View File

@ -41,4 +41,12 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
* @return userVo
*/
UserVo selectUserVoByMobile(String mobile);
/**
* 通过openId查询用户信息
*
* @param openId openid
* @return userVo
*/
UserVo selectUserVoByOpenId(String openId);
}

View File

@ -79,4 +79,11 @@ public interface UserService extends IService<SysUser> {
* @return truefalse
*/
Boolean sendSmsCode(String mobile);
/**
* 通过openId查询用户
* @param openId openId
* @return 用户信息
*/
UserVo findUserByOpenId(String openId);
}

View File

@ -11,6 +11,7 @@ import com.github.pig.admin.mapper.SysUserMapper;
import com.github.pig.admin.service.SysMenuService;
import com.github.pig.admin.service.SysUserRoleService;
import com.github.pig.admin.service.UserService;
import com.github.pig.common.constant.CommonConstant;
import com.github.pig.common.constant.MqQueueConstant;
import com.github.pig.common.constant.SecurityConstants;
import com.github.pig.common.util.Query;
@ -94,6 +95,18 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
return sysUserMapper.selectUserVoByMobile(mobile);
}
/**
* 通过openId查询用户
*
* @param openId openId
* @return 用户信息
*/
@Override
@Cacheable(value = "user_details_openid", key = "#openId")
public UserVo findUserByOpenId(String openId) {
return sysUserMapper.selectUserVoByOpenId(openId);
}
@Override
public Page selectWithRolePage(Query query) {
query.setRecords(sysUserMapper.selectUserVoPage(query, query.getCondition()));
@ -129,7 +142,7 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
if (tempCode == null) {
String code = RandomUtil.randomNumbers(4);
logger.info("短信发送请求消息中心 -> 手机号:{} -> 验证码:{}", mobile, code);
rabbitTemplate.convertAndSend(MqQueueConstant.MOBILE_CODE_QUEUE,new MobileMsgTemplate(mobile,code));
rabbitTemplate.convertAndSend(MqQueueConstant.MOBILE_CODE_QUEUE,new MobileMsgTemplate(mobile,code, CommonConstant.ALIYUN_SMS));
redisTemplate.opsForValue().set(SecurityConstants.DEFAULT_CODE_KEY + mobile, code, SecurityConstants.DEFAULT_IMAGE_EXPIRE, TimeUnit.SECONDS);
result = true;
}

View File

@ -34,7 +34,8 @@
<result column="rupdate_time" property="updateTime" />
</collection>
</resultMap>
<select id="selectUserVoByUsername" resultMap="userVoResultMap">
<sql id="selectUserVo">
SELECT
`user`.user_id,
`user`.username,
@ -55,33 +56,21 @@
sys_user AS `user`
LEFT JOIN sys_user_role AS ur ON ur.user_id = `user`.user_id
LEFT JOIN sys_role AS r ON r.role_id = ur.role_id
WHERE
`user`.username = #{username}
</sql>
<select id="selectUserVoByUsername" resultMap="userVoResultMap">
<include refid="selectUserVo"/>
WHERE `user`.username = #{username}
</select>
<select id="selectUserVoByMobile" resultMap="userVoResultMap">
SELECT
`user`.user_id,
`user`.username,
`user`.`password`,
`user`.salt,
`user`.introduction,
`user`.avatar,
`user`.create_time AS ucreate_time,
`user`.update_time AS uupdate_time,
`user`.del_flag AS udel_flag,
r.role_id,
r.role_name,
r.role_code,
r.role_desc,
r.create_time AS rcreate_time,
r.update_time AS rupdate_time
FROM
sys_user AS `user`
LEFT JOIN sys_user_role AS ur ON ur.user_id = `user`.user_id
LEFT JOIN sys_role AS r ON r.role_id = ur.role_id
WHERE
`user`.salt = #{mobile}
<include refid="selectUserVo"/>
WHERE `user`.introduction = #{mobile}
</select>
<select id="selectUserVoByOpenId" resultMap="userVoResultMap">
<include refid="selectUserVo"/>
WHERE `user`.salt = #{openId}
</select>
<select id="selectUserVoPage" resultMap="userVoResultMap" >

View File

@ -19,6 +19,8 @@ public class PigAdminApplicationTest {
System.out.println(stringEncryptor.encrypt("lengleng"));
System.out.println(stringEncryptor.encrypt("root"));
System.out.println(stringEncryptor.encrypt("g0HJr2Ltrs0k6tJDY6pDI2aVMUCPSWZDTROLcFMs"));
System.out.println(stringEncryptor.encrypt("24760324"));
System.out.println(stringEncryptor.encrypt("175d516debb916d3842d981dd3b76061"));
}
}

View File

@ -1,62 +0,0 @@
package com.github.pig.admin.controller;
import com.github.pig.admin.dto.UserDto;
import com.xiaoleilu.hutool.http.HttpUtil;
import com.xiaoleilu.hutool.json.JSONUtil;
import org.apache.commons.collections.MapUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
/**
* @author lengleng
* @date 2017/12/25
* UserController单元测试
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserControllerTest {
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void testUserGet() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/user/{id}", 1)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.username").value("admin"));
}
@Test
public void testUserAdd() throws Exception {
UserDto userDto = new UserDto();
userDto.setRole(1);
userDto.setNewpassword1("@1312312");
mockMvc.perform(MockMvcRequestBuilders.post("/user")
.contentType(MediaType.APPLICATION_JSON)
.content(JSONUtil.toJsonStr(userDto)))
.andExpect(MockMvcResultMatchers.status().isOk());
}
@Test
public void testPostEdu() throws Exception {
System.out.println(HttpUtil.post("http://eco.ahau.edu.cn/jc/dtrans", MapUtils.EMPTY_MAP));
}
}

View File

@ -27,12 +27,12 @@
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server</artifactId>
<version>1.5.5</version>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-ui</artifactId>
<version>1.5.5</version>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
@ -41,7 +41,7 @@
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-ui-turbine</artifactId>
<version>1.5.5</version>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>

View File

@ -39,7 +39,7 @@
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>
<version>1.28.0</version>
<version>2.3.1</version>
</dependency>
</dependencies>

View File

@ -16,7 +16,7 @@
<pig.version>1.0-ALPHA</pig.version>
<spring-boot.version>1.5.9.RELEASE</spring-boot.version>
<spring-cloud.version>Dalston.SR4</spring-cloud.version>
<spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
<!--Lombok-->
<lombok.version>[1.0.0,9.99.99]</lombok.version>