All Downloads are FREE. Search and download functionalities are using the official Maven repository.

plus.easydo.starter.oauth.server.service.CustomizeAuthorizationCodeServices Maven / Gradle / Ivy

The newest version!
package plus.easydo.starter.oauth.server.service;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.security.oauth2.common.util.SerializationUtils;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import plus.easydo.starter.oauth.server.model.OauthCode;
import plus.easydo.starter.oauth.server.properties.Oauth2ServerProperties;
import plus.easydo.starter.oauth.server.serializer.FastJsonRedisTokenStoreSerializationStrategy;
import plus.easydo.starter.redis.service.RedisService;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 实现AuthorizationCodeServices
 * 自定义code授权码流程
 * 使用redis存储
 * @author yuzhanfeng
 */
@EnableConfigurationProperties(Oauth2ServerProperties.class)
@Configuration
public class CustomizeAuthorizationCodeServices implements AuthorizationCodeServices {


    /**
     * 自定义授权码长度,默认为12位,
     */
    private final RandomValueStringGenerator randomValueStringGenerator = new RandomValueStringGenerator(12);
    private final FastJsonRedisTokenStoreSerializationStrategy serializations
            = new FastJsonRedisTokenStoreSerializationStrategy<>(OAuth2Authentication.class);

/* @Bean
 public RandomValueStringGenerator randomValueStringGenerator(){
     return new RandomValueStringGenerator(oAuth2Properties.getOauthCodeLength());
 }*/
    @Resource
    Oauth2ServerProperties oAuth2Properties;
    /**
     * 使用redis存储代替数据库存储
     */
    @Resource
    RedisService redisService;

    /**
     * 创建授权码
     * @param oAuth2Authentication 身份认证
     * @return String
     */
    @Override
    public String createAuthorizationCode(OAuth2Authentication oAuth2Authentication) {
        String clientId = oAuth2Authentication.getOAuth2Request().getClientId();
        return saveCode(clientId, oAuth2Authentication);
    }


    /**
     * 使用授权码
     * @param code 授权码
     * @return OAuth2Authentication 身份认证
     */
    @Override
    public OAuth2Authentication consumeAuthorizationCode(String code){
        String oauthCodePrefix = oAuth2Properties.getOauthCodePrefix();
        OauthCode oauthCode = redisService.getCacheObject(oauthCodePrefix + code);
        if(oauthCode != null){
            remove(code,oauthCode.getClientId());
            //反序列化为OAuth2Authentication并返回
            if(oAuth2Properties.isEnableFastJsonSerializer()){
                return (OAuth2Authentication) serializations.deserialize(oauthCode.getAuthentication(),OAuth2Authentication.class);
            }else {
                return SerializationUtils.deserialize(oauthCode.getAuthentication());
            }
        }else {
            throw new InvalidGrantException("授权码无效: " + code);
        }
    }


    /**
     * 存储授权码
     * @param oAuth2Authentication oAuth2Authentication
     */
    private String saveCode(String clientId, OAuth2Authentication oAuth2Authentication) {
        String codeClientPrefix = oAuth2Properties.getCodeClientPrefix();
        String oauthCodePrefix = oAuth2Properties.getOauthCodePrefix();
        String cacheCode = validatorClientIdCode(clientId,codeClientPrefix,oauthCodePrefix);
        if (cacheCode != null) {
            return cacheCode;
        }
        /*初始化一个自定义的code对象*/
        String code = randomValueStringGenerator.generate();
        OauthCode oauthCode = new OauthCode();
        oauthCode.setClientId(clientId);
        oauthCode.setCode(code);
        /*将oAuth2Authentication序列化为byte*/
        if (oAuth2Properties.isEnableFastJsonSerializer()) {
            //noinspection unchecked
            oauthCode.setAuthentication(serializations.serialize(oAuth2Authentication));
        } else {
            oauthCode.setAuthentication(SerializationUtils.serialize(oAuth2Authentication));
        }
        /*存储一份客户端凭证,用于校验是否已存在code但未消费*/
        redisService.setCacheObject(codeClientPrefix + clientId, code);
        redisService.expire(codeClientPrefix + clientId, 5, TimeUnit.MINUTES);
        /*存储code 设置有效时间*/
        redisService.setCacheObject(oauthCodePrefix + code, oauthCode);
        redisService.expire(oauthCodePrefix + code, 5, TimeUnit.MINUTES);
        return code;
    }


    /**
     * 删除授权码
     * @param code 授权码
     * @param clientId 客户端id
     */
    private void remove(String code, String clientId){
        /*删除code*/
        redisService.deleteObject(oAuth2Properties.getOauthCodePrefix() +code);
        /*删除用于校验code的客户端信息*/
        redisService.deleteObject(oAuth2Properties.getCodeClientPrefix() +clientId);
    }

    /**
     * 根据clientId判断是否已经授权过code但未消费,
     *  如果存在则续期,防止无限获取授权码导致redis内存占用过高
     * @param clientId 客户端id
     * @return 结果
     */
    private String validatorClientIdCode(String clientId, String codeClientPrefix, String oauthCodePrefix) {
        String cacheCode = redisService.getCacheObject(codeClientPrefix + clientId);
        if (cacheCode != null) {
            OauthCode oauthCode =  redisService.getCacheObject(oauthCodePrefix + cacheCode);
            if (oauthCode != null) {
                /*续期客户端凭证*/
                redisService.expire(codeClientPrefix + clientId,5,TimeUnit.MINUTES);
                /*续期code*/
                redisService.expire(oauthCodePrefix + cacheCode,5,TimeUnit.MINUTES);
                return oauthCode.getCode();
            }
        }
        return null;
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy