提交 935a89ab 编写于 作者: pig_冷冷's avatar pig_冷冷

🐛 Fixing a bug. refresh-token error

上级 d1367808
......@@ -25,6 +25,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
......@@ -49,7 +50,7 @@ import java.util.Map;
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private final DataSource dataSource;
private final org.springframework.security.core.userdetails.UserDetailsService UserDetailsService;
private final UserDetailsService userDetailsService;
private final AuthenticationManager authenticationManager;
private final RedisConnectionFactory redisConnectionFactory;
......@@ -74,7 +75,7 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancer())
.userDetailsService(UserDetailsService)
.userDetailsService(userDetailsService)
.authenticationManager(authenticationManager)
.reuseRefreshTokens(false)
.exceptionTranslator(new PigWebResponseExceptionTranslator());
......
......@@ -69,4 +69,8 @@ public interface CommonConstants {
*/
Integer FAIL = 1;
/**
* 验证码前缀
*/
String DEFAULT_CODE_KEY = "DEFAULT_CODE_KEY_";
}
......@@ -16,10 +16,15 @@
package com.pig4cloud.pig.common.core.util;
import cn.hutool.core.codec.Base64;
import cn.hutool.json.JSONUtil;
import com.pig4cloud.pig.common.core.exception.CheckedException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
......@@ -31,6 +36,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
/**
......@@ -40,8 +46,8 @@ import java.io.PrintWriter;
*/
@Slf4j
public class WebUtils extends org.springframework.web.util.WebUtils {
public static final String UNKNOWN = "unknown";
private static final String BASIC_ = "Basic ";
private static final String UNKNOWN = "unknown";
/**
* 判断是否ajax请求
......@@ -188,5 +194,36 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
}
return StringUtils.isBlank(ip) ? null : ip.split(",")[0];
}
/**
* 从request 获取CLIENT_ID
*
* @return
*/
@SneakyThrows
public static String[] getClientId(ServerHttpRequest request) {
String header = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (header == null || !header.startsWith(BASIC_)) {
throw new CheckedException("请求头中client信息为空");
}
byte[] base64Token = header.substring(6).getBytes("UTF-8");
byte[] decoded;
try {
decoded = Base64.decode(base64Token);
} catch (IllegalArgumentException e) {
throw new CheckedException(
"Failed to decode basic authentication token");
}
String token = new String(decoded, StandardCharsets.UTF_8);
int delim = token.indexOf(":");
if (delim == -1) {
throw new CheckedException("Invalid basic authentication token");
}
return new String[]{token.substring(0, delim), token.substring(delim + 1)};
}
}
......@@ -11,7 +11,7 @@ spring:
- Path=/auth/**
filters:
# 验证码处理
- ImageCodeGatewayFilter
- ValidateCodeGatewayFilter
# 前端密码解密
- PasswordDecoderFilter
#UPMS 模块
......@@ -42,3 +42,8 @@ security:
encode:
# 前端密码密钥,必须16位
key: 'thanks,pig4cloud'
# 不校验验证码终端
ignore:
clients:
- test
......@@ -16,87 +16,39 @@
package com.pig4cloud.pig.gateway.filter;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.pig4cloud.pig.common.core.exception.CheckedException;
import com.pig4cloud.pig.common.core.exception.ValidateCodeException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pig4cloud.pig.common.core.config.FilterIgnorePropertiesConfig;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.exception.ValidateCodeException;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.core.util.WebUtils;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import java.io.IOException;
import reactor.core.publisher.Mono;
/**
* @author lengleng
* @date 2019/2/1
* @date 2018/7/4
* 验证码处理
*/
@Slf4j
@Component
public class ImageCodeGatewayFilter extends AbstractGatewayFilterFactory {
public static final String DEFAULT_CODE_KEY = "DEFAULT_CODE_KEY";
public static final String OAUTH_TOKEN_URL = "/oauth/token";
private static final String BASIC_ = "Basic ";
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private FilterIgnorePropertiesConfig filterIgnorePropertiesConfig;
/**
* 从header 请求中的clientId/clientsecect
*
* @param header header中的参数
* @throws CheckedException if the Basic header is not present or is not valid
* Base64
*/
public static String[] extractAndDecodeHeader(String header)
throws IOException, CheckedException {
byte[] base64Token = header.substring(6).getBytes("UTF-8");
byte[] decoded;
try {
decoded = Base64.decode(base64Token);
} catch (IllegalArgumentException e) {
throw new CheckedException(
"Failed to decode basic authentication token");
}
String token = new String(decoded, CharsetUtil.UTF_8);
int delim = token.indexOf(":");
if (delim == -1) {
throw new CheckedException("Invalid basic authentication token");
}
return new String[]{token.substring(0, delim), token.substring(delim + 1)};
}
/**
* *从header 请求中的clientId/clientsecect
*
* @param request
* @return
* @throws IOException
*/
public static String[] extractAndDecodeHeader(ServerHttpRequest request)
throws IOException, CheckedException {
String header = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (header == null || !header.startsWith(BASIC_)) {
throw new CheckedException("请求头中client信息为空");
}
return extractAndDecodeHeader(header);
}
@AllArgsConstructor
public class ValidateCodeGatewayFilter extends AbstractGatewayFilterFactory {
private final ObjectMapper objectMapper;
private final RedisTemplate redisTemplate;
private final FilterIgnorePropertiesConfig filterIgnorePropertiesConfig;
@Override
public GatewayFilter apply(Object config) {
......@@ -104,35 +56,37 @@ public class ImageCodeGatewayFilter extends AbstractGatewayFilterFactory {
ServerHttpRequest request = exchange.getRequest();
// 不是登录请求,直接向下执行
if (!StrUtil.containsAnyIgnoreCase(request.getURI().getPath(), OAUTH_TOKEN_URL)) {
if (!StrUtil.containsAnyIgnoreCase(request.getURI().getPath()
, SecurityConstants.OAUTH_TOKEN_URL)) {
return chain.filter(exchange);
}
// 终端设置不校验, 直接向下执行(1. 从请求参数中获取 2.从header取)
String clientId = request.getQueryParams().getFirst("client_id");
if (StrUtil.isNotBlank(clientId)) {
if (filterIgnorePropertiesConfig.getClients().contains(clientId)) {
return chain.filter(exchange);
}
// 刷新token,直接向下执行
String grantType = request.getQueryParams().getFirst("grant_type");
if (StrUtil.equals(SecurityConstants.REFRESH_TOKEN, grantType)) {
return chain.filter(exchange);
}
// 终端设置不校验, 直接向下执行
try {
String[] clientInfos = extractAndDecodeHeader(request);
String[] clientInfos = WebUtils.getClientId(request);
if (filterIgnorePropertiesConfig.getClients().contains(clientInfos[0])) {
return chain.filter(exchange);
}
} catch (Exception e) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.PRECONDITION_REQUIRED);
return response.setComplete();
}
//校验验证码合法性
try {
//校验验证码
checkCode(request);
} catch (ValidateCodeException e) {
} catch (Exception e) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.PRECONDITION_REQUIRED);
return response.setComplete();
try {
return response.writeWith(Mono.just(response.bufferFactory()
.wrap(objectMapper.writeValueAsBytes(
R.builder().msg(e.getMessage())
.code(CommonConstants.FAIL).build()))));
} catch (JsonProcessingException e1) {
log.error("对象输出异常", e1);
}
}
return chain.filter(exchange);
......@@ -143,40 +97,40 @@ public class ImageCodeGatewayFilter extends AbstractGatewayFilterFactory {
* 检查code
*
* @param request
* @throws ValidateCodeException 校验异常
*/
private void checkCode(ServerHttpRequest request) throws ValidateCodeException {
@SneakyThrows
private void checkCode(ServerHttpRequest request) {
String code = request.getQueryParams().getFirst("code");
if (StrUtil.isBlank(code)) {
throw new ValidateCodeException();
throw new ValidateCodeException("验证码不能为空");
}
String randomStr = request.getQueryParams().getFirst("randomStr");
if (StrUtil.isBlank(randomStr)) {
throw new ValidateCodeException();
randomStr = request.getQueryParams().getFirst("mobile");
}
String key = DEFAULT_CODE_KEY + randomStr;
String key = CommonConstants.DEFAULT_CODE_KEY + randomStr;
if (!redisTemplate.hasKey(key)) {
throw new ValidateCodeException();
throw new ValidateCodeException("验证码不合法");
}
Object codeObj = redisTemplate.opsForValue().get(key);
if (codeObj == null) {
throw new ValidateCodeException();
throw new ValidateCodeException("验证码不合法");
}
String saveCode = codeObj.toString();
if (StrUtil.isBlank(saveCode)) {
redisTemplate.delete(key);
throw new ValidateCodeException();
throw new ValidateCodeException("验证码不合法");
}
if (!StrUtil.equals(saveCode, code)) {
redisTemplate.delete(key);
throw new ValidateCodeException();
throw new ValidateCodeException("验证码不合法");
}
redisTemplate.delete(key);
......
......@@ -17,7 +17,7 @@
package com.pig4cloud.pig.gateway.handler;
import com.google.code.kaptcha.Producer;
import com.pig4cloud.pig.gateway.filter.ImageCodeGatewayFilter;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ByteArrayResource;
......@@ -57,7 +57,7 @@ public class ImageCodeHandler implements HandlerFunction<ServerResponse> {
//保存验证码信息
String randomStr = serverRequest.queryParam("randomStr").get();
redisTemplate.opsForValue().set(ImageCodeGatewayFilter.DEFAULT_CODE_KEY + randomStr, text, 60, TimeUnit.SECONDS);
redisTemplate.opsForValue().set(CommonConstants.DEFAULT_CODE_KEY + randomStr, text, 60, TimeUnit.SECONDS);
// 转换流信息写出
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册