潘志宝
3 天以前 10edab49cfd859ea4928c969da658b4a548f5b71
iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/oauth2/OAuth2OpenController.java
@@ -1,5 +1,6 @@
package com.iailab.module.system.controller.admin.oauth2;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
@@ -11,7 +12,6 @@
import com.iailab.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO;
import com.iailab.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAuthorizeInfoRespVO;
import com.iailab.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO;
import com.iailab.module.system.controller.admin.oauth2.vo.open.OAuth2OpenLoginReqVO;
import com.iailab.module.system.convert.oauth2.OAuth2OpenConvert;
import com.iailab.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import com.iailab.module.system.dal.dataobject.oauth2.OAuth2ApproveDO;
@@ -34,6 +34,7 @@
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -82,19 +83,73 @@
     *
     * 注意,默认需要传递 client_id + client_secret 参数
     */
    @PostMapping("/fast/token")
    @PermitAll
    @Operation(summary = "脚手架获得访问令牌", description = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【获取】调用")
    @Parameters({
            @Parameter(name = "grant_type", required = true, description = "授权类型", example = "code"),
            @Parameter(name = "code", description = "授权范围", example = "userinfo.read"),
            @Parameter(name = "redirect_uri", description = "重定向 URI", example = "https://www.iocoder.cn"),
            @Parameter(name = "state", description = "状态", example = "1"),
            @Parameter(name = "username", example = "tudou"),
            @Parameter(name = "password", example = "cai"), // 多个使用空格分隔
            @Parameter(name = "scope", example = "user_info"),
            @Parameter(name = "refresh_token", example = "123424233"),
    })
    public CommonResult<OAuth2OpenAccessTokenRespVO> FastAccessToken(HttpServletRequest request,
                                                                     @RequestParam("grant_type") String grantType,
                                                                     @RequestParam(value = "code", required = false) String code, // 授权码模式
                                                                     @RequestParam(value = "redirect_uri", required = false) String redirectUri, // 授权码模式
                                                                     @RequestParam(value = "state", required = false) String state, // 授权码模式
                                                                     @RequestParam(value = "username", required = false) String username, // 密码模式
                                                                     @RequestParam(value = "password", required = false) String password, // 密码模式
                                                                     @RequestParam(value = "scope", required = false) String scope, // 密码模式
                                                                     @RequestParam(value = "refresh_token", required = false) String refreshToken) { // 刷新模式
        OAuth2AccessTokenDO accessTokenDO = getAccessToken(request, grantType, code, redirectUri, state, username, password, scope, refreshToken);
        Assert.notNull(accessTokenDO, "访问令牌不能为空"); // 防御性检查
        return success(OAuth2OpenConvert.INSTANCE.convert(accessTokenDO));
    }
    /**
     * 对应 Spring Security OAuth 的 TokenEndpoint 类的 postAccessToken 方法
     *
     * 外部平台专用授权方式
     *
     * 注意,默认需要传递 client_id + client_secret 参数
     */
    @PostMapping("/token")
    @PermitAll
    @Operation(summary = "获得访问令牌", description = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【获取】调用")
    public CommonResult<OAuth2OpenAccessTokenRespVO> postAccessToken(HttpServletRequest request,
                                                                     @RequestBody OAuth2OpenLoginReqVO openLoginReqVO) {
        String code = openLoginReqVO.getCode();
        String scope = openLoginReqVO.getScope();
        String grantType = openLoginReqVO.getGrantType();
        String redirectUri = openLoginReqVO.getRedirectUri();
        String state = openLoginReqVO.getState();
        String username = openLoginReqVO.getUsername();
        String password = openLoginReqVO.getPassword();
        String refreshToken = openLoginReqVO.getRefreshToken();
    @Operation(summary = "外部平台获得访问令牌", description = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【获取】调用")
    @Parameters({
            @Parameter(name = "grant_type", required = true, description = "授权类型", example = "code"),
            @Parameter(name = "code", description = "授权码", example = "asdfasdfasdf"),
            @Parameter(name = "redirect_uri", description = "重定向 URI", example = "https://www.baidu.com"),
            @Parameter(name = "state", description = "状态", example = "1"),
            @Parameter(name = "username", example = "tudou"),
            @Parameter(name = "password", example = "cai"), // 多个使用空格分隔
            @Parameter(name = "scope", description = "授权范围", example = "user.read"),
            @Parameter(name = "refresh_token", example = "123424233"),
    })
    public Map<String, Object> postAccessToken(HttpServletRequest request,
                                                   @RequestParam("grant_type") String grantType,
                                                   @RequestParam(value = "code", required = false) String code, // 授权码模式
                                                   @RequestParam(value = "redirect_uri", required = false) String redirectUri, // 授权码模式
                                                   @RequestParam(value = "state", required = false) String state, // 授权码模式
                                                   @RequestParam(value = "username", required = false) String username, // 密码模式
                                                   @RequestParam(value = "password", required = false) String password, // 密码模式
                                                   @RequestParam(value = "scope", required = false) String scope, // 密码模式
                                                   @RequestParam(value = "refresh_token", required = false) String refreshToken) { // 刷新模式
        OAuth2AccessTokenDO accessTokenDO = getAccessToken(request, grantType, code, redirectUri, state, username, password, scope, refreshToken);
        Assert.notNull(accessTokenDO, "访问令牌不能为空"); // 防御性检查
        Map<String, Object> map = new HashMap<>();
        map.put("access_token", accessTokenDO.getAccessToken());
        map.put("refresh_token", accessTokenDO.getRefreshToken());
        map.put("expires_time", LocalDateTimeUtil.toEpochMilli(accessTokenDO.getExpiresTime()) / 1000L);
        map.put("client_id", accessTokenDO.getClientId());
        return map;
    }
    private OAuth2AccessTokenDO getAccessToken(HttpServletRequest request, String grantType, String code, String redirectUri, String state, String username, String password, String scope, String refreshToken) {
        List<String> scopes = OAuth2Utils.buildScopes(scope);
        // 1.1 校验授权类型
        OAuth2GrantTypeEnum grantTypeEnum = OAuth2GrantTypeEnum.getByGrantType(grantType);
@@ -129,7 +184,7 @@
                throw new IllegalArgumentException("未知授权类型:" + grantType);
        }
        Assert.notNull(accessTokenDO, "访问令牌不能为空"); // 防御性检查
        return success(OAuth2OpenConvert.INSTANCE.convert(accessTokenDO));
        return accessTokenDO;
    }
    @DeleteMapping("/token")