mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 12:18:42 +08:00 
			
		
		
		
	完成 oauth2 implicit 简化模式的实现
This commit is contained in:
		@@ -24,7 +24,7 @@ public class OAuth2TokenApiImpl implements OAuth2TokenApi {
 | 
			
		||||
    @Override
 | 
			
		||||
    public OAuth2AccessTokenRespDTO createAccessToken(OAuth2AccessTokenCreateReqDTO reqDTO) {
 | 
			
		||||
        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(
 | 
			
		||||
                reqDTO.getUserId(), reqDTO.getUserType(), reqDTO.getClientId());
 | 
			
		||||
                reqDTO.getUserId(), reqDTO.getUserType(), reqDTO.getClientId(), reqDTO.getScopes());
 | 
			
		||||
        return OAuth2TokenConvert.INSTANCE.convert2(accessTokenDO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,7 @@
 | 
			
		||||
### 请求 /system/oauth2/authorize 接口 => 成功
 | 
			
		||||
POST {{baseUrl}}/system/oauth2/authorize
 | 
			
		||||
Content-Type: application/x-www-form-urlencoded
 | 
			
		||||
Authorization: Bearer {{token}}
 | 
			
		||||
tenant-id: {{adminTenentId}}
 | 
			
		||||
 | 
			
		||||
response_type=token&client_id=default&scope={"user_info": true}&redirect_uri=https://www.iocoder.cn&auto_approve=true
 | 
			
		||||
@@ -1,15 +1,19 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.lang.Assert;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 | 
			
		||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2AccessTokenDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.enums.auth.OAuth2GrantTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ApproveService;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2GrantService;
 | 
			
		||||
import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiImplicitParam;
 | 
			
		||||
import io.swagger.annotations.ApiImplicitParams;
 | 
			
		||||
@@ -26,6 +30,7 @@ import java.util.Map;
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 | 
			
		||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 | 
			
		||||
 | 
			
		||||
@Api(tags = "管理后台 - OAuth2.0 授权")
 | 
			
		||||
@@ -72,16 +77,6 @@ public class OAuth2Controller {
 | 
			
		||||
        // 1.2 校验 redirectUri 重定向域名是否合法 + 校验 scope 是否在 Client 授权范围内
 | 
			
		||||
        oauth2ClientService.validOAuthClientFromCache(clientId, grantTypeEnum.getGrantType(), scopes, redirectUri);
 | 
			
		||||
 | 
			
		||||
        // 2. 判断是否满足自动授权(满足)
 | 
			
		||||
        boolean approved = oauth2ApproveService.checkForPreApproval(getLoginUserId(), UserTypeEnum.ADMIN.getValue(), clientId, scopes);
 | 
			
		||||
        if (approved) {
 | 
			
		||||
            // 2.1 如果是 code 授权码模式,则发放 code 授权码,并重定向
 | 
			
		||||
            if (grantTypeEnum == OAuth2GrantTypeEnum.AUTHORIZATION_CODE) {
 | 
			
		||||
                return success(getAuthorizationCodeRedirect());
 | 
			
		||||
            }
 | 
			
		||||
            return success(getImplicitGrantRedirect());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 3. 不满足自动授权,则返回授权相关的展示信息
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
@@ -104,7 +99,7 @@ public class OAuth2Controller {
 | 
			
		||||
                                              @RequestParam("client_id") String clientId,
 | 
			
		||||
                                              @RequestParam(value = "scope", required = false) String scope,
 | 
			
		||||
                                              @RequestParam("redirect_uri") String redirectUri,
 | 
			
		||||
                                              @RequestParam(value = "autoApprove") Boolean autoApprove,
 | 
			
		||||
                                              @RequestParam(value = "auto_approve") Boolean autoApprove,
 | 
			
		||||
                                              @RequestParam(value = "state", required = false) String state) {
 | 
			
		||||
        @SuppressWarnings("unchecked")
 | 
			
		||||
        Map<String, Boolean> scopes = JsonUtils.parseObject(scope, Map.class);
 | 
			
		||||
@@ -115,27 +110,28 @@ public class OAuth2Controller {
 | 
			
		||||
        // 1.1 校验 responseType 是否满足 code 或者 token 值
 | 
			
		||||
        OAuth2GrantTypeEnum grantTypeEnum = getGrantTypeEnum(responseType);
 | 
			
		||||
        // 1.2 校验 redirectUri 重定向域名是否合法 + 校验 scope 是否在 Client 授权范围内
 | 
			
		||||
        oauth2ClientService.validOAuthClientFromCache(clientId, grantTypeEnum.getGrantType(), scopes.keySet(), redirectUri);
 | 
			
		||||
        OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientId, grantTypeEnum.getGrantType(), scopes.keySet(), redirectUri);
 | 
			
		||||
 | 
			
		||||
        // 2.1 假设 approved 为 null,说明是场景一
 | 
			
		||||
        if (Boolean.TRUE.equals(autoApprove)) {
 | 
			
		||||
            // 如果无法自动授权通过,则返回空 url,前端不进行跳转
 | 
			
		||||
            if (!oauth2ApproveService.checkForPreApproval(getLoginUserId(), UserTypeEnum.ADMIN.getValue(), clientId, scopes.keySet())) {
 | 
			
		||||
            if (!oauth2ApproveService.checkForPreApproval(getLoginUserId(), getUserType(), clientId, scopes.keySet())) {
 | 
			
		||||
                return success(null);
 | 
			
		||||
            }
 | 
			
		||||
        } else { // 2.2 假设 approved 非 null,说明是场景二
 | 
			
		||||
            // 如果计算后不通过,则跳转一个错误链接
 | 
			
		||||
            if (!oauth2ApproveService.updateAfterApproval(getLoginUserId(), UserTypeEnum.ADMIN.getValue(), clientId, scopes)) {
 | 
			
		||||
            if (!oauth2ApproveService.updateAfterApproval(getLoginUserId(), getUserType(), clientId, scopes)) {
 | 
			
		||||
                return success("TODO");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 3.1 如果是 code 授权码模式,则发放 code 授权码,并重定向
 | 
			
		||||
        List<String> approveScopes = convertList(scopes.entrySet(), Map.Entry::getKey, Map.Entry::getValue);
 | 
			
		||||
        if (grantTypeEnum == OAuth2GrantTypeEnum.AUTHORIZATION_CODE) {
 | 
			
		||||
            return success(getAuthorizationCodeRedirect());
 | 
			
		||||
        }
 | 
			
		||||
        // 3.2 如果是 token 则是 implicit 简化模式,则发送 accessToken 访问令牌,并重定向
 | 
			
		||||
        return success(getImplicitGrantRedirect());
 | 
			
		||||
        return success(getImplicitGrantRedirect(getLoginUserId(), client, redirectUri, state, approveScopes));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static OAuth2GrantTypeEnum getGrantTypeEnum(String responseType) {
 | 
			
		||||
@@ -148,12 +144,22 @@ public class OAuth2Controller {
 | 
			
		||||
        throw exception0(BAD_REQUEST.getCode(), "response_type 参数值允许 code 和 token");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getImplicitGrantRedirect() {
 | 
			
		||||
        return "";
 | 
			
		||||
    private String getImplicitGrantRedirect(Long userId, OAuth2ClientDO client,
 | 
			
		||||
                                            String redirectUri, String state, List<String> scopes) {
 | 
			
		||||
        OAuth2AccessTokenDO accessTokenDO = oAuth2GrantService.grantImplicit(userId, getUserType(), client.getClientId(), scopes);
 | 
			
		||||
        Assert.notNull(accessTokenDO, "访问令牌不能为空"); // 防御性检查
 | 
			
		||||
        // 拼接 URL
 | 
			
		||||
        // noinspection unchecked
 | 
			
		||||
        return OAuth2Utils.buildImplicitRedirectUri(redirectUri, accessTokenDO.getAccessToken(), state, accessTokenDO.getExpiresTime(),
 | 
			
		||||
                scopes, JsonUtils.parseObject(client.getAdditionalInformation(), Map.class));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getAuthorizationCodeRedirect() {
 | 
			
		||||
        return "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Integer getUserType() {
 | 
			
		||||
        return UserTypeEnum.ADMIN.getValue();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,13 +3,16 @@ package cn.iocoder.yudao.module.system.dal.dataobject.auth;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.KeySequence;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableField;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableId;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableName;
 | 
			
		||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * OAuth2 访问令牌 DO
 | 
			
		||||
@@ -55,6 +58,11 @@ public class OAuth2AccessTokenDO extends TenantBaseDO {
 | 
			
		||||
     * 关联 {@link OAuth2ClientDO#getId()}
 | 
			
		||||
     */
 | 
			
		||||
    private String clientId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 授权范围
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(typeHandler = JacksonTypeHandler.class)
 | 
			
		||||
    private List<String> scopes;
 | 
			
		||||
    /**
 | 
			
		||||
     * 过期时间
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -3,12 +3,15 @@ package cn.iocoder.yudao.module.system.dal.dataobject.auth;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.KeySequence;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableField;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableName;
 | 
			
		||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * OAuth2 刷新令牌
 | 
			
		||||
@@ -47,6 +50,11 @@ public class OAuth2RefreshTokenDO extends BaseDO {
 | 
			
		||||
     * 关联 {@link OAuth2ClientDO#getId()}
 | 
			
		||||
     */
 | 
			
		||||
    private String clientId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 授权范围
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(typeHandler = JacksonTypeHandler.class)
 | 
			
		||||
    private List<String> scopes;
 | 
			
		||||
    /**
 | 
			
		||||
     * 过期时间
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -207,7 +207,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
 | 
			
		||||
        createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS);
 | 
			
		||||
        // 创建访问令牌
 | 
			
		||||
        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, getUserType().getValue(),
 | 
			
		||||
                OAuth2ClientConstants.CLIENT_ID_DEFAULT);
 | 
			
		||||
                OAuth2ClientConstants.CLIENT_ID_DEFAULT, null);
 | 
			
		||||
        // 构建返回结果
 | 
			
		||||
        return AuthConvert.INSTANCE.convert(accessTokenDO);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.service.oauth2;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
@@ -181,7 +182,7 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService {
 | 
			
		||||
        if (client == null) {
 | 
			
		||||
            throw exception(OAUTH2_CLIENT_EXISTS);
 | 
			
		||||
        }
 | 
			
		||||
        if (Objects.equals(client.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
 | 
			
		||||
        if (ObjectUtil.notEqual(client.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
 | 
			
		||||
            throw exception(OAUTH2_CLIENT_DISABLE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.system.service.oauth2;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2AccessTokenDO;
 | 
			
		||||
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * OAuth2 授予 Service 接口
 | 
			
		||||
@@ -20,11 +20,11 @@ public interface OAuth2GrantService {
 | 
			
		||||
 | 
			
		||||
    // ImplicitTokenGranter
 | 
			
		||||
    OAuth2AccessTokenDO grantImplicit(Long userId, Integer userType,
 | 
			
		||||
                                      String clientId, Collection<String> scopes);
 | 
			
		||||
                                      String clientId, List<String> scopes);
 | 
			
		||||
 | 
			
		||||
    // AuthorizationCodeTokenGranter
 | 
			
		||||
    String grantAuthorizationCode(Long userId, Integer userType,
 | 
			
		||||
                                  String clientId, Collection<String> scopes,
 | 
			
		||||
                                  String clientId, List<String> scopes,
 | 
			
		||||
                                  String redirectUri, String state);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,9 @@ package cn.iocoder.yudao.module.system.service.oauth2;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2AccessTokenDO;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * OAuth2 授予 Service 实现类
 | 
			
		||||
@@ -13,15 +15,18 @@ import java.util.Collection;
 | 
			
		||||
@Service
 | 
			
		||||
public class OAuth2GrantServiceImpl implements OAuth2GrantService {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private OAuth2TokenService oauth2TokenService;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public OAuth2AccessTokenDO grantImplicit(Long userId, Integer userType,
 | 
			
		||||
                                             String clientId, Collection<String> scopes) {
 | 
			
		||||
        return null;
 | 
			
		||||
                                             String clientId, List<String> scopes) {
 | 
			
		||||
        return oauth2TokenService.createAccessToken(userId, userType, clientId, scopes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String grantAuthorizationCode(Long userId, Integer userType,
 | 
			
		||||
                                         String clientId, Collection<String> scopes,
 | 
			
		||||
                                         String clientId, List<String> scopes,
 | 
			
		||||
                                         String redirectUri, String state) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2AccessTokenDO;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * OAuth2.0 Token Service 接口
 | 
			
		||||
 *
 | 
			
		||||
@@ -22,9 +24,10 @@ public interface OAuth2TokenService {
 | 
			
		||||
     * @param userId 用户编号
 | 
			
		||||
     * @param userType 用户类型
 | 
			
		||||
     * @param clientId 客户端编号
 | 
			
		||||
     * @param scopes 授权范围
 | 
			
		||||
     * @return 访问令牌的信息
 | 
			
		||||
     */
 | 
			
		||||
    OAuth2AccessTokenDO createAccessToken(Long userId, Integer userType, String clientId);
 | 
			
		||||
    OAuth2AccessTokenDO createAccessToken(Long userId, Integer userType, String clientId, List<String> scopes);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 刷新访问令牌
 | 
			
		||||
 
 | 
			
		||||
@@ -45,10 +45,10 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional
 | 
			
		||||
    public OAuth2AccessTokenDO createAccessToken(Long userId, Integer userType, String clientId) {
 | 
			
		||||
    public OAuth2AccessTokenDO createAccessToken(Long userId, Integer userType, String clientId, List<String> scopes) {
 | 
			
		||||
        OAuth2ClientDO clientDO = oauth2ClientService.validOAuthClientFromCache(clientId);
 | 
			
		||||
        // 创建刷新令牌
 | 
			
		||||
        OAuth2RefreshTokenDO refreshTokenDO = createOAuth2RefreshToken(userId, userType, clientDO);
 | 
			
		||||
        OAuth2RefreshTokenDO refreshTokenDO = createOAuth2RefreshToken(userId, userType, clientDO, scopes);
 | 
			
		||||
        // 创建访问令牌
 | 
			
		||||
        return createOAuth2AccessToken(refreshTokenDO, clientDO);
 | 
			
		||||
    }
 | 
			
		||||
@@ -134,7 +134,8 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
 | 
			
		||||
 | 
			
		||||
    private OAuth2AccessTokenDO createOAuth2AccessToken(OAuth2RefreshTokenDO refreshTokenDO, OAuth2ClientDO clientDO) {
 | 
			
		||||
        OAuth2AccessTokenDO accessTokenDO = new OAuth2AccessTokenDO().setAccessToken(generateAccessToken())
 | 
			
		||||
                .setUserId(refreshTokenDO.getUserId()).setUserType(refreshTokenDO.getUserType()).setClientId(clientDO.getClientId())
 | 
			
		||||
                .setUserId(refreshTokenDO.getUserId()).setUserType(refreshTokenDO.getUserType())
 | 
			
		||||
                .setClientId(clientDO.getClientId()).setScopes(refreshTokenDO.getScopes())
 | 
			
		||||
                .setRefreshToken(refreshTokenDO.getRefreshToken())
 | 
			
		||||
                .setExpiresTime(DateUtils.addDate(Calendar.SECOND, clientDO.getAccessTokenValiditySeconds()));
 | 
			
		||||
        accessTokenDO.setTenantId(TenantContextHolder.getTenantId()); // 手动设置租户编号,避免缓存到 Redis 的时候,无对应的租户编号
 | 
			
		||||
@@ -144,9 +145,10 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
 | 
			
		||||
        return accessTokenDO;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private OAuth2RefreshTokenDO createOAuth2RefreshToken(Long userId, Integer userType, OAuth2ClientDO clientDO) {
 | 
			
		||||
    private OAuth2RefreshTokenDO createOAuth2RefreshToken(Long userId, Integer userType, OAuth2ClientDO clientDO, List<String> scopes) {
 | 
			
		||||
        OAuth2RefreshTokenDO refreshToken = new OAuth2RefreshTokenDO().setRefreshToken(generateRefreshToken())
 | 
			
		||||
                .setUserId(userId).setUserType(userType).setClientId(clientDO.getClientId())
 | 
			
		||||
                .setUserId(userId).setUserType(userType)
 | 
			
		||||
                .setClientId(clientDO.getClientId()).setScopes(scopes)
 | 
			
		||||
                .setExpiresTime(DateUtils.addDate(Calendar.SECOND, clientDO.getRefreshTokenValiditySeconds()));
 | 
			
		||||
        oauth2RefreshTokenMapper.insert(refreshToken);
 | 
			
		||||
        return refreshToken;
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,56 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.util.oauth2;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
 | 
			
		||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * OAuth2 相关的工具类
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
public class OAuth2Utils {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 构建简化模式下,重定向的 URI
 | 
			
		||||
     *
 | 
			
		||||
     * copy from Spring Security OAuth2 的 AuthorizationEndpoint 类的 appendAccessToken 方法
 | 
			
		||||
     *
 | 
			
		||||
     * @param redirectUri 重定向 URI
 | 
			
		||||
     * @param accessToken 访问令牌
 | 
			
		||||
     * @param state 状态
 | 
			
		||||
     * @param expireTime 过期时间
 | 
			
		||||
     * @param scopes 授权范围
 | 
			
		||||
     * @param additionalInformation 附加信息
 | 
			
		||||
     * @return 简化授权模式下的重定向 URI
 | 
			
		||||
     */
 | 
			
		||||
    public static String buildImplicitRedirectUri(String redirectUri, String accessToken, String state, Date expireTime,
 | 
			
		||||
                                                  Collection<String> scopes, Map<String, Object> additionalInformation) {
 | 
			
		||||
        Map<String, Object> vars = new LinkedHashMap<String, Object>();
 | 
			
		||||
        Map<String, String> keys = new HashMap<String, String>();
 | 
			
		||||
        vars.put("access_token", accessToken);
 | 
			
		||||
        vars.put("token_type", SecurityFrameworkUtils.TOKEN_TYPE.toLowerCase());
 | 
			
		||||
        if (state != null) {
 | 
			
		||||
            vars.put("state", state);
 | 
			
		||||
        }
 | 
			
		||||
        if (expireTime != null) {
 | 
			
		||||
            long expires_in = (expireTime.getTime() - System.currentTimeMillis()) / 1000;
 | 
			
		||||
            vars.put("expires_in", expires_in);
 | 
			
		||||
        }
 | 
			
		||||
        if (CollUtil.isNotEmpty(scopes)) {
 | 
			
		||||
            vars.put("scope", CollUtil.join(scopes, " "));
 | 
			
		||||
        }
 | 
			
		||||
        for (String key : additionalInformation.keySet()) {
 | 
			
		||||
            Object value = additionalInformation.get(key);
 | 
			
		||||
            if (value != null) {
 | 
			
		||||
                keys.put("extra_" + key, key);
 | 
			
		||||
                vars.put("extra_" + key, value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Do not include the refresh token (even if there is one)
 | 
			
		||||
        return HttpUtils.append(redirectUri, vars, keys, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user