使用openId换取access_token功能完成
This commit is contained in:
+8
-1
@@ -2,6 +2,7 @@ package com.micro.fast.security.app.config.authorization2;
|
||||
|
||||
import com.micro.fast.security.app.config.component.MsAuthenticationFailureHandler;
|
||||
import com.micro.fast.security.app.config.component.MsAuthenticationSuccessHandler;
|
||||
import com.micro.fast.security.app.social.OpenIdAuthenticationSecurityConfig;
|
||||
import com.micro.fast.security.core.authentication.mobile.SmsCodeAuthenticationSecurityConfig;
|
||||
import com.micro.fast.security.core.master.SecurityConstants;
|
||||
import com.micro.fast.security.core.master.SecurityProperties;
|
||||
@@ -45,6 +46,9 @@ public class AuthorizationResourceConfig extends ResourceServerConfigurerAdapter
|
||||
@Autowired
|
||||
private ValidateCodeRepository validateCodeRepository;
|
||||
|
||||
@Autowired
|
||||
private OpenIdAuthenticationSecurityConfig openIdAuthenticationSecurityConfig;
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) throws Exception {
|
||||
//创建自定义的验证码过滤器,填入身份认证失败处理对象
|
||||
@@ -55,7 +59,7 @@ public class AuthorizationResourceConfig extends ResourceServerConfigurerAdapter
|
||||
validateCodeFilter.afterPropertiesSet();
|
||||
|
||||
http
|
||||
//添加自定义的验证码处理器,在用户密码校验过滤器之前
|
||||
//添加自定义的验证码处理器,在用户密码校验过滤器的方式获取令牌之前
|
||||
.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
//使用表单登录
|
||||
.formLogin()
|
||||
@@ -93,6 +97,9 @@ public class AuthorizationResourceConfig extends ResourceServerConfigurerAdapter
|
||||
.and()
|
||||
//应用springSocial的配置,在接收到特殊的请求的时候进行社交登录.例如 /auth/qq 其中/auth是默认的前缀,qq是providerId
|
||||
.apply(springSocialConfigurer)
|
||||
.and()
|
||||
//openid
|
||||
.apply(openIdAuthenticationSecurityConfig);
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
package com.micro.fast.security.app.social;
|
||||
|
||||
import com.micro.fast.security.core.master.SecurityConstants;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* openId登录身份认证过滤器
|
||||
* @author lsy
|
||||
*/
|
||||
public class OpenIdAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
|
||||
|
||||
/**
|
||||
* 从请求中获取openId的key
|
||||
*/
|
||||
private String openIdParameter = SecurityConstants.DEFAULT_PARAMETER_NAME_OPNEID;
|
||||
|
||||
/**
|
||||
* 从请求中获取providerId的key
|
||||
*/
|
||||
private String providerIdParameter = SecurityConstants.DEFAULT_PARAMETER_NAME_PROVIDERID;
|
||||
/**
|
||||
* 是不是只处理post请求
|
||||
*/
|
||||
private boolean postOnly = true;
|
||||
|
||||
/**
|
||||
* 对/authentication/openid路径的post请求进行身份登录操作
|
||||
*/
|
||||
public OpenIdAuthenticationFilter() {
|
||||
super(new AntPathRequestMatcher(SecurityConstants.DEFAULT_LOGIN_PROCESS_URL_OPENID, "POST"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 主要的身份认证方法
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
|
||||
if (this.postOnly && !request.getMethod().equals("POST")) {
|
||||
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
|
||||
} else {
|
||||
//获取请求中的mobile
|
||||
String openid = this.obtainMobile(request);
|
||||
if (openid == null) {
|
||||
openid = "";
|
||||
}
|
||||
openid = openid.trim();
|
||||
String providerId = request.getParameter(this.providerIdParameter);
|
||||
if (providerId == null){
|
||||
providerId = "";
|
||||
}
|
||||
providerId = providerId.trim();
|
||||
OpenIdAuthenticationToken authRequest = new OpenIdAuthenticationToken(openid,providerId);
|
||||
this.setDetails(request, authRequest);
|
||||
//调用AuthenticationManager中的方法
|
||||
return this.getAuthenticationManager().authenticate(authRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取openId的方法
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
protected String obtainMobile(HttpServletRequest request) {
|
||||
return request.getParameter(this.openIdParameter);
|
||||
}
|
||||
|
||||
protected void setDetails(HttpServletRequest request, OpenIdAuthenticationToken authRequest) {
|
||||
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
|
||||
}
|
||||
|
||||
public void setOpenIdParameter(String openIdParameter) {
|
||||
Assert.hasText(openIdParameter, "Username parameter must not be empty or null");
|
||||
this.openIdParameter = openIdParameter;
|
||||
}
|
||||
|
||||
public void setPostOnly(boolean postOnly) {
|
||||
this.postOnly = postOnly;
|
||||
}
|
||||
|
||||
public final String getOpenIdParameter() {
|
||||
return this.openIdParameter;
|
||||
}
|
||||
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package com.micro.fast.security.app.social;
|
||||
|
||||
import com.micro.fast.security.core.authentication.mobile.SmsCodeAuthenticationToken;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.social.connect.UsersConnectionRepository;
|
||||
import org.springframework.social.security.SocialUserDetails;
|
||||
import org.springframework.social.security.SocialUserDetailsService;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 进行openId的身份认证提供类
|
||||
* @author lsy
|
||||
*/
|
||||
public class OpenIdAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
private SocialUserDetailsService userDetailsService;
|
||||
|
||||
private UsersConnectionRepository usersConnectionRepository;
|
||||
/**
|
||||
* 返回经过验证的Authentication
|
||||
* @param authentication
|
||||
* @return
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
OpenIdAuthenticationToken openIdAuthenticationToken = (OpenIdAuthenticationToken) authentication;
|
||||
Set<String> providerUserIds = new HashSet<>();
|
||||
String principal = (String)openIdAuthenticationToken.getPrincipal();
|
||||
providerUserIds.add(principal);
|
||||
Set<String> userIds = usersConnectionRepository.findUserIdsConnectedTo(openIdAuthenticationToken.getProviderId(), providerUserIds);
|
||||
if (CollectionUtils.isEmpty(userIds) || userIds.size()!=1) {
|
||||
throw new InternalAuthenticationServiceException("无法获取用户的信息");
|
||||
}
|
||||
String userId = userIds.iterator().next();
|
||||
UserDetails socialUserDetails = userDetailsService.loadUserByUserId(userId);
|
||||
if (socialUserDetails == null){
|
||||
throw new InternalAuthenticationServiceException("无法获取用户的信息");
|
||||
}
|
||||
OpenIdAuthenticationToken openIdAuthenticationTokenResult = new OpenIdAuthenticationToken(socialUserDetails, socialUserDetails.getAuthorities());
|
||||
openIdAuthenticationTokenResult.setDetails(openIdAuthenticationToken.getDetails());
|
||||
return openIdAuthenticationTokenResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 这个类是不是支持传入的token的校验
|
||||
* @param authenticate
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean supports(Class<?> authenticate) {
|
||||
return OpenIdAuthenticationToken.class.isAssignableFrom(authenticate);
|
||||
}
|
||||
|
||||
public SocialUserDetailsService getUserDetailsService() {
|
||||
return userDetailsService;
|
||||
}
|
||||
|
||||
public void setUserDetailsService(SocialUserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
|
||||
public UsersConnectionRepository getUsersConnectionRepository() {
|
||||
return usersConnectionRepository;
|
||||
}
|
||||
|
||||
public void setUsersConnectionRepository(UsersConnectionRepository usersConnectionRepository) {
|
||||
this.usersConnectionRepository = usersConnectionRepository;
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.micro.fast.security.app.social;
|
||||
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
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.AuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.social.connect.UsersConnectionRepository;
|
||||
import org.springframework.social.security.SocialUserDetailsService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author lsy
|
||||
* openId登录的配置类
|
||||
*/
|
||||
@Component
|
||||
public class OpenIdAuthenticationSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain,HttpSecurity>{
|
||||
|
||||
@Autowired
|
||||
@Qualifier("msAuthenticationSuccessHandler")
|
||||
private AuthenticationSuccessHandler authenticationSuccessHandler;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("msAuthenticationFailureHandler")
|
||||
private AuthenticationFailureHandler authenticationFailureHandler;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("msUserDetailsServiceImpl")
|
||||
private SocialUserDetailsService userDetailsService ;
|
||||
|
||||
@Autowired
|
||||
private UsersConnectionRepository usersConnectionRepository;
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
OpenIdAuthenticationFilter OpenIdAuthenticationFilter = new OpenIdAuthenticationFilter();
|
||||
//将短信验证码登录过滤器放入AuthenticationManager,方便后续调用
|
||||
OpenIdAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
|
||||
OpenIdAuthenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
|
||||
OpenIdAuthenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler);
|
||||
|
||||
//将根据手机号获取用户信息的对象放入短信验证码的provider中
|
||||
OpenIdAuthenticationProvider openIdAuthenticationProvider = new OpenIdAuthenticationProvider();
|
||||
openIdAuthenticationProvider.setUserDetailsService(userDetailsService);
|
||||
openIdAuthenticationProvider.setUsersConnectionRepository(usersConnectionRepository);
|
||||
//将自定义的provider放入authenticaionManger管理的集合中去
|
||||
http.authenticationProvider(openIdAuthenticationProvider)
|
||||
//将自定义的过滤器添加到用户账号密码校验过滤器后面
|
||||
.addFilterAfter(OpenIdAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package com.micro.fast.security.app.social;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* APP社交登陆中使用openId进行登录的token
|
||||
* @author lsy
|
||||
*/
|
||||
public class OpenIdAuthenticationToken extends AbstractAuthenticationToken {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Object principal;
|
||||
|
||||
/**
|
||||
* 服务提供商的id
|
||||
*/
|
||||
private String providerId;
|
||||
|
||||
/**
|
||||
* 在没有进行身份认证的时候存储手机号
|
||||
* @param openId openId
|
||||
*/
|
||||
public OpenIdAuthenticationToken(String openId,String providerId) {
|
||||
super((Collection)null);
|
||||
this.principal = openId;
|
||||
this.providerId = providerId;
|
||||
this.setAuthenticated(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param principal
|
||||
* @param authorities
|
||||
*/
|
||||
public OpenIdAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(authorities);
|
||||
this.principal = principal;
|
||||
super.setAuthenticated(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
|
||||
if (isAuthenticated) {
|
||||
throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
|
||||
} else {
|
||||
super.setAuthenticated(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eraseCredentials() {
|
||||
super.eraseCredentials();
|
||||
}
|
||||
|
||||
public String getProviderId() {
|
||||
return providerId;
|
||||
}
|
||||
|
||||
public void setProviderId(String providerId) {
|
||||
this.providerId = providerId;
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
package com.micro.fast.security.app.social;
|
||||
+14
@@ -41,4 +41,18 @@ public interface SecurityConstants {
|
||||
*/
|
||||
String DEFAULT_SESSION_INVALID_URL = "/ms-session-invalid.html";
|
||||
|
||||
/**
|
||||
* 获取openId的key
|
||||
*/
|
||||
String DEFAULT_PARAMETER_NAME_OPNEID = "openid";
|
||||
|
||||
/**
|
||||
* 获取providerId的key
|
||||
*/
|
||||
String DEFAULT_PARAMETER_NAME_PROVIDERID = "providerId";
|
||||
|
||||
/**
|
||||
* openID获取access_token的步骤
|
||||
*/
|
||||
String DEFAULT_LOGIN_PROCESS_URL_OPENID = "/authentication/openId";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user