文章目录
我们使用Spring Social已经实现了国内最常用的QQ和微信社交登录。本章我们来简单分析一下Spring Social在社交登录的过程中做了哪些事情?(微博社交登录也已经实现,由于已经连续两篇介绍社交登录,所以不在单开一章节描述)
引言
OAuth2是一种授权协议,简单理解就是它可以让用户在不将用户名密码交给第三方应用的情况下,第三方应用有权访问用户存在服务提供商上面的数据。
Spring Social 基本原理
- 访问第三方应用
- 将用户请求导向服务提供商
- 用户同意授权
- 携带授权码返回第三方应用
- 第三方应用携带授权码到服务提供商申请令牌
- 服务提供商返回令牌
- 获取用户基本信息
- 根据用户信息构建
Authentication
放入SecurityContext
中如果在SecurityContext
中放入一个已经认证过的Authentication
实例,那么对于SpringSecurity
来说,已经成功登录
Spring Social
就是为我们将OAuth2
认证流程封装到SocialAuthenticationFilter
过滤器中,并根据返回的用户信息构建Authentication
。然后使用Spring Security
的验证逻辑从而实现使用社交登录。
启动logback断点调试;
ValidateCodeFilter
校验验证码过滤器SocialAuthenticationFilter
社交登录过滤器UsernamePasswordAuthenticationFilter
用户名密码登录过滤器SmsCodeAuthenticationFilter
短信登录过滤器AnonymousAuthenticationFilter
前面过滤器都没校验时匿名验证的过滤器ExceptionTranslationFilter
处理FilterSecurityInterceptor
授权失败时的过滤器FilterSecurityInterceptor
授权过滤器
本章我们主要讲解SocialAuthenticationFilter
SocialAuthenticationFilter
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
//#1.判断用户是否允许授权
if (detectRejection(request)) {
if (logger.isDebugEnabled()) {
logger.debug("A rejection was detected. Failing authentication.");
}
throw new SocialAuthenticationException("Authentication failed because user rejected authorization.");
}
Authentication auth = null;
//#2.获取所有的社交配置providerId(本项目中三个:qq,weixin,weibo)
Set<String> authProviders = authServiceLocator.registeredAuthenticationProviderIds();
//#3.根据请求获取当前的是那种类型的社交登录
String authProviderId = getRequestedProviderId(request);
//#4.判断是否系统中是否配置当前社交providerId
if (!authProviders.isEmpty() && authProviderId != null && authProviders.contains(authProviderId)) {
//#5.获取当前社交的处理类即OAuth2AuthenticationService用于获取Authentication
SocialAuthenticationService<?> authService = authServiceLocator.getAuthenticationService(authProviderId);
//#6.获取SocialAuthenticationToken
auth = attemptAuthService(authService, request, response);
if (auth == null) {
throw new AuthenticationServiceException("authentication failed");
}
}
return auth;
}
private Auth