mirror of
https://gitee.com/log4j/pig.git
synced 2024-12-31 08:14:18 +08:00
♻️ Refactoring code. close #I5A40W PigRedisOAuth2AuthorizationService 重写
This commit is contained in:
parent
41de38c39a
commit
b6c97c6132
@ -21,8 +21,8 @@ import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.pig4cloud.pig.admin.api.entity.SysOauthClientDetails;
|
||||
import com.pig4cloud.pig.admin.api.feign.RemoteClientDetailsService;
|
||||
import com.pig4cloud.pig.auth.support.OAuth2EndpointUtils;
|
||||
import com.pig4cloud.pig.auth.support.OAuth2ErrorCodesExpand;
|
||||
import com.pig4cloud.pig.common.security.util.OAuth2EndpointUtils;
|
||||
import com.pig4cloud.pig.common.security.util.OAuth2ErrorCodesExpand;
|
||||
import com.pig4cloud.pig.common.core.constant.CacheConstants;
|
||||
import com.pig4cloud.pig.common.core.constant.CommonConstants;
|
||||
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.pig4cloud.pig.auth.support;
|
||||
|
||||
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.ClaimAccessor;
|
||||
@ -86,9 +85,8 @@ public class CustomeOAuth2AccessTokenGenerator implements OAuth2TokenGenerator<O
|
||||
OAuth2TokenClaimsSet accessTokenClaimsSet = claimsBuilder.build();
|
||||
|
||||
// 组装key PIG:client:username:uuid
|
||||
String key = String.format("%s:%s:%s:%s", SecurityConstants.PROJECT_PREFIX,
|
||||
SecurityContextHolder.getContext().getAuthentication().getPrincipal(), context.getPrincipal().getName(),
|
||||
UUID.randomUUID());
|
||||
String key = String.format("%s::%s::%s", SecurityContextHolder.getContext().getAuthentication().getPrincipal(),
|
||||
context.getPrincipal().getName(), UUID.randomUUID());
|
||||
|
||||
OAuth2AccessToken accessToken = new CustomeOAuth2AccessTokenGenerator.OAuth2AccessTokenClaims(
|
||||
OAuth2AccessToken.TokenType.BEARER, key, accessTokenClaimsSet.getIssuedAt(),
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.pig4cloud.pig.auth.support;
|
||||
|
||||
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
|
||||
import com.pig4cloud.pig.common.security.util.OAuth2EndpointUtils;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.pig4cloud.pig.auth.support;
|
||||
|
||||
import com.pig4cloud.pig.common.security.util.OAuth2ErrorCodesExpand;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.context.support.MessageSourceAccessor;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.pig4cloud.pig.auth.support;
|
||||
|
||||
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
|
||||
import com.pig4cloud.pig.common.security.util.OAuth2EndpointUtils;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.pig4cloud.pig.auth.support;
|
||||
|
||||
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
|
||||
import com.pig4cloud.pig.common.security.util.OAuth2ErrorCodesExpand;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.context.support.MessageSourceAccessor;
|
||||
|
@ -6,40 +6,44 @@ import org.springframework.security.oauth2.server.authorization.OAuth2Authorizat
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class PigRedisOAuth2AuthorizationConsentService implements OAuth2AuthorizationConsentService {
|
||||
|
||||
private final RedisTemplate<String, String> redisTemplate;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
private final static Long TIMEOUT = 10L;
|
||||
|
||||
@Override
|
||||
public void save(OAuth2AuthorizationConsent authorizationConsent) {
|
||||
Assert.notNull(authorizationConsent, "authorizationConsent cannot be null");
|
||||
redisTemplate.opsForHash().put(buildKey(authorizationConsent), authorizationConsent.getRegisteredClientId(), authorizationConsent);
|
||||
|
||||
redisTemplate.opsForValue().set(buildKey(authorizationConsent), authorizationConsent, TIMEOUT,
|
||||
TimeUnit.MINUTES);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(OAuth2AuthorizationConsent authorizationConsent) {
|
||||
Assert.notNull(authorizationConsent, "authorizationConsent cannot be null");
|
||||
redisTemplate.opsForHash().delete(buildKey(authorizationConsent), authorizationConsent.getRegisteredClientId());
|
||||
redisTemplate.delete(buildKey(authorizationConsent));
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2AuthorizationConsent findById(String registeredClientId, String principalName) {
|
||||
Assert.hasText(registeredClientId, "registeredClientId cannot be empty");
|
||||
Assert.hasText(principalName, "principalName cannot be empty");
|
||||
return (OAuth2AuthorizationConsent) redisTemplate.opsForHash().get(buildKey(registeredClientId, principalName), registeredClientId);
|
||||
return (OAuth2AuthorizationConsent) redisTemplate.opsForValue()
|
||||
.get(buildKey(registeredClientId, principalName));
|
||||
}
|
||||
|
||||
|
||||
private static String buildKey(String registeredClientId, String principalName) {
|
||||
return "OAC::" + registeredClientId + "::" + principalName;
|
||||
return "token:consent:" + registeredClientId + ":" + principalName;
|
||||
}
|
||||
|
||||
private static String buildKey(OAuth2AuthorizationConsent authorizationConsent) {
|
||||
return buildKey(authorizationConsent.getRegisteredClientId(), authorizationConsent.getPrincipalName());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -7,10 +7,17 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthorizationCode;
|
||||
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenType;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2022/5/27
|
||||
@ -18,81 +25,110 @@ import org.springframework.util.Assert;
|
||||
@RequiredArgsConstructor
|
||||
public class PigRedisOAuth2AuthorizationService implements OAuth2AuthorizationService {
|
||||
|
||||
private final static Long TIMEOUT = 10L;
|
||||
|
||||
private static final String AUTHORIZATION = "token";
|
||||
|
||||
private final RedisTemplate<String, String> redisTemplate;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Override
|
||||
public void save(OAuth2Authorization authorization) {
|
||||
Assert.notNull(authorization, "authorization cannot be null");
|
||||
redisTemplate.opsForHash().put(AUTHORIZATION, authorization.getId(), authorization);
|
||||
|
||||
if (isState(authorization)) {
|
||||
String token = authorization.getAttribute("state");
|
||||
redisTemplate.opsForValue().set(buildKey(OAuth2ParameterNames.STATE, token), authorization, TIMEOUT,
|
||||
TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
if (isCode(authorization)) {
|
||||
OAuth2Authorization.Token<OAuth2AuthorizationCode> authorizationCode = authorization
|
||||
.getToken(OAuth2AuthorizationCode.class);
|
||||
OAuth2AuthorizationCode authorizationCodeToken = authorizationCode.getToken();
|
||||
long between = ChronoUnit.MINUTES.between(authorizationCodeToken.getIssuedAt(),
|
||||
authorizationCodeToken.getExpiresAt());
|
||||
redisTemplate.opsForValue().set(buildKey(OAuth2ParameterNames.CODE, authorizationCodeToken.getTokenValue()),
|
||||
authorization, between, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
if (isRefreshToken(authorization)) {
|
||||
OAuth2RefreshToken refreshToken = authorization.getRefreshToken().getToken();
|
||||
long between = ChronoUnit.SECONDS.between(refreshToken.getIssuedAt(), refreshToken.getExpiresAt());
|
||||
redisTemplate.opsForValue().set(buildKey(OAuth2ParameterNames.REFRESH_TOKEN, refreshToken.getTokenValue()),
|
||||
authorization, between, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (isAccessToken(authorization)) {
|
||||
OAuth2AccessToken accessToken = authorization.getAccessToken().getToken();
|
||||
long between = ChronoUnit.SECONDS.between(accessToken.getIssuedAt(), accessToken.getExpiresAt());
|
||||
redisTemplate.opsForValue().set(buildKey(OAuth2ParameterNames.ACCESS_TOKEN, accessToken.getTokenValue()),
|
||||
authorization, between, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(OAuth2Authorization authorization) {
|
||||
Assert.notNull(authorization, "authorization cannot be null");
|
||||
redisTemplate.opsForHash().delete(AUTHORIZATION, authorization.getId());
|
||||
|
||||
List<String> keys = new ArrayList<>();
|
||||
if (isState(authorization)) {
|
||||
String token = authorization.getAttribute("state");
|
||||
keys.add(buildKey(OAuth2ParameterNames.STATE, token));
|
||||
}
|
||||
|
||||
if (isCode(authorization)) {
|
||||
OAuth2Authorization.Token<OAuth2AuthorizationCode> authorizationCode = authorization
|
||||
.getToken(OAuth2AuthorizationCode.class);
|
||||
OAuth2AuthorizationCode authorizationCodeToken = authorizationCode.getToken();
|
||||
keys.add(buildKey(OAuth2ParameterNames.CODE, authorizationCodeToken.getTokenValue()));
|
||||
}
|
||||
|
||||
if (isRefreshToken(authorization)) {
|
||||
OAuth2RefreshToken refreshToken = authorization.getRefreshToken().getToken();
|
||||
keys.add(buildKey(OAuth2ParameterNames.REFRESH_TOKEN, refreshToken.getTokenValue()));
|
||||
}
|
||||
|
||||
if (isAccessToken(authorization)) {
|
||||
OAuth2AccessToken accessToken = authorization.getAccessToken().getToken();
|
||||
keys.add(buildKey(OAuth2ParameterNames.ACCESS_TOKEN, accessToken.getTokenValue()));
|
||||
}
|
||||
redisTemplate.delete(keys);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public OAuth2Authorization findById(String id) {
|
||||
Assert.hasText(id, "id cannot be empty");
|
||||
return (OAuth2Authorization) redisTemplate.opsForHash().get(AUTHORIZATION, id);
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public OAuth2Authorization findByToken(String token, @Nullable OAuth2TokenType tokenType) {
|
||||
Assert.hasText(token, "token cannot be empty");
|
||||
for (Object authorization : redisTemplate.opsForHash().values(AUTHORIZATION)) {
|
||||
if (hasToken((OAuth2Authorization) authorization, token, tokenType)) {
|
||||
return (OAuth2Authorization) authorization;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
Assert.notNull(tokenType, "tokenType cannot be empty");
|
||||
return (OAuth2Authorization) redisTemplate.opsForValue().get(buildKey(tokenType.getValue(), token));
|
||||
}
|
||||
|
||||
private static boolean hasToken(OAuth2Authorization authorization, String token,
|
||||
@Nullable OAuth2TokenType tokenType) {
|
||||
if (tokenType != null) {
|
||||
if ("state".equals(tokenType.getValue())) {
|
||||
return matchesState(authorization, token);
|
||||
}
|
||||
else if ("code".equals(tokenType.getValue())) {
|
||||
return matchesAuthorizationCode(authorization, token);
|
||||
}
|
||||
else if (OAuth2TokenType.ACCESS_TOKEN.equals(tokenType)) {
|
||||
return matchesAccessToken(authorization, token);
|
||||
}
|
||||
else {
|
||||
return OAuth2TokenType.REFRESH_TOKEN.equals(tokenType) && matchesRefreshToken(authorization, token);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return matchesState(authorization, token) || matchesAuthorizationCode(authorization, token)
|
||||
|| matchesAccessToken(authorization, token) || matchesRefreshToken(authorization, token);
|
||||
}
|
||||
private String buildKey(String type, String id) {
|
||||
return String.format("%s::%s::%s", AUTHORIZATION, type, id);
|
||||
}
|
||||
|
||||
private static boolean matchesState(OAuth2Authorization authorization, String token) {
|
||||
return token.equals(authorization.getAttribute("state"));
|
||||
private static boolean isState(OAuth2Authorization authorization) {
|
||||
return Objects.nonNull(authorization.getAttribute("state"));
|
||||
}
|
||||
|
||||
private static boolean matchesAuthorizationCode(OAuth2Authorization authorization, String token) {
|
||||
private static boolean isCode(OAuth2Authorization authorization) {
|
||||
OAuth2Authorization.Token<OAuth2AuthorizationCode> authorizationCode = authorization
|
||||
.getToken(OAuth2AuthorizationCode.class);
|
||||
return authorizationCode != null && authorizationCode.getToken().getTokenValue().equals(token);
|
||||
return Objects.nonNull(authorizationCode);
|
||||
}
|
||||
|
||||
private static boolean matchesAccessToken(OAuth2Authorization authorization, String token) {
|
||||
OAuth2Authorization.Token<OAuth2AccessToken> accessToken = authorization.getToken(OAuth2AccessToken.class);
|
||||
return accessToken != null && accessToken.getToken().getTokenValue().equals(token);
|
||||
private static boolean isRefreshToken(OAuth2Authorization authorization) {
|
||||
return Objects.nonNull(authorization.getRefreshToken());
|
||||
}
|
||||
|
||||
private static boolean matchesRefreshToken(OAuth2Authorization authorization, String token) {
|
||||
OAuth2Authorization.Token<OAuth2RefreshToken> refreshToken = authorization.getToken(OAuth2RefreshToken.class);
|
||||
return refreshToken != null && refreshToken.getToken().getTokenValue().equals(token);
|
||||
private static boolean isAccessToken(OAuth2Authorization authorization) {
|
||||
return Objects.nonNull(authorization.getAccessToken());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.pig4cloud.pig.auth.support;
|
||||
package com.pig4cloud.pig.common.security.util;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.springframework.security.oauth2.core.*;
|
||||
@ -21,7 +21,7 @@ import java.util.Map;
|
||||
@UtilityClass
|
||||
public class OAuth2EndpointUtils {
|
||||
|
||||
static final String ACCESS_TOKEN_REQUEST_ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";
|
||||
public final String ACCESS_TOKEN_REQUEST_ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";
|
||||
|
||||
public MultiValueMap<String, String> getParameters(HttpServletRequest request) {
|
||||
Map<String, String[]> parameterMap = request.getParameterMap();
|
@ -1,4 +1,4 @@
|
||||
package com.pig4cloud.pig.auth.support;
|
||||
package com.pig4cloud.pig.common.security.util;
|
||||
|
||||
/**
|
||||
* @author jumuning
|
Loading…
Reference in New Issue
Block a user