Commit 98ed8009455f3e3f548a3c063a672f91e68817c9

Authored by YunaiV
1 parent e8383407

feat:【system 系统管理】oauth2 支持 ClientCredentials 模式

yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2OpenController.http
@@ -35,6 +35,14 @@ tenant-id: {{adminTenantId}} @@ -35,6 +35,14 @@ tenant-id: {{adminTenantId}}
35 35
36 grant_type=password&username=admin&password=admin123&scope=user.read 36 grant_type=password&username=admin&password=admin123&scope=user.read
37 37
  38 +### 请求 /system/oauth2/token + client_credentials 接口 => 成功
  39 +POST {{baseUrl}}/system/oauth2/token
  40 +Content-Type: application/x-www-form-urlencoded
  41 +Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw==
  42 +tenant-id: {{adminTenantId}}
  43 +
  44 +grant_type=client_credentials&scope=user.read
  45 +
38 ### 请求 /system/oauth2/token + refresh_token 接口 => 成功 46 ### 请求 /system/oauth2/token + refresh_token 接口 => 成功
39 POST {{baseUrl}}/system/oauth2/token 47 POST {{baseUrl}}/system/oauth2/token
40 Content-Type: application/x-www-form-urlencoded 48 Content-Type: application/x-www-form-urlencoded
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2OpenController.java
@@ -94,6 +94,7 @@ public class OAuth2OpenController { @@ -94,6 +94,7 @@ public class OAuth2OpenController {
94 @Parameter(name = "scope", example = "user_info"), 94 @Parameter(name = "scope", example = "user_info"),
95 @Parameter(name = "refresh_token", example = "123424233"), 95 @Parameter(name = "refresh_token", example = "123424233"),
96 }) 96 })
  97 + @SuppressWarnings("EnhancedSwitchMigration")
97 public CommonResult<OAuth2OpenAccessTokenRespVO> postAccessToken(HttpServletRequest request, 98 public CommonResult<OAuth2OpenAccessTokenRespVO> postAccessToken(HttpServletRequest request,
98 @RequestParam("grant_type") String grantType, 99 @RequestParam("grant_type") String grantType,
99 @RequestParam(value = "code", required = false) String code, // 授权码模式 100 @RequestParam(value = "code", required = false) String code, // 授权码模式
@@ -119,15 +120,23 @@ public class OAuth2OpenController { @@ -119,15 +120,23 @@ public class OAuth2OpenController {
119 grantType, scopes, redirectUri); 120 grantType, scopes, redirectUri);
120 121
121 // 2. 根据授权模式,获取访问令牌 122 // 2. 根据授权模式,获取访问令牌
122 - OAuth2AccessTokenDO accessTokenDO = switch (grantTypeEnum) {  
123 - // TODO @xingyu:这里改了,可能会影响 jdk8 版本哈;  
124 - case AUTHORIZATION_CODE ->  
125 - oauth2GrantService.grantAuthorizationCodeForAccessToken(client.getClientId(), code, redirectUri, state);  
126 - case PASSWORD -> oauth2GrantService.grantPassword(username, password, client.getClientId(), scopes);  
127 - case CLIENT_CREDENTIALS -> oauth2GrantService.grantClientCredentials(client.getClientId(), scopes);  
128 - case REFRESH_TOKEN -> oauth2GrantService.grantRefreshToken(refreshToken, client.getClientId());  
129 - default -> throw new IllegalArgumentException("未知授权类型:" + grantType);  
130 - }; 123 + OAuth2AccessTokenDO accessTokenDO;
  124 + switch (grantTypeEnum) {
  125 + case AUTHORIZATION_CODE:
  126 + accessTokenDO = oauth2GrantService.grantAuthorizationCodeForAccessToken(client.getClientId(), code, redirectUri, state);
  127 + break;
  128 + case PASSWORD:
  129 + accessTokenDO = oauth2GrantService.grantPassword(username, password, client.getClientId(), scopes);
  130 + break;
  131 + case CLIENT_CREDENTIALS:
  132 + accessTokenDO = oauth2GrantService.grantClientCredentials(client.getClientId(), scopes);
  133 + break;
  134 + case REFRESH_TOKEN:
  135 + accessTokenDO = oauth2GrantService.grantRefreshToken(refreshToken, client.getClientId());
  136 + break;
  137 + default:
  138 + throw new IllegalArgumentException("未知授权类型:" + grantType);
  139 + }
131 Assert.notNull(accessTokenDO, "访问令牌不能为空"); // 防御性检查 140 Assert.notNull(accessTokenDO, "访问令牌不能为空"); // 防御性检查
132 return success(OAuth2OpenConvert.INSTANCE.convert(accessTokenDO)); 141 return success(OAuth2OpenConvert.INSTANCE.convert(accessTokenDO));
133 } 142 }
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2GrantServiceImpl.java
@@ -86,8 +86,8 @@ public class OAuth2GrantServiceImpl implements OAuth2GrantService { @@ -86,8 +86,8 @@ public class OAuth2GrantServiceImpl implements OAuth2GrantService {
86 86
87 @Override 87 @Override
88 public OAuth2AccessTokenDO grantClientCredentials(String clientId, List<String> scopes) { 88 public OAuth2AccessTokenDO grantClientCredentials(String clientId, List<String> scopes) {
89 - // TODO 芋艿:项目中使用 OAuth2 解决的是三方应用的授权,内部的 SSO 等问题,所以暂时不考虑 client_credentials 这个场景  
90 - throw new UnsupportedOperationException("暂时不支持 client_credentials 授权模式"); 89 + // 特殊:https://yuanbao.tencent.com/bot/app/share/chat/wFj642xSZHHx
  90 + return oauth2TokenService.createAccessToken(0L, UserTypeEnum.ADMIN.getValue(), clientId, scopes);
91 } 91 }
92 92
93 @Override 93 @Override
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImpl.java
@@ -197,6 +197,9 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService { @@ -197,6 +197,9 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
197 * @return 用户信息 197 * @return 用户信息
198 */ 198 */
199 private Map<String, String> buildUserInfo(Long userId, Integer userType) { 199 private Map<String, String> buildUserInfo(Long userId, Integer userType) {
  200 + if (userId == null || userId <= 0) {
  201 + return Collections.emptyMap();
  202 + }
200 if (userType.equals(UserTypeEnum.ADMIN.getValue())) { 203 if (userType.equals(UserTypeEnum.ADMIN.getValue())) {
201 AdminUserDO user = adminUserService.getUser(userId); 204 AdminUserDO user = adminUserService.getUser(userId);
202 return MapUtil.builder(LoginUser.INFO_KEY_NICKNAME, user.getNickname()) 205 return MapUtil.builder(LoginUser.INFO_KEY_NICKNAME, user.getNickname())
@@ -205,7 +208,7 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService { @@ -205,7 +208,7 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
205 // 注意:目前 Member 暂时不读取,可以按需实现 208 // 注意:目前 Member 暂时不读取,可以按需实现
206 return Collections.emptyMap(); 209 return Collections.emptyMap();
207 } 210 }
208 - return null; 211 + throw new IllegalArgumentException("未知用户类型:" + userType);
209 } 212 }
210 213
211 private static String generateAccessToken() { 214 private static String generateAccessToken() {