springsecurity实现oauth2换取授权码的过程中,涉及到先登录,然后再授权,再换取授权码的过程。如果不进行设置,security会跳转到一个默认的授权页面,如下图:

其中红框标注的scope为请求/oauth/authorize时传入的scope。
源码分析
跳转到approve页面的源码如下:
if (authorizationRequest.isApproved()) {
if (responseTypes.contains("token")) {
return getImplicitGrantResponse(authorizationRequest);
}
if (responseTypes.contains("code")) {
return new ModelAndView(getAuthorizationCodeResponse(authorizationRequest,
(Authentication) principal));
}
}
// Store authorizationRequest AND an immutable Map of authorizationRequest in session
// which will be used to validate against in approveOrDeny()
model.put(AUTHORIZATION_REQUEST_ATTR_NAME, authorizationRequest);
model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, unmodifiableMap(authorizationRequest));
//跳转到授权页面
return getUserApprovalPageResponse(model, authorizationRequest, (Authentication) principal);
//生成授权页面
private ModelAndView getUserApprovalPageResponse(Map<String, Object> model,
AuthorizationRequest authorizationRequest, Authentication principal) {
logger.debug("Loading user approval page: " + userApprovalPage);
model.putAll(userApprovalHandler.getUserApprovalRequest(authorizationRequest, principal));
return new ModelAndView(userApprovalPage, model);
}
那么,不想跳转到授权页面就需要看看authorizationRequest.isApproved()这个函数式怎么判断的,进去发现这是authorizationRequest的一个属性,那么属性又是怎么设置的呢?
同样是在这个endpoint里,发现了三行关键代码

进入第一行代码,进入它的实现类ApprovalStoreUserApprovalHandler,可以看到这里对authorizationRequest的approved属性进行了配置,源码如下:
//类名org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler
//方法名checkForPreApproval
if (clientDetailsService != null) {
try {
ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
for (String scope : requestedScopes) {
if (client.isAutoApprove(scope)) {
approvedScopes.add(scope);
}
}
if (approvedScopes.containsAll(requestedScopes)) {
// gh-877 - if all scopes are auto approved, approvals still need to be added to the approval store.
Set<Approval> approvals = new HashSet<Approval>();
Date expiry = computeExpiry();
for (String approvedScope : approvedScopes) {
approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(),
approvedScope, expiry, ApprovalStatus.APPROVED));
}
approvalStore.addApprovals(approvals);
authorizationRequest.setApproved(true);
return authorizationRequest;
}
}
catch (ClientRegistrationException e) {
logger.warn("Client registration problem prevent autoapproval check for client=" + clientId);
}
}
//类名org.springframework.security.oauth2.provider.client.BaseClientDetails
public boolean isAutoApprove(String scope) {
if (autoApproveScopes == null) {
return false;
}
for (String auto : autoApproveScopes) {
if (auto.equals("true") || scope.matches(auto)) {
return true;
}
}
return false;
}
根据以上代码可以判断出,会首先使用clientDetailsService加载出client的信息,然后判断当前的scope是否支持自动approve。autoApprovesScopes定义如下:

故只需要在数据库的oauth_client_details的对应字段添加支持自动授权的字段。
SpringSecurity OAuth2 自动授权机制解析
本文深入探讨了SpringSecurity中OAuth2自动授权机制的实现原理,详细分析了如何通过配置clientDetailsService来实现scope的自动批准,避免跳转到用户授权页面,简化授权流程。
1449

被折叠的 条评论
为什么被折叠?



