摘要
自定义方式登录原理是相同的
自定义登录方式获取Token.png
- AppAuthenticationSuccessHandler
@Slf4j
@Component
public class AppAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
@Autowired
private ObjectMapper objectMapper;
@Autowired
private RavenSecurityProperties securityProperties;
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private AuthorizationServerTokenServices authorizationServerTokenServices;
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
logger.info("登录成功处理器");
String header = request.getHeader("Authorization");
if (header == null || !header.toLowerCase().startsWith("basic ")) {
throw new UnapprovedClientAuthenticationException("请求头中无client信息");
}
String[] tokens = extractAndDecodeHeader(header, request);
assert tokens.length == 2;
String clientId = tokens[0];
String clientSecret = tokens[1];
// 根据clientId获取ClientDetails对象 --- ClientDetails为第三方应用的信息
// 现在配置在了yml文件里,真实项目中应该放在数据库里
ClientDetails clientDetails = this.clientDetailsService.loadClientByClientId(clientId);
// 对获取到的clientDetails进行校验
if (clientDetails == null) {
throw new UnapprovedClientAuthenticationException("clientId对应的配置信息不存在:" + clientId);
} else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {
throw new UnapprovedClientAuthenticationException("clientSecret不匹配:" + clientId);
}
// 第一个参数为请求参数的一个Map集合,
// 在Spring Security OAuth的源码里要用这个Map里的用户名+密码或授权码来生成Authentication对象,
// 但我们已经获取到了Authentication对象,所以这里可以直接传一个空的Map
// 第三个参数为scope即请求的权限 ---》这里的策略是获得的ClientDetails对象里配了什么权限就给什么权限
// TODO
// 第四个参数为指定什么模式 比如密码模式为password,授权码模式为authorization_code,
// 这里我们写一个自定义模式custom
TokenRequest tokenRequest = new TokenRequest(MapUtils.EMPTY_MAP, clientId, clientDetails.getScope(), "custom");
//获取OAuth2Request对象
//源码中是这么写的 --- todo 有兴趣的可以看一下
// OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
//new出一个OAuth2Authentication对象
OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
//生成token
OAuth2AccessToken token = this.authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
//将生成的token返回
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(objectMapper.writeValueAsString(token));
}
/**
* Base64解码
*/
private String[] extractAndDecodeHeader(String header, HttpServletRequest request)
throws IOException {
byte[] base64Token = header.substring(6).getBytes("UTF-8");
byte[] decoded;
try {
decoded = Base64.getDecoder().decode(base64Token);
}
catch (IllegalArgumentException e) {
throw new BadCredentialsException(
"Failed to decode basic authentication token");
}
String token = new String(decoded, "UTF-8");
int delim = token.indexOf(":");
if (delim == -1) {
throw new BadCredentialsException("Invalid basic authentication token");
}
return new String[] { token.substring(0, delim), token.substring(delim + 1) };
}
}
网友评论