spring security oauth2认证服务器 用户授权确认 流程源码 配置要点
源码
org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint
// 授权
@RequestMapping(value = "/oauth/authorize")
public ModelAndView authorize(Map<String, Object> model, @RequestParam Map<String, String> parameters,
SessionStatus sessionStatus, Principal principal) {
...
try {
// 判断当前会话是否存在认证信息
if (!(principal instanceof Authentication) || !((Authentication) principal).isAuthenticated()) {
throw new InsufficientAuthenticationException(
"User must be authenticated with Spring Security before authorization can be completed.");
}
// 校验请求中的scope是否包含在client中
oauth2RequestValidator.validateScope(authorizationRequest, client);
// TokenStoreUserApprovalHandler判断client是否存在autoApprove,并从tokenStore获取保存的approval信息,如果存在则将approved置为true
authorizationRequest = userApprovalHandler.checkForPreApproval(authorizationRequest,
(Authentication) principal);
boolean approved = userApprovalHandler.isApproved(authorizationRequest, (Authentication) principal);
authorizationRequest.setApproved(approved);
// 如果已经存在用户授权,则直接授权
if (authorizationRequest.isApproved()) {
if (responseTypes.contains("token")) {
return getImplicitGrantResponse(authorizationRequest);
}
if (responseTypes.contains("code")) {
return new ModelAndView(getAuthorizationCodeResponse(authorizationRequest,
(Authentication) principal));
}
}
// 将授权请求信息保存在session中以供后续用户确认时使用
model.put(AUTHORIZATION_REQUEST_ATTR_NAME, authorizationRequest);
// 将授权请求原始信息保存在session中以供后续用户确认时使用
model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, unmodifiableMap(authorizationRequest));
// 不存在用户授权则跳转到用户确认页面
return getUserApprovalPageResponse(model, authorizationRequest, (Authentication) principal);
}
...
}
// 用户授权确认页面确认后调用
@RequestMapping(value = "/oauth/authorize", method = RequestMethod.POST, params = OAuth2Utils.USER_OAUTH_APPROVAL)
public View approveOrDeny(@RequestParam Map<String, String> approvalParameters, Map<String, ?> model,
SessionStatus sessionStatus, Principal principal) {
// 从会话中取出授权请求信息
AuthorizationRequest authorizationRequest = (AuthorizationRequest) model.get(AUTHORIZATION_REQUEST_ATTR_NAME);
if (authorizationRequest == null) {
sessionStatus.setComplete();
throw new InvalidRequestException("Cannot approve uninitialized authorization request.");
}
// 取出会话的授权请求信息以及原始授权请求信息,判断是否不一致
@SuppressWarnings("unchecked")
Map<String, Object> originalAuthorizationRequest = (Map<String, Object>) model.get(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME);
if (isAuthorizationRequestModified(authorizationRequest, originalAuthorizationRequest)) {
throw new InvalidRequestException("Changes were detected from the original authorization request.");
}
try {
Set<String> responseTypes = authorizationRequest.getResponseTypes();
// 根据用户提交的授权认可信息重新设置授权请求参数
authorizationRequest.setApprovalParameters(approvalParameters);
// 更新授权请求的确认标识,如果使用的是ApprovalStoreUserApprovalHandler/TokenStoreUserApprovalHandler或其他自定义handler,可在此处保存确认信息,以供后续授权请求自动确认。如果使用DefaultUserApprovalHandler则不进行保存
authorizationRequest = userApprovalHandler.updateAfterApproval(authorizationRequest,
(Authentication) principal);
boolean approved = userApprovalHandler.isApproved(authorizationRequest, (Authentication) principal);
authorizationRequest.setApproved(approved);
// 如果用户拒绝授权,则跳转到错误信息页面
if (!authorizationRequest.isApproved()) {
RedirectView redirectView = new RedirectView(getUnsuccessfulRedirect(authorizationRequest,
new UserDeniedAuthorizationException("User denied access"), responseTypes.contains("token")),
false, true, false);
redirectView.setStatusCode(HttpStatus.SEE_OTHER);
return redirectView;
}
// 执行授权
if (responseTypes.contains("token")) {
return getImplicitGrantResponse(authorizationRequest).getView();
}
return getAuthorizationCodeResponse(authorizationRequest, (Authentication) principal);
}
...
}
用户授权认可处理默认配置
org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer
// 默认的用户确认处理器
private UserApprovalHandler userApprovalHandler() {
if (userApprovalHandler == null) {
if (approvalStore() != null) {
ApprovalStoreUserApprovalHandler handler = new ApprovalStoreUserApprovalHandler();
handler.setApprovalStore(approvalStore());
handler.setRequestFactory(requestFactory());
handler.setClientDetailsService(clientDetailsService);
this.userApprovalHandler = handler;
}
else if (tokenStore() != null) {
TokenStoreUserApprovalHandler userApprovalHandler = new TokenStoreUserApprovalHandler();
userApprovalHandler.setTokenStore(tokenStore());
userApprovalHandler.setClientDetailsService(clientDetailsService());
userApprovalHandler.setRequestFactory(requestFactory());
this.userApprovalHandler = userApprovalHandler;
}
else {
throw new IllegalStateException("Either a TokenStore or an ApprovalStore must be provided");
}
}
return this.userApprovalHandler;
}
// 默认的确认仓库
private ApprovalStore approvalStore() {
if (approvalStore == null && tokenStore() != null && !isApprovalStoreDisabled()) {
TokenApprovalStore tokenApprovalStore = new TokenApprovalStore();
tokenApprovalStore.setTokenStore(tokenStore());
this.approvalStore = tokenApprovalStore;
}
return this.approvalStore;
}
// 默认的令牌仓库
private TokenStore tokenStore() {
if (tokenStore == null) {
if (accessTokenConverter() instanceof JwtAccessTokenConverter) {
this.tokenStore = new JwtTokenStore((JwtAccessTokenConverter) accessTokenConverter());
}
else {
this.tokenStore = new InMemoryTokenStore();
}
}
return this.tokenStore;
}
自定义配置
实现org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
// 配置令牌仓库
endpoints.tokenStore(redisTokenStore);
// 不需要存储用户授权确认信息,则配置DefaultUserApprovalHandler
endpoints.userApprovalHandler(new DefaultUserApprovalHandler());
// 如不需要存储用户授权确认信息,配置此项
endpoints.approvalStoreDisabled();
}
- 注:如果配置了approvalStoreDisabled,必须配置userApprovalHandler,否则将报异常:
Either a TokenStore or an ApprovalStore must be provided