From 9736f1b5aa31ffb4e7bd3c96d688020159a9a05d Mon Sep 17 00:00:00 2001 From: lbw Date: Wed, 10 Jan 2024 16:37:23 +0800 Subject: [PATCH] =?UTF-8?q?:recycle:=20Refactoring=20code.=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E7=BD=91=E5=85=B3filter=20=E5=88=A4=E6=96=AD=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E9=9D=9E=E5=AF=86=E7=A0=81=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E8=B7=B3=E8=BF=87=20PasswordDecoderFilter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/PigDaoAuthenticationProvider.java | 5 +- .../core/constant/SecurityConstants.java | 5 + .../handle/GlobalBizExceptionHandler.java | 166 ++++++++--------- .../gateway/filter/PasswordDecoderFilter.java | 176 +++++++++--------- 4 files changed, 176 insertions(+), 176 deletions(-) diff --git a/pig-auth/src/main/java/com/pig4cloud/pig/auth/support/core/PigDaoAuthenticationProvider.java b/pig-auth/src/main/java/com/pig4cloud/pig/auth/support/core/PigDaoAuthenticationProvider.java index ad709548..ca218f4a 100644 --- a/pig-auth/src/main/java/com/pig4cloud/pig/auth/support/core/PigDaoAuthenticationProvider.java +++ b/pig-auth/src/main/java/com/pig4cloud/pig/auth/support/core/PigDaoAuthenticationProvider.java @@ -20,6 +20,7 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import org.springframework.security.web.authentication.www.BasicAuthenticationConverter; import org.springframework.util.Assert; @@ -66,9 +67,9 @@ public class PigDaoAuthenticationProvider extends AbstractUserDetailsAuthenticat protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { - // app 模式不用校验密码 + // 只有密码模式需要校验密码 String grantType = WebUtils.getRequest().get().getParameter(OAuth2ParameterNames.GRANT_TYPE); - if (StrUtil.equals(SecurityConstants.MOBILE, grantType)) { + if (!StrUtil.equals(AuthorizationGrantType.PASSWORD.getValue(), grantType)) { return; } diff --git a/pig-common/pig-common-core/src/main/java/com/pig4cloud/pig/common/core/constant/SecurityConstants.java b/pig-common/pig-common-core/src/main/java/com/pig4cloud/pig/common/core/constant/SecurityConstants.java index acda5fa6..fe757be2 100755 --- a/pig-common/pig-common-core/src/main/java/com/pig4cloud/pig/common/core/constant/SecurityConstants.java +++ b/pig-common/pig-common-core/src/main/java/com/pig4cloud/pig/common/core/constant/SecurityConstants.java @@ -62,6 +62,11 @@ public interface SecurityConstants { */ String REFRESH_TOKEN = "refresh_token"; + /** + * password 模式 + */ + String PASSWORD = "password"; + /** * 手机号登录 */ diff --git a/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/sentinel/handle/GlobalBizExceptionHandler.java b/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/sentinel/handle/GlobalBizExceptionHandler.java index da465e01..0eb65459 100644 --- a/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/sentinel/handle/GlobalBizExceptionHandler.java +++ b/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/sentinel/handle/GlobalBizExceptionHandler.java @@ -49,97 +49,91 @@ import java.util.List; @ConditionalOnExpression("!'${security.oauth2.client.clientId}'.isEmpty()") public class GlobalBizExceptionHandler { - /** - * 全局异常. - * - * @param e the e - * @return R - */ - @ExceptionHandler(Exception.class) - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) - public R handleGlobalException(Exception e) { - log.error("全局异常信息 ex={}", e.getMessage(), e); + /** + * 全局异常. + * @param e the e + * @return R + */ + @ExceptionHandler(Exception.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public R handleGlobalException(Exception e) { + log.error("全局异常信息 ex={}", e.getMessage(), e); - // 业务异常交由 sentinel 记录 - Tracer.trace(e); - return R.failed(e.getLocalizedMessage()); - } + // 业务异常交由 sentinel 记录 + Tracer.trace(e); + return R.failed(e.getLocalizedMessage()); + } - /** - * 处理业务校验过程中碰到的非法参数异常 该异常基本由{@link org.springframework.util.Assert}抛出 - * - * @param exception 参数校验异常 - * @return API返回结果对象包装后的错误输出结果 - * @see Assert#hasLength(String, String) - * @see Assert#hasText(String, String) - * @see Assert#isTrue(boolean, String) - * @see Assert#isNull(Object, String) - * @see Assert#notNull(Object, String) - */ - @ExceptionHandler(IllegalArgumentException.class) - @ResponseStatus(HttpStatus.OK) - public R handleIllegalArgumentException(IllegalArgumentException exception) { - log.error("非法参数,ex = {}", exception.getMessage(), exception); - return R.failed(exception.getMessage()); - } + /** + * 处理业务校验过程中碰到的非法参数异常 该异常基本由{@link org.springframework.util.Assert}抛出 + * @param exception 参数校验异常 + * @return API返回结果对象包装后的错误输出结果 + * @see Assert#hasLength(String, String) + * @see Assert#hasText(String, String) + * @see Assert#isTrue(boolean, String) + * @see Assert#isNull(Object, String) + * @see Assert#notNull(Object, String) + */ + @ExceptionHandler(IllegalArgumentException.class) + @ResponseStatus(HttpStatus.OK) + public R handleIllegalArgumentException(IllegalArgumentException exception) { + log.error("非法参数,ex = {}", exception.getMessage(), exception); + return R.failed(exception.getMessage()); + } - /** - * AccessDeniedException - * - * @param e the e - * @return R - */ - @ExceptionHandler(AccessDeniedException.class) - @ResponseStatus(HttpStatus.FORBIDDEN) - public R handleAccessDeniedException(AccessDeniedException e) { - String msg = SpringSecurityMessageSource.getAccessor() - .getMessage("AbstractAccessDecisionManager.accessDenied", e.getMessage()); - log.warn("拒绝授权异常信息 ex={}", msg); - return R.failed(e.getLocalizedMessage()); - } + /** + * AccessDeniedException + * @param e the e + * @return R + */ + @ExceptionHandler(AccessDeniedException.class) + @ResponseStatus(HttpStatus.FORBIDDEN) + public R handleAccessDeniedException(AccessDeniedException e) { + String msg = SpringSecurityMessageSource.getAccessor() + .getMessage("AbstractAccessDecisionManager.accessDenied", e.getMessage()); + log.warn("拒绝授权异常信息 ex={}", msg); + return R.failed(e.getLocalizedMessage()); + } - /** - * validation Exception - * - * @param exception - * @return R - */ - @ExceptionHandler({MethodArgumentNotValidException.class}) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public R handleBodyValidException(MethodArgumentNotValidException exception) { - List fieldErrors = exception.getBindingResult().getFieldErrors(); - log.warn("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage()); - return R.failed(String.format("%s %s", fieldErrors.get(0).getField(), fieldErrors.get(0).getDefaultMessage())); - } + /** + * validation Exception + * @param exception + * @return R + */ + @ExceptionHandler({ MethodArgumentNotValidException.class }) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public R handleBodyValidException(MethodArgumentNotValidException exception) { + List fieldErrors = exception.getBindingResult().getFieldErrors(); + log.warn("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage()); + return R.failed(String.format("%s %s", fieldErrors.get(0).getField(), fieldErrors.get(0).getDefaultMessage())); + } - /** - * validation Exception (以form-data形式传参) - * - * @param exception - * @return R - */ - @ExceptionHandler({BindException.class}) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public R bindExceptionHandler(BindException exception) { - List fieldErrors = exception.getBindingResult().getFieldErrors(); - log.warn("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage()); - return R.failed(fieldErrors.get(0).getDefaultMessage()); - } - - /** - * 保持和低版本请求路径不存在的行为一致 - *

- * [Spring Boot 3.2.0] 404 Not Found behavior #38733 - * - * @param exception - * @return R - */ - @ExceptionHandler({NoResourceFoundException.class}) - @ResponseStatus(HttpStatus.NOT_FOUND) - public R bindExceptionHandler(NoResourceFoundException exception) { - log.debug("请求路径 404 {}", exception.getMessage()); - return R.failed(exception.getMessage()); - } + /** + * validation Exception (以form-data形式传参) + * @param exception + * @return R + */ + @ExceptionHandler({ BindException.class }) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public R bindExceptionHandler(BindException exception) { + List fieldErrors = exception.getBindingResult().getFieldErrors(); + log.warn("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage()); + return R.failed(fieldErrors.get(0).getDefaultMessage()); + } + /** + * 保持和低版本请求路径不存在的行为一致 + *

+ * [Spring Boot + * 3.2.0] 404 Not Found behavior #38733 + * @param exception + * @return R + */ + @ExceptionHandler({ NoResourceFoundException.class }) + @ResponseStatus(HttpStatus.NOT_FOUND) + public R bindExceptionHandler(NoResourceFoundException exception) { + log.debug("请求路径 404 {}", exception.getMessage()); + return R.failed(exception.getMessage()); + } } diff --git a/pig-gateway/src/main/java/com/pig4cloud/pig/gateway/filter/PasswordDecoderFilter.java b/pig-gateway/src/main/java/com/pig4cloud/pig/gateway/filter/PasswordDecoderFilter.java index f9f22844..61c18ef6 100755 --- a/pig-gateway/src/main/java/com/pig4cloud/pig/gateway/filter/PasswordDecoderFilter.java +++ b/pig-gateway/src/main/java/com/pig4cloud/pig/gateway/filter/PasswordDecoderFilter.java @@ -60,107 +60,107 @@ import java.util.function.Function; @RequiredArgsConstructor public class PasswordDecoderFilter extends AbstractGatewayFilterFactory { - private static final List> messageReaders = HandlerStrategies.withDefaults().messageReaders(); + private static final List> messageReaders = HandlerStrategies.withDefaults().messageReaders(); - private static final String PASSWORD = "password"; + private static final String PASSWORD = "password"; - private static final String KEY_ALGORITHM = "AES"; + private static final String KEY_ALGORITHM = "AES"; - private final GatewayConfigProperties gatewayConfig; + private final GatewayConfigProperties gatewayConfig; - static { - // 关闭hutool 强制关闭Bouncy Castle库的依赖 - SecureUtil.disableBouncyCastle(); - } + static { + // 关闭hutool 强制关闭Bouncy Castle库的依赖 + SecureUtil.disableBouncyCastle(); + } - @Override - public GatewayFilter apply(Object config) { - return (exchange, chain) -> { - ServerHttpRequest request = exchange.getRequest(); - // 1. 不是登录请求,直接向下执行 - if (!StrUtil.containsAnyIgnoreCase(request.getURI().getPath(), SecurityConstants.OAUTH_TOKEN_URL)) { - return chain.filter(exchange); - } + @Override + public GatewayFilter apply(Object config) { + return (exchange, chain) -> { + ServerHttpRequest request = exchange.getRequest(); + // 1. 不是登录请求,直接向下执行 + if (!StrUtil.containsAnyIgnoreCase(request.getURI().getPath(), SecurityConstants.OAUTH_TOKEN_URL)) { + return chain.filter(exchange); + } - // 2. 刷新token类型,直接向下执行 - String grantType = request.getQueryParams().getFirst("grant_type"); - if (StrUtil.equals(SecurityConstants.REFRESH_TOKEN, grantType)) { - return chain.filter(exchange); - } + // 2. 不是密码登录模式直接跳过 + String grantType = request.getQueryParams().getFirst("grant_type"); + if (!StrUtil.equals(SecurityConstants.PASSWORD, grantType)) { + return chain.filter(exchange); + } - // 3. 前端加密密文解密逻辑 - Class inClass = String.class; - Class outClass = String.class; - ServerRequest serverRequest = ServerRequest.create(exchange, messageReaders); + // 3. 前端加密密文解密逻辑 + Class inClass = String.class; + Class outClass = String.class; + ServerRequest serverRequest = ServerRequest.create(exchange, messageReaders); - // 4. 解密生成新的报文 - Mono modifiedBody = serverRequest.bodyToMono(inClass).flatMap(decryptAES()); + // 4. 解密生成新的报文 + Mono modifiedBody = serverRequest.bodyToMono(inClass).flatMap(decryptAES()); - BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, outClass); - HttpHeaders headers = new HttpHeaders(); - headers.putAll(exchange.getRequest().getHeaders()); - headers.remove(HttpHeaders.CONTENT_LENGTH); + BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, outClass); + HttpHeaders headers = new HttpHeaders(); + headers.putAll(exchange.getRequest().getHeaders()); + headers.remove(HttpHeaders.CONTENT_LENGTH); - headers.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE); - CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers); - return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> { - ServerHttpRequest decorator = decorate(exchange, headers, outputMessage); - return chain.filter(exchange.mutate().request(decorator).build()); - })); - }; - } + headers.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE); + CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers); + return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> { + ServerHttpRequest decorator = decorate(exchange, headers, outputMessage); + return chain.filter(exchange.mutate().request(decorator).build()); + })); + }; + } - /** - * 原文解密 - * @return - */ - private Function decryptAES() { - return s -> { - // 构建前端对应解密AES 因子 - AES aes = new AES(Mode.CFB, Padding.NoPadding, - new SecretKeySpec(gatewayConfig.getEncodeKey().getBytes(), KEY_ALGORITHM), - new IvParameterSpec(gatewayConfig.getEncodeKey().getBytes())); + /** + * 原文解密 + * + * @return + */ + private Function decryptAES() { + return s -> { + // 构建前端对应解密AES 因子 + AES aes = new AES(Mode.CFB, Padding.NoPadding, + new SecretKeySpec(gatewayConfig.getEncodeKey().getBytes(), KEY_ALGORITHM), + new IvParameterSpec(gatewayConfig.getEncodeKey().getBytes())); - // 获取请求密码并解密 - Map inParamsMap = HttpUtil.decodeParamMap((String) s, CharsetUtil.CHARSET_UTF_8); - if (inParamsMap.containsKey(PASSWORD)) { - String password = aes.decryptStr(inParamsMap.get(PASSWORD)); - // 返回修改后报文字符 - inParamsMap.put(PASSWORD, password); - } - else { - log.error("非法请求数据:{}", s); - } - return Mono.just(HttpUtil.toParams(inParamsMap, Charset.defaultCharset(), true)); - }; - } + // 获取请求密码并解密 + Map inParamsMap = HttpUtil.decodeParamMap((String) s, CharsetUtil.CHARSET_UTF_8); + if (inParamsMap.containsKey(PASSWORD)) { + String password = aes.decryptStr(inParamsMap.get(PASSWORD)); + // 返回修改后报文字符 + inParamsMap.put(PASSWORD, password); + } else { + log.error("非法请求数据:{}", s); + } + return Mono.just(HttpUtil.toParams(inParamsMap, Charset.defaultCharset(), true)); + }; + } - /** - * 报文转换 - * @return - */ - private ServerHttpRequestDecorator decorate(ServerWebExchange exchange, HttpHeaders headers, - CachedBodyOutputMessage outputMessage) { - return new ServerHttpRequestDecorator(exchange.getRequest()) { - @Override - public HttpHeaders getHeaders() { - long contentLength = headers.getContentLength(); - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.putAll(super.getHeaders()); - if (contentLength > 0) { - httpHeaders.setContentLength(contentLength); - } - else { - httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); - } - return httpHeaders; - } + /** + * 报文转换 + * + * @return + */ + private ServerHttpRequestDecorator decorate(ServerWebExchange exchange, HttpHeaders headers, + CachedBodyOutputMessage outputMessage) { + return new ServerHttpRequestDecorator(exchange.getRequest()) { + @Override + public HttpHeaders getHeaders() { + long contentLength = headers.getContentLength(); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.putAll(super.getHeaders()); + if (contentLength > 0) { + httpHeaders.setContentLength(contentLength); + } else { + httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); + } + return httpHeaders; + } - @Override - public Flux getBody() { - return outputMessage.getBody(); - } - }; - } + @Override + public Flux getBody() { + return outputMessage.getBody(); + } + }; + } }