mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-22 20:54:26 +08:00
refactor:项目结构优化
This commit is contained in:
parent
9a0a62d89b
commit
2b87d5b1c1
@ -70,7 +70,7 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
||||
// refresh token有两种使用方式:重复使用(true)、非重复使用(false),默认为true
|
||||
// 1 重复使用:access token过期刷新时, refresh token过期时间未改变,仍以初次生成的时间为准
|
||||
// 2 非重复使用:access token过期刷新时, refresh token过期时间延续,在refresh token有效期内刷新便永不失效达到无需再次登录的目的
|
||||
.reuseRefreshTokens(false);
|
||||
.reuseRefreshTokens(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4,20 +4,24 @@ import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
|
||||
import cn.binarywang.wx.miniapp.config.WxMaConfig;
|
||||
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
public class WxConfig {
|
||||
private WxProperties properties;
|
||||
|
||||
@Value("${wx.miniapp.appid}")
|
||||
private String appid;
|
||||
|
||||
@Value("${wx.miniapp.secret}")
|
||||
private String secret;
|
||||
|
||||
@Bean
|
||||
public WxMaConfig wxMaConfig() {
|
||||
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
|
||||
config.setAppid(properties.getAppid());
|
||||
config.setSecret(properties.getSecret());
|
||||
config.setAppid(appid);
|
||||
config.setSecret(secret);
|
||||
return config;
|
||||
}
|
||||
|
||||
|
@ -1,22 +0,0 @@
|
||||
package com.youlai.auth.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "wx.miniapp")
|
||||
public class WxProperties {
|
||||
|
||||
/**
|
||||
* 设置微信小程序的appid
|
||||
*/
|
||||
private String appid;
|
||||
|
||||
/**
|
||||
* 设置微信小程序的Secret
|
||||
*/
|
||||
private String secret;
|
||||
}
|
@ -6,6 +6,8 @@ import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.nimbusds.jose.jwk.JWKSet;
|
||||
import com.nimbusds.jose.jwk.RSAKey;
|
||||
import com.youlai.auth.domain.Oauth2Token;
|
||||
import com.youlai.common.core.constant.AuthConstants;
|
||||
import com.youlai.common.core.constant.Constants;
|
||||
@ -20,6 +22,7 @@ import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
@ -31,7 +34,9 @@ import org.springframework.web.bind.annotation.*;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.security.KeyPair;
|
||||
import java.security.Principal;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -39,6 +44,7 @@ import java.util.concurrent.TimeUnit;
|
||||
@RestController
|
||||
@RequestMapping("/oauth")
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class AuthController {
|
||||
|
||||
private TokenEndpoint tokenEndpoint;
|
||||
@ -46,6 +52,7 @@ public class AuthController {
|
||||
private WxMaService wxService;
|
||||
private UmsMemberFeignClient umsMemberFeignClient;
|
||||
private PasswordEncoder passwordEncoder;
|
||||
private KeyPair keyPair;
|
||||
|
||||
|
||||
@ApiOperation("OAuth2认证生成token")
|
||||
@ -66,7 +73,7 @@ public class AuthController {
|
||||
@ApiIgnore Principal principal,
|
||||
@ApiIgnore @RequestParam Map<String, String> parameters
|
||||
) throws HttpRequestMethodNotSupportedException, WxErrorException {
|
||||
|
||||
log.info("生成token开始");
|
||||
String clientId = parameters.get("client_id");
|
||||
|
||||
if (StrUtil.isBlank(clientId)) {
|
||||
@ -74,8 +81,8 @@ public class AuthController {
|
||||
}
|
||||
|
||||
// 微信小程序端认证处理
|
||||
if(AuthConstants.WEAPP_CLIENT_ID.equals(clientId)){
|
||||
return this.handleForWxAppAuth(principal,parameters);
|
||||
if (AuthConstants.WEAPP_CLIENT_ID.equals(clientId)) {
|
||||
return this.handleForWxAppAuth(principal, parameters);
|
||||
}
|
||||
|
||||
OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
|
||||
@ -162,4 +169,11 @@ public class AuthController {
|
||||
|
||||
}
|
||||
|
||||
@GetMapping("/public_key")
|
||||
public Map<String, Object> getKey() {
|
||||
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
|
||||
RSAKey key = new RSAKey.Builder(publicKey).build();
|
||||
return new JWKSet(key).toJSONObject();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
package com.youlai.auth.controller;
|
||||
import com.nimbusds.jose.jwk.JWKSet;
|
||||
import com.nimbusds.jose.jwk.RSAKey;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.security.KeyPair;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* RSA公钥开放接口
|
||||
*/
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class PublicKeyController {
|
||||
|
||||
private KeyPair keyPair;
|
||||
|
||||
@GetMapping("/rsa/publicKey")
|
||||
public Map<String, Object> getKey() {
|
||||
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
|
||||
RSAKey key = new RSAKey.Builder(publicKey).build();
|
||||
return new JWKSet(key).toJSONObject();
|
||||
}
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
package com.youlai.gateway.component;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.youlai.common.core.result.Result;
|
||||
import com.youlai.common.core.result.ResultCode;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* 无权访问自定义响应
|
||||
*/
|
||||
@Component
|
||||
public class CustomServerAccessDeniedHandler implements ServerAccessDeniedHandler {
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException e) {
|
||||
ServerHttpResponse response=exchange.getResponse();
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
|
||||
response.getHeaders().set("Access-Control-Allow-Origin","*");
|
||||
response.getHeaders().set("Cache-Control","no-cache");
|
||||
String body= JSONUtil.toJsonStr(Result.custom(ResultCode.USER_ACCESS_UNAUTHORIZED));
|
||||
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
|
||||
return response.writeWith(Mono.just(buffer));
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package com.youlai.gateway.component;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.youlai.common.core.result.Result;
|
||||
import com.youlai.common.core.result.ResultCode;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* 无效token/token过期 自定义响应
|
||||
*/
|
||||
@Component
|
||||
public class CustomServerAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {
|
||||
|
||||
@Override
|
||||
public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException e) {
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
|
||||
response.getHeaders().set("Access-Control-Allow-Origin", "*");
|
||||
response.getHeaders().set("Cache-Control", "no-cache");
|
||||
String body = JSONUtil.toJsonStr(Result.custom(ResultCode.TOKEN_INVALID_OR_EXPIRED));
|
||||
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
|
||||
return response.writeWith(Mono.just(buffer));
|
||||
}
|
||||
|
||||
}
|
@ -2,24 +2,37 @@ package com.youlai.gateway.config;
|
||||
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.youlai.common.core.constant.AuthConstants;
|
||||
import com.youlai.gateway.component.AuthorizationManager;
|
||||
import com.youlai.gateway.component.CustomServerAccessDeniedHandler;
|
||||
import com.youlai.gateway.component.CustomServerAuthenticationEntryPoint;
|
||||
import com.youlai.common.core.result.Result;
|
||||
import com.youlai.common.core.result.ResultCode;
|
||||
import com.youlai.gateway.security.AuthorizationManager;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
||||
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler;
|
||||
import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* 资源服务器配置
|
||||
*/
|
||||
@ -29,34 +42,101 @@ import reactor.core.publisher.Mono;
|
||||
public class ResourceServerConfig {
|
||||
|
||||
private AuthorizationManager authorizationManager;
|
||||
private CustomServerAccessDeniedHandler customServerAccessDeniedHandler;
|
||||
private CustomServerAuthenticationEntryPoint customServerAuthenticationEntryPoint;
|
||||
private WhiteListConfig whiteListConfig;
|
||||
|
||||
@Bean
|
||||
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
|
||||
http.oauth2ResourceServer().jwt()
|
||||
.jwtAuthenticationConverter(jwtAuthenticationConverter());
|
||||
// 自定义处理JWT请求头过期或签名错误的结果
|
||||
http.oauth2ResourceServer().authenticationEntryPoint(customServerAuthenticationEntryPoint);
|
||||
http.oauth2ResourceServer().authenticationEntryPoint(serverAuthenticationEntryPoint());
|
||||
//http.formLogin().authenticationFailureHandler(serverAuthenticationFailureHandler());
|
||||
http.authorizeExchange()
|
||||
.pathMatchers(ArrayUtil.toArray(whiteListConfig.getUrls(),String.class)).permitAll()
|
||||
.pathMatchers(ArrayUtil.toArray(whiteListConfig.getUrls(), String.class)).permitAll()
|
||||
.anyExchange().access(authorizationManager)
|
||||
.and()
|
||||
.exceptionHandling()
|
||||
.accessDeniedHandler(customServerAccessDeniedHandler) // 处理未授权
|
||||
.authenticationEntryPoint(customServerAuthenticationEntryPoint) //处理未认证
|
||||
.accessDeniedHandler(accessDeniedHandler()) // 处理未授权
|
||||
.authenticationEntryPoint(serverAuthenticationEntryPoint()) //处理未认证
|
||||
.and().csrf().disable();
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 未授权
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
ServerAccessDeniedHandler accessDeniedHandler() {
|
||||
return (exchange, denied) -> {
|
||||
Mono<Void> mono = Mono.defer(() -> Mono.just(exchange.getResponse()))
|
||||
.flatMap(response -> {
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
|
||||
response.getHeaders().set("Access-Control-Allow-Origin", "*");
|
||||
response.getHeaders().set("Cache-Control", "no-cache");
|
||||
String body = JSONUtil.toJsonStr(Result.custom(ResultCode.USER_ACCESS_UNAUTHORIZED));
|
||||
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
|
||||
return response.writeWith(Mono.just(buffer))
|
||||
.doOnError(error -> DataBufferUtils.release(buffer));
|
||||
});
|
||||
|
||||
return mono;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* token无效或者已过期
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
ServerAuthenticationEntryPoint serverAuthenticationEntryPoint() {
|
||||
return (exchange, e) -> {
|
||||
Mono<Void> mono = Mono.defer(() -> Mono.just(exchange.getResponse()))
|
||||
.flatMap(response -> {
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
|
||||
response.getHeaders().set("Access-Control-Allow-Origin", "*");
|
||||
response.getHeaders().set("Cache-Control", "no-cache");
|
||||
String body = JSONUtil.toJsonStr(Result.custom(ResultCode.TOKEN_INVALID_OR_EXPIRED));
|
||||
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
|
||||
return response.writeWith(Mono.just(buffer))
|
||||
.doOnError(error -> DataBufferUtils.release(buffer));
|
||||
});
|
||||
|
||||
return mono;
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
ServerAuthenticationFailureHandler serverAuthenticationFailureHandler() {
|
||||
return (exchange, e) -> {
|
||||
Mono<Void> mono = Mono.defer(() -> Mono.just(exchange.getExchange().getResponse()))
|
||||
.flatMap(response -> {
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
|
||||
response.getHeaders().set("Access-Control-Allow-Origin", "*");
|
||||
response.getHeaders().set("Cache-Control", "no-cache");
|
||||
String body = JSONUtil.toJsonStr(Result.custom(ResultCode.TOKEN_INVALID_OR_EXPIRED));
|
||||
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
|
||||
return response.writeWith(Mono.just(buffer))
|
||||
.doOnError(error -> DataBufferUtils.release(buffer));
|
||||
});
|
||||
return mono;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @link https://blog.csdn.net/qq_24230139/article/details/105091273
|
||||
* ServerHttpSecurity没有将jwt中authorities的负载部分当做Authentication
|
||||
* 需要把jwt的Claim中的authorities加入
|
||||
* 方案:重新定义ReactiveAuthenticationManager权限管理器,默认转换器JwtGrantedAuthoritiesConverter
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
|
||||
@ -69,4 +149,5 @@ public class ResourceServerConfig {
|
||||
return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.youlai.gateway.component;
|
||||
package com.youlai.gateway.security;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.StrUtil;
|
Loading…
Reference in New Issue
Block a user