Commit 65ee56c81194209d827a592a9224c3c2b7ec3a2b

Authored by YunaiV
1 parent 0900b9e1

完成 oauth2 check-token 校验 token 的实现

yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2Controller.http renamed to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2OpenController.http
@@ -42,3 +42,8 @@ grant_type=refresh_token&refresh_token=00895465d6994f72a9d926ceeed0f588 @@ -42,3 +42,8 @@ grant_type=refresh_token&refresh_token=00895465d6994f72a9d926ceeed0f588
42 DELETE {{baseUrl}}/system/oauth2/token?token=ca8a188f464441d6949c51493a2b7596 42 DELETE {{baseUrl}}/system/oauth2/token?token=ca8a188f464441d6949c51493a2b7596
43 Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw== 43 Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw==
44 tenant-id: {{adminTenentId}} 44 tenant-id: {{adminTenentId}}
  45 +
  46 +### 请求 /system/oauth2/check-token 接口 => 成功
  47 +POST {{baseUrl}}/system/oauth2/check-token?token=620d307c5b4148df8a98dd6c6c547106
  48 +Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw==
  49 +tenant-id: {{adminTenentId}}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2OpenController.java
@@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.util.http.HttpUtils; @@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
10 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 10 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
11 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 11 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
12 import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO; 12 import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO;
  13 +import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO;
13 import cn.iocoder.yudao.module.system.convert.oauth2.OAuth2OpenConvert; 14 import cn.iocoder.yudao.module.system.convert.oauth2.OAuth2OpenConvert;
14 import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2AccessTokenDO; 15 import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2AccessTokenDO;
15 import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO; 16 import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO;
@@ -17,6 +18,7 @@ import cn.iocoder.yudao.module.system.enums.auth.OAuth2GrantTypeEnum; @@ -17,6 +18,7 @@ import cn.iocoder.yudao.module.system.enums.auth.OAuth2GrantTypeEnum;
17 import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ApproveService; 18 import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ApproveService;
18 import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService; 19 import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService;
19 import cn.iocoder.yudao.module.system.service.oauth2.OAuth2GrantService; 20 import cn.iocoder.yudao.module.system.service.oauth2.OAuth2GrantService;
  21 +import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
20 import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils; 22 import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils;
21 import io.swagger.annotations.Api; 23 import io.swagger.annotations.Api;
22 import io.swagger.annotations.ApiImplicitParam; 24 import io.swagger.annotations.ApiImplicitParam;
@@ -45,14 +47,14 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti @@ -45,14 +47,14 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
45 @Slf4j 47 @Slf4j
46 public class OAuth2OpenController { 48 public class OAuth2OpenController {
47 49
48 -// POST oauth/check_token CheckTokenEndpoint  
49 -  
50 @Resource 50 @Resource
51 private OAuth2GrantService oauth2GrantService; 51 private OAuth2GrantService oauth2GrantService;
52 @Resource 52 @Resource
53 private OAuth2ClientService oauth2ClientService; 53 private OAuth2ClientService oauth2ClientService;
54 @Resource 54 @Resource
55 private OAuth2ApproveService oauth2ApproveService; 55 private OAuth2ApproveService oauth2ApproveService;
  56 + @Resource
  57 + private OAuth2TokenService oauth2TokenService;
56 58
57 /** 59 /**
58 * 对应 Spring Security OAuth 的 TokenEndpoint 类的 postAccessToken 方法 60 * 对应 Spring Security OAuth 的 TokenEndpoint 类的 postAccessToken 方法
@@ -130,9 +132,6 @@ public class OAuth2OpenController { @@ -130,9 +132,6 @@ public class OAuth2OpenController {
130 @RequestParam("token") String token) { 132 @RequestParam("token") String token) {
131 // 校验客户端 133 // 校验客户端
132 String[] clientIdAndSecret = obtainBasicAuthorization(request); 134 String[] clientIdAndSecret = obtainBasicAuthorization(request);
133 - if (ArrayUtil.isEmpty(clientIdAndSecret) || clientIdAndSecret.length != 2) {  
134 - throw exception0(BAD_REQUEST.getCode(), "client_id 或 client_secret 未正确传递");  
135 - }  
136 OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientIdAndSecret[0], clientIdAndSecret[1], 135 OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientIdAndSecret[0], clientIdAndSecret[1],
137 null, null, null); 136 null, null, null);
138 137
@@ -140,6 +139,26 @@ public class OAuth2OpenController { @@ -140,6 +139,26 @@ public class OAuth2OpenController {
140 return success(oauth2GrantService.revokeToken(client.getClientId(), token)); 139 return success(oauth2GrantService.revokeToken(client.getClientId(), token));
141 } 140 }
142 141
  142 + /**
  143 + * 对应 Spring Security OAuth 的 CheckTokenEndpoint 类的 checkToken 方法
  144 + */
  145 + @PostMapping("/check-token")
  146 + @ApiOperation(value = "校验访问令牌")
  147 + @ApiImplicitParam(name = "token", required = true, value = "访问令牌", example = "biu", dataTypeClass = String.class)
  148 + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
  149 + public CommonResult<OAuth2OpenCheckTokenRespVO> checkToken(HttpServletRequest request,
  150 + @RequestParam("token") String token) {
  151 + // 校验客户端
  152 + String[] clientIdAndSecret = obtainBasicAuthorization(request);
  153 + OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientIdAndSecret[0], clientIdAndSecret[1],
  154 + null, null, null);
  155 +
  156 + // 校验令牌
  157 + OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.checkAccessToken(token);
  158 + Assert.notNull(accessTokenDO, "访问令牌不能为空"); // 防御性检查
  159 + return success(OAuth2OpenConvert.INSTANCE.convert2(accessTokenDO));
  160 + }
  161 +
143 // GET oauth/authorize AuthorizationEndpoint TODO 162 // GET oauth/authorize AuthorizationEndpoint TODO
144 @GetMapping("/authorize") 163 @GetMapping("/authorize")
145 @ApiOperation(value = "获得授权信息", notes = "适合 code 授权码模式,或者 implicit 简化模式;在 authorize.vue 单点登录界面被【获取】调用") 164 @ApiOperation(value = "获得授权信息", notes = "适合 code 授权码模式,或者 implicit 简化模式;在 authorize.vue 单点登录界面被【获取】调用")
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/open/OAuth2OpenAccessTokenRespVO.java
@@ -7,7 +7,7 @@ import lombok.AllArgsConstructor; @@ -7,7 +7,7 @@ import lombok.AllArgsConstructor;
7 import lombok.Data; 7 import lombok.Data;
8 import lombok.NoArgsConstructor; 8 import lombok.NoArgsConstructor;
9 9
10 -@ApiModel("管理后台 - 访问令牌 Response VO") 10 +@ApiModel("管理后台 - 【开放接口】访问令牌 Response VO")
11 @Data 11 @Data
12 @NoArgsConstructor 12 @NoArgsConstructor
13 @AllArgsConstructor 13 @AllArgsConstructor
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/open/OAuth2OpenCheckTokenRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonProperty;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.AllArgsConstructor;
  7 +import lombok.Data;
  8 +import lombok.NoArgsConstructor;
  9 +
  10 +import java.util.Set;
  11 +
  12 +@ApiModel("管理后台 - 【开放接口】校验令牌 Response VO")
  13 +@Data
  14 +@NoArgsConstructor
  15 +@AllArgsConstructor
  16 +public class OAuth2OpenCheckTokenRespVO {
  17 +
  18 + @ApiModelProperty(value = "用户编号", required = true, example = "666")
  19 + @JsonProperty("user_id")
  20 + private Long userId;
  21 + @ApiModelProperty(value = "用户类型", required = true, example = "2", notes = "参见 UserTypeEnum 枚举")
  22 + @JsonProperty("user_type")
  23 + private Integer userType;
  24 + @ApiModelProperty(value = "租户编号", required = true, example = "1024")
  25 + @JsonProperty("tenant_id")
  26 + private Long tenantId;
  27 +
  28 + @ApiModelProperty(value = "客户端编号", required = true, example = "car")
  29 + private String clientId;
  30 + @ApiModelProperty(value = "授权范围", required = true, example = "user_info")
  31 + private Set<String> scopes;
  32 +
  33 + @ApiModelProperty(value = "访问令牌", required = true, example = "tudou")
  34 + @JsonProperty("access_token")
  35 + private String accessToken;
  36 +
  37 + @ApiModelProperty(value = "过期时间", required = true, example = "1593092157", notes = "时间戳 / 1000,即单位:秒")
  38 + @JsonProperty("exp")
  39 + private Long exp;
  40 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/oauth2/OAuth2OpenConvert.java
1 package cn.iocoder.yudao.module.system.convert.oauth2; 1 package cn.iocoder.yudao.module.system.convert.oauth2;
2 2
  3 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
3 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; 4 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
4 import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO; 5 import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO;
  6 +import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO;
5 import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2AccessTokenDO; 7 import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2AccessTokenDO;
6 import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils; 8 import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils;
7 import org.mapstruct.Mapper; 9 import org.mapstruct.Mapper;
@@ -19,7 +21,14 @@ public interface OAuth2OpenConvert { @@ -19,7 +21,14 @@ public interface OAuth2OpenConvert {
19 respVO.setScope(OAuth2Utils.buildScopeStr(bean.getScopes())); 21 respVO.setScope(OAuth2Utils.buildScopeStr(bean.getScopes()));
20 return respVO; 22 return respVO;
21 } 23 }
22 -  
23 OAuth2OpenAccessTokenRespVO convert0(OAuth2AccessTokenDO bean); 24 OAuth2OpenAccessTokenRespVO convert0(OAuth2AccessTokenDO bean);
24 25
  26 + default OAuth2OpenCheckTokenRespVO convert2(OAuth2AccessTokenDO bean) {
  27 + OAuth2OpenCheckTokenRespVO respVO = convert3(bean);
  28 + respVO.setExp(bean.getExpiresTime().getTime() / 1000L);
  29 + respVO.setUserType(UserTypeEnum.ADMIN.getValue());
  30 + return respVO;
  31 + }
  32 + OAuth2OpenCheckTokenRespVO convert3(OAuth2AccessTokenDO bean);
  33 +
25 } 34 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java
@@ -37,7 +37,7 @@ public class SecurityConfiguration { @@ -37,7 +37,7 @@ public class SecurityConfiguration {
37 registry.antMatchers(buildAdminApi("/system/sms/callback/**")).permitAll(); 37 registry.antMatchers(buildAdminApi("/system/sms/callback/**")).permitAll();
38 // OAuth2 API 38 // OAuth2 API
39 registry.antMatchers(buildAdminApi("/system/oauth2/token")).permitAll(); 39 registry.antMatchers(buildAdminApi("/system/oauth2/token")).permitAll();
40 - registry.antMatchers(buildAdminApi("/system/oauth2/check_token")).permitAll(); 40 + registry.antMatchers(buildAdminApi("/system/oauth2/check-token")).permitAll();
41 } 41 }
42 42
43 }; 43 };