优化授权码模式

This commit is contained in:
zhuyijun 2022-10-15 21:21:22 +08:00
parent ed9885bf85
commit b2ee0701e1
8 changed files with 49 additions and 35 deletions

View File

@ -73,9 +73,12 @@ public class AuthFilter implements GlobalFilter {
if (isWhileList(path)) { if (isWhileList(path)) {
return chain.filter(exchange); return chain.filter(exchange);
} }
if (token == null || StringUtils.isEmpty(token) || !token.startsWith(HttpHeaderConstant.AUTHORIZATION_TYPE)) { if (token == null || StringUtils.isEmpty(token)) {
return getErrorMono(response, HttpCode.UNAUTHORIZED, "无访问权限"); return getErrorMono(response, HttpCode.UNAUTHORIZED, "无访问权限");
} }
if (!token.toLowerCase().startsWith(HttpHeaderConstant.BEARER_TYPE.toLowerCase())) {
return getErrorMono(response, HttpCode.UNAUTHORIZED, "令牌格式有误");
}
if (isExpired(token)) { if (isExpired(token)) {
log.info("token过期"); log.info("token过期");
return getErrorMono(response, HttpCode.UNAUTHORIZED, "token失效"); return getErrorMono(response, HttpCode.UNAUTHORIZED, "token失效");
@ -103,7 +106,7 @@ public class AuthFilter implements GlobalFilter {
* @date 2021/11/15 19:17 * @date 2021/11/15 19:17
*/ */
private boolean isExpired(String token) { private boolean isExpired(String token) {
String jwt = token.replace(HttpHeaderConstant.AUTHORIZATION_TYPE, "").trim(); String jwt = token.substring(HttpHeaderConstant.BEARER_TYPE.length()).trim();
try { try {
JwtParsers jwtParsers = new JwtParsers(true); JwtParsers jwtParsers = new JwtParsers(true);
if (rsaKeyProperties.getEnable()) { if (rsaKeyProperties.getEnable()) {

View File

@ -7,8 +7,6 @@ import org.springframework.security.oauth2.common.exceptions.InvalidGrantExcepti
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStoreSerializationStrategy;
/** /**
* @author zhuyijun * @author zhuyijun
@ -23,8 +21,7 @@ public class OauthAuthorizationCodeServices implements AuthorizationCodeServices
/** /**
* 生成随机字符的类 * 生成随机字符的类
*/ */
private RandomValueStringGenerator generator = new RandomValueStringGenerator(10); private RandomValueStringGenerator generator = new RandomValueStringGenerator(16);
private RedisTokenStoreSerializationStrategy serializationStrategy = new JdkSerializationStrategy();
/** /**
* @description 生成授权码的方法 * @description 生成授权码的方法
@ -47,7 +44,9 @@ public class OauthAuthorizationCodeServices implements AuthorizationCodeServices
@SneakyThrows @SneakyThrows
@Override @Override
public OAuth2Authentication consumeAuthorizationCode(String code) throws InvalidGrantException { public OAuth2Authentication consumeAuthorizationCode(String code) throws InvalidGrantException {
return redisTemplateHandler.<String, OAuth2Authentication>hGet(CommonRedisKeyConstant.AUTHORIZATION_CODE, code); OAuth2Authentication oAuth2Authentication = redisTemplateHandler.<String, OAuth2Authentication>hGet(CommonRedisKeyConstant.AUTHORIZATION_CODE, code);
redisTemplateHandler.hDelete(CommonRedisKeyConstant.AUTHORIZATION_CODE, code);
return oAuth2Authentication;
} }

View File

@ -11,14 +11,16 @@ public class AuthorizationCodeDto {
@ApiModelProperty(value = "作用范围", dataType = "String", example = "all") @ApiModelProperty(value = "作用范围", dataType = "String", example = "all")
private String scope; private String scope;
@ApiModelProperty(value = "回调地址", dataType = "String", example = "all") @ApiModelProperty(value = "回调地址", dataType = "String", example = "all")
private String redirectUrl; private String redirect_uri;
@ApiModelProperty(value = "客户端id", dataType = "String", example = "all") @ApiModelProperty(value = "客户端id", dataType = "String", example = "all")
private String clientId; private String client_id;
@ApiModelProperty(value = "客户端密码", dataType = "String", example = "all") @ApiModelProperty(value = "客户端密码", dataType = "String", example = "all")
private String clientSecret; private String client_secret;
@ApiModelProperty(value = "返回类型 code token", dataType = "String", example = "all") @ApiModelProperty(value = "响应体类型 code token", dataType = "String", example = "code token")
private String responseType; private String response_type;
@ApiModelProperty(value = "", dataType = "String", example = "")
private String state; private String state;
private Boolean isApproved; @ApiModelProperty(value = "允许或拒绝 true 或false", dataType = "String", example = "true")
private String user_oauth_approval;
} }

View File

@ -101,7 +101,7 @@ public class AuthServiceImpl implements AuthService {
@Override @Override
public String getAuthorizationCode(AuthorizationCodeDto authorizationCodeDto) { public String getAuthorizationCode(AuthorizationCodeDto authorizationCodeDto) {
String responseType = authorizationCodeDto.getResponseType(); String responseType = authorizationCodeDto.getResponse_type();
if (!StringUtils.hasLength(responseType)) { if (!StringUtils.hasLength(responseType)) {
throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "responseType不能为空"); throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "responseType不能为空");
} }
@ -109,23 +109,34 @@ public class AuthServiceImpl implements AuthService {
if (!responseTypes.contains("token") && !responseTypes.contains("code")) { if (!responseTypes.contains("token") && !responseTypes.contains("code")) {
throw new UnsupportedResponseTypeException("Unsupported response types: " + responseTypes); throw new UnsupportedResponseTypeException("Unsupported response types: " + responseTypes);
} }
ClientDetails clientDetail = this.clientDetails.loadClientByClientId(authorizationCodeDto.getClient_id());
ClientDetails clientDetail = this.clientDetails.loadClientByClientId(authorizationCodeDto.getClientId());
if (clientDetail == null) { if (clientDetail == null) {
throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "无此客户端"); throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "无此客户端");
} }
// if (!passwordEncoder.matches(clientDetail.getClientSecret(), authorizationCodeDto.getClientSecret())) { if (!passwordEncoder.matches(authorizationCodeDto.getClient_secret(), clientDetail.getClientSecret())) {
// throw new AuthRuntimeException(HttpCode.UNAUTHORIZED, "客户端" + authorizationCodeDto.getClientId() + "认证失败"); throw new AuthRuntimeException(HttpCode.UNAUTHORIZED, "客户端" + authorizationCodeDto.getClient_id() + "认证失败");
// } }
Map<String, String> parameters = new HashMap<>(); Map<String, String> parameters = new HashMap<>(16);
parameters.put(OAuth2Utils.CLIENT_ID, authorizationCodeDto.getClientId()); parameters.put(OAuth2Utils.CLIENT_ID, authorizationCodeDto.getClient_id());
parameters.put("client_secret", authorizationCodeDto.getClientSecret()); parameters.put("client_secret", authorizationCodeDto.getClient_secret());
parameters.put(OAuth2Utils.REDIRECT_URI, authorizationCodeDto.getRedirectUrl()); if (StringUtils.hasLength(authorizationCodeDto.getRedirect_uri())) {
parameters.put(OAuth2Utils.REDIRECT_URI, authorizationCodeDto.getRedirect_uri());
} else {
Set<String> registeredRedirectUri = clientDetail.getRegisteredRedirectUri();
if (CollectionUtils.isEmpty(registeredRedirectUri)) {
throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "redirect_uri回调地址不能为空");
}
parameters.put(OAuth2Utils.REDIRECT_URI, registeredRedirectUri.toArray()[0].toString());
}
parameters.put(OAuth2Utils.RESPONSE_TYPE, "code"); parameters.put(OAuth2Utils.RESPONSE_TYPE, "code");
parameters.put(OAuth2Utils.SCOPE, authorizationCodeDto.getScope()); parameters.put(OAuth2Utils.SCOPE, authorizationCodeDto.getScope());
parameters.put(OAuth2Utils.STATE, authorizationCodeDto.getState()); parameters.put(OAuth2Utils.STATE, authorizationCodeDto.getState());
parameters.put(OAuth2Utils.USER_OAUTH_APPROVAL, authorizationCodeDto.getUser_oauth_approval());
AuthorizationRequest authorizationRequest = createAuthorizationRequest(parameters, clientDetail); AuthorizationRequest authorizationRequest = createAuthorizationRequest(parameters, clientDetail);
if (!authorizationCodeDto.getIsApproved()) { String flag = parameters.get(OAuth2Utils.USER_OAUTH_APPROVAL);
boolean isApproved = "true".equalsIgnoreCase(flag);
authorizationRequest.setApproved(isApproved);
if (!isApproved) {
return getUnsuccessfulRedirect(authorizationRequest, return getUnsuccessfulRedirect(authorizationRequest,
new UserDeniedAuthorizationException("User denied access"), false); new UserDeniedAuthorizationException("User denied access"), false);
} }

View File

@ -49,18 +49,18 @@ public class LoginServiceImpl implements LoginService {
@Override @Override
public OAuth2AccessTokenVo login(UserLoginDto userLoginDto) { public OAuth2AccessTokenVo login(UserLoginDto userLoginDto) {
Map<String, String> parameters = BeanUtils.map(userLoginDto, Map.class); Map<String, String> parameters = BeanUtils.map(userLoginDto, Map.class);
parameters.put("username",userLoginDto.getUserIdentification()); parameters.put("username", userLoginDto.getUserIdentification());
parameters.put("password",userLoginDto.getPwdOrVerifyCode()); parameters.put("password", userLoginDto.getPwdOrVerifyCode());
parameters.put("grant_type", "password"); parameters.put("grant_type", "password");
ClientDetails authenticatedClient = clientDetails.loadClientByClientId(clientId); ClientDetails authenticatedClient = clientDetails.loadClientByClientId(clientId);
if (authenticatedClient == null) { if (authenticatedClient == null) {
throw new AuthRuntimeException(HttpCode.INTERNAL_SERVER_ERROR, "客户端获取token失败"); throw new AuthRuntimeException(HttpCode.INTERNAL_SERVER_ERROR, "客户端获取token失败");
} }
try{ try {
TokenRequest tokenRequest = oAuth2RequestFactory.createTokenRequest(parameters, authenticatedClient); TokenRequest tokenRequest = oAuth2RequestFactory.createTokenRequest(parameters, authenticatedClient);
OAuth2AccessToken token = tokenGranter.grant(tokenRequest.getGrantType(), tokenRequest); OAuth2AccessToken token = tokenGranter.grant(tokenRequest.getGrantType(), tokenRequest);
return OAuth2AccessTokenVo.TransferToken(token); return OAuth2AccessTokenVo.TransferToken(token);
}catch (Exception e){ } catch (Exception e) {
throw new AuthRuntimeException(HttpCode.INTERNAL_SERVER_ERROR, e.getMessage()); throw new AuthRuntimeException(HttpCode.INTERNAL_SERVER_ERROR, e.getMessage());
} }
} }
@ -71,7 +71,7 @@ public class LoginServiceImpl implements LoginService {
if (StringUtils.isEmpty(token)) { if (StringUtils.isEmpty(token)) {
return; return;
} }
token = token.replace(HttpHeaderConstant.AUTHORIZATION_TYPE, "").trim(); token = token.substring(HttpHeaderConstant.BEARER_TYPE.length()).trim();
OAuth2AccessToken oAuth2AccessToken = new DefaultOAuth2AccessToken(token); OAuth2AccessToken oAuth2AccessToken = new DefaultOAuth2AccessToken(token);
tokenStore.removeAccessToken(oAuth2AccessToken); tokenStore.removeAccessToken(oAuth2AccessToken);
} }

View File

@ -2,7 +2,7 @@ package cn.zyjblogs.starter.common.entity.constant;
public class HttpHeaderConstant { public class HttpHeaderConstant {
public static final String AUTHORIZATION = "Authorization"; public static final String AUTHORIZATION = "Authorization";
public static final String AUTHORIZATION_TYPE = "Bearer"; public static final String BEARER_TYPE = "Bearer";
public static final String LANGUAGE = "istorm-language"; public static final String LANGUAGE = "istorm-language";
public static final String REQUEST_FROM_GATEWAY_KEY = "request-from-istorm-gateway"; public static final String REQUEST_FROM_GATEWAY_KEY = "request-from-istorm-gateway";
public static final String REQUEST_FROM_GATEWAY_VALUE = "yes"; public static final String REQUEST_FROM_GATEWAY_VALUE = "yes";

View File

@ -35,8 +35,8 @@ public class OauthFeignInterceptorAutoConfiguration {
* @date 2022/03/12 * @date 2022/03/12
*/ */
private String tokenCompletion(String token) { private String tokenCompletion(String token) {
if (token.indexOf(HttpHeaderConstant.AUTHORIZATION_TYPE) != 0) { if (token.indexOf(HttpHeaderConstant.BEARER_TYPE) != 0) {
token = HttpHeaderConstant.AUTHORIZATION_TYPE + " " + token; token = HttpHeaderConstant.BEARER_TYPE + " " + token;
} }
return token; return token;
} }

View File

@ -83,11 +83,10 @@ public class RabbitMqAutoConfiguration {
* @date 2021/11/12 9:17 * @date 2021/11/12 9:17
*/ */
private void setContext(String authorization) { private void setContext(String authorization) {
String type = HttpHeaderConstant.AUTHORIZATION_TYPE; if (!authorization.toLowerCase().startsWith(HttpHeaderConstant.BEARER_TYPE.toLowerCase())) {
if (!authorization.startsWith(type)) {
return; return;
} }
String token = authorization.replace(HttpHeaderConstant.AUTHORIZATION_TYPE, "").trim(); String token = authorization.substring(HttpHeaderConstant.BEARER_TYPE.length()).trim();
JwtParsers jwtParsers = new JwtParsers(false); JwtParsers jwtParsers = new JwtParsers(false);
try { try {