Commit 345cdf96 by zhangxingmin

配置

parent ffa894fc
......@@ -19,12 +19,6 @@
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
......@@ -75,9 +69,34 @@
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
<!--对于bootstrap.properties/bootstrap.yaml配置文件(我们合起来成为Bootstrap配置文件)的支持,需要导入如下的依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
</dependency>
<!-- 用户API模块 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<groupId>com.yd</groupId>
<artifactId>yd-user-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
......
......@@ -6,14 +6,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@SpringBootApplication(scanBasePackages = "com.yd")
@MapperScan("com.yd.**.mapper")
@EnableFeignClients(basePackages = "com.yd.auth.core.**")
@EnableFeignClients(basePackages = "com.yd")
public class AuthApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(AuthApplication.class)
.properties("spring.config.name:bootstrap", "config/bootstrap.yml")
// .properties("spring.config.name:bootstrap", "config/bootstrap.yml")
.properties("spring.application.name="+ ServerNameConstants.ydAuthCore)
.build().run(args);
System.out.println("(♥◠‿◠)ノ゙ yd-auth-core认证服务启动成功 ლ(´ڡ`ლ)゙ ");
......
......@@ -2,7 +2,7 @@ package com.yd.auth.core.config;
import com.yd.auth.core.security.JwtAuthenticationEntryPoint;
import com.yd.auth.core.security.JwtAuthenticationFilter;
import com.yd.auth.core.security.JwtAuthenticationProvider;
import com.yd.auth.core.service.AuthUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
......@@ -20,46 +20,52 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
private final AuthUserDetailsService userDetailsService;
private final JwtAuthenticationEntryPoint authenticationEntryPoint;
private final JwtAuthenticationFilter authenticationFilter;
@Autowired
private JwtAuthenticationProvider jwtAuthenticationProvider;
public SecurityConfig(AuthUserDetailsService userDetailsService,
JwtAuthenticationEntryPoint authenticationEntryPoint,
JwtAuthenticationFilter authenticationFilter) {
this.userDetailsService = userDetailsService;
this.authenticationEntryPoint = authenticationEntryPoint;
this.authenticationFilter = authenticationFilter;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(jwtAuthenticationProvider);
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/v2/api-docs", "/swagger-resources/configuration/ui",
"/swagger-resources", "/swagger-resources/configuration/security",
"/swagger-ui.html", "/webjars/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
.antMatchers(
"/auth/login",
"/auth/register",
"/swagger-ui/**",
"/v3/api-docs/**"
).permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
}
package com.yd.auth.core.controller;
import com.yd.common.result.Result;
import com.yd.auth.core.dto.LoginRequest;
import com.yd.auth.core.dto.LoginResponse;
import com.yd.auth.core.service.AuthService;
import com.yd.user.service.entity.User;
import com.yd.common.result.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import javax.validation.Valid;
@RestController
@RequestMapping("/api/auth")
@RequestMapping("/auth")
public class AuthController {
@Autowired
private AuthService authService;
@PostMapping("/login")
public Result<?> login(@RequestBody Map<String, String> loginRequest) {
String username = loginRequest.get("username");
String password = loginRequest.get("password");
private final AuthService authService;
Map<String, String> tokens = authService.login(username, password);
return Result.success(tokens);
@Autowired
public AuthController(AuthService authService) {
this.authService = authService;
}
@PostMapping("/refresh")
public Result<?> refreshToken(@RequestBody Map<String, String> refreshRequest) {
String refreshToken = refreshRequest.get("refreshToken");
Map<String, String> tokens = authService.refreshToken(refreshToken);
return Result.success(tokens);
@PostMapping("/login")
public Result<LoginResponse> login(@Valid @RequestBody LoginRequest loginRequest) {
LoginResponse response = authService.login(loginRequest);
return Result.success(response);
}
@PostMapping("/register")
public Result<?> register(@RequestBody User user) {
User registeredUser = authService.register(user);
return Result.success(registeredUser);
}
// @PostMapping("/logout")
// public Result<Void> logout() {
// // 实际实现需要前端传递token
// // 这里简化处理
// return R.success("登出成功");
// }
}
package com.yd.auth.core.dto;
public class LoginRequest {
private String username;
private String password;
// Getters and Setters
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.yd.auth.core.dto;
public class LoginResponse {
private String token;
private String tokenType = "Bearer";
private long expiresIn;
// Getters and Setters
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getTokenType() {
return tokenType;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
public long getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(long expiresIn) {
this.expiresIn = expiresIn;
}
}
package com.yd.auth.core.exception;
import com.yd.auth.core.security.JwtTokenProvider;
import com.yd.common.result.Result;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BadCredentialsException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public Result<?> handleBadCredentialsException(BadCredentialsException e) {
return Result.fail(401, "用户名或密码错误");
}
@ExceptionHandler(JwtTokenProvider.JwtAuthenticationException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public Result<?> handleJwtAuthenticationException(JwtTokenProvider.JwtAuthenticationException e) {
return Result.fail(401, e.getMessage());
}
}
package com.yd.auth.core.model;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
@Getter
public class AuthUser extends User {
private final Long id;
public AuthUser(Long id, String username, String password,
Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
this.id = id;
}
}
package com.yd.auth.core.security;
import com.alibaba.fastjson.JSON;
import com.yd.common.result.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
......@@ -14,16 +12,9 @@ import java.io.IOException;
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
// 设置响应状态码为401
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
// 设置响应内容类型
response.setContentType("application/json;charset=UTF-8");
// 返回统一的错误响应
Result<?> result = Result.fail(401, "未经授权: " + authException.getMessage());
response.getWriter().write(JSON.toJSONString(result));
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "未经授权的访问");
}
}
package com.yd.auth.core.security;
import com.yd.auth.core.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtUtils jwtUtils;
private final JwtTokenProvider tokenProvider;
private final UserDetailsService userDetailsService;
@Autowired
private UserDetailsService userDetailsService;
public JwtAuthenticationFilter(JwtTokenProvider tokenProvider,
UserDetailsService userDetailsService) {
this.tokenProvider = tokenProvider;
this.userDetailsService = userDetailsService;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
// 从请求头中获取JWT令牌
String jwt = parseJwt(request);
if (jwt != null && jwtUtils.validateToken(jwt)) {
// 从JWT中获取用户名
String username = jwtUtils.getUsernameFromToken(jwt);
// 加载用户详情
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String token = resolveToken(request);
if (token != null && tokenProvider.validateToken(token)) {
String username = tokenProvider.getUsernameFromToken(token);
// 从数据库加载用户信息
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// 创建认证令牌
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// 将认证信息设置到SecurityContext中
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
log.error("无法设置用户认证: {}", e.getMessage());
}
filterChain.doFilter(request, response);
}
private String parseJwt(HttpServletRequest request) {
String headerAuth = request.getHeader("Authorization");
if (headerAuth != null && headerAuth.startsWith("Bearer ")) {
return headerAuth.substring(7);
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
}
package com.yd.auth.core.security;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.util.Collection;
import java.util.Date;
import java.util.stream.Collectors;
@Component
public class JwtTokenProvider {
@Value("${jwt.secret}")
private String jwtSecret;
@Value("${jwt.expiration}")
private int jwtExpiration;
public String generateToken(Authentication authentication) {
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
return Jwts.builder()
.setSubject(userDetails.getUsername())
.claim("roles", getRoles(userDetails.getAuthorities()))
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + jwtExpiration * 1000L))
.signWith(getSigningKey(), SignatureAlgorithm.HS512)
.compact();
}
private Collection<String> getRoles(Collection<? extends GrantedAuthority> authorities) {
return authorities.stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toList());
}
public String getUsernameFromToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
}
public Authentication getAuthentication(String token) {
if (validateToken(token)) {
String username = getUsernameFromToken(token);
// 这里应该从数据库加载用户信息,但为了性能通常只加载基本信息
// 实际项目中可以在这里加载用户权限
return new UsernamePasswordAuthenticationToken(
username,
null,
// 从token中提取权限
getAuthoritiesFromToken(token)
);
}
return null;
}
private Collection<? extends GrantedAuthority> getAuthoritiesFromToken(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();
@SuppressWarnings("unchecked")
Collection<String> roles = (Collection<String>) claims.get("roles");
return roles.stream()
.map(role -> (GrantedAuthority) () -> role)
.collect(Collectors.toList());
}
public boolean validateToken(String token) {
try {
Jwts.parserBuilder().setSigningKey(getSigningKey()).build().parseClaimsJws(token);
return true;
} catch (SecurityException | MalformedJwtException e) {
throw new JwtAuthenticationException("无效的JWT签名");
} catch (ExpiredJwtException e) {
throw new JwtAuthenticationException("JWT令牌已过期");
} catch (UnsupportedJwtException e) {
throw new JwtAuthenticationException("不支持的JWT令牌");
} catch (IllegalArgumentException e) {
throw new JwtAuthenticationException("JWT令牌无效");
} catch (Exception e) {
throw new JwtAuthenticationException("无效的JWT令牌");
}
}
private SecretKey getSigningKey() {
return Keys.hmacShaKeyFor(jwtSecret.getBytes());
}
public int getJwtExpiration() {
return jwtExpiration;
}
public static class JwtAuthenticationException extends RuntimeException {
public JwtAuthenticationException(String message) {
super(message);
}
}
}
package com.yd.auth.core.service;
import com.yd.auth.core.security.JwtAuthenticationToken;
import com.yd.user.service.entity.User;
import com.yd.auth.core.dto.LoginRequest;
import com.yd.auth.core.dto.LoginResponse;
import org.springframework.security.core.Authentication;
import java.util.Map;
public interface AuthService {
/**
* 用户登录
*/
Map<String, String> login(String username, String password);
/**
* 刷新令牌
*/
Map<String, String> refreshToken(String refreshToken);
/**
* 验证令牌
*/
Authentication validateToken(String token);
/**
* 注册新用户
*/
User register(User user);
LoginResponse login(LoginRequest loginRequest);
void logout(String token);
Authentication getAuthentication(String token);
}
package com.yd.auth.core.service;
import com.yd.auth.core.model.AuthUser;
import com.yd.user.api.dto.UserDTO;
import com.yd.user.api.feign.UserFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.stream.Collectors;
@Service
public class AuthUserDetailsService implements UserDetailsService {
private final UserFeignClient userFeignClient;
@Autowired
public AuthUserDetailsService(UserFeignClient userFeignClient) {
this.userFeignClient = userFeignClient;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 通过Feign调用yd-user服务获取用户信息
UserDTO user = userFeignClient.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("用户不存在:" + username);
}
// 转换为Spring Security用户对象
return new AuthUser(
user.getId(),
user.getUsername(),
user.getPassword(),
user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role)) // 修正类名
.collect(Collectors.toList())
);
}
}
package com.yd.auth.core.service.impl;
import com.yd.auth.core.security.JwtAuthenticationToken;
import com.yd.auth.core.dto.LoginRequest;
import com.yd.auth.core.dto.LoginResponse;
import com.yd.auth.core.security.JwtTokenProvider;
import com.yd.auth.core.service.AuthService;
import com.yd.auth.core.utils.JwtUtils;
import com.yd.user.service.entity.User;
import com.yd.user.service.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class AuthServiceImpl implements AuthService {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtils jwtUtils;
private final AuthenticationManager authenticationManager;
private final JwtTokenProvider jwtTokenProvider;
@Autowired
private UserService userService;
public AuthServiceImpl(AuthenticationManager authenticationManager,
JwtTokenProvider jwtTokenProvider) {
this.authenticationManager = authenticationManager;
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
public Map<String, String> login(String username, String password) {
// 验证用户名和密码
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(username, password)
public LoginResponse login(LoginRequest loginRequest) {
// 1. 创建认证对象
Authentication authentication = new UsernamePasswordAuthenticationToken(
loginRequest.getUsername(),
loginRequest.getPassword()
);
// 将认证信息设置到SecurityContext中
SecurityContextHolder.getContext().setAuthentication(authentication);
// 获取用户信息
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
// 生成JWT令牌
String token = jwtUtils.generateToken(userDetails);
String refreshToken = jwtUtils.generateRefreshToken(userDetails);
// 2. 进行认证
Authentication authenticated = authenticationManager.authenticate(authentication);
// 返回令牌
Map<String, String> result = new HashMap<String, String>();
result.put("token", token);
result.put("refreshToken", refreshToken);
return result;
}
@Override
public Map<String, String> refreshToken(String refreshToken) {
// 验证刷新令牌
if (!jwtUtils.validateToken(refreshToken)) {
throw new RuntimeException("无效的刷新令牌");
}
// 获取用户名
String username = jwtUtils.getUsernameFromToken(refreshToken);
// 3. 设置安全上下文
SecurityContextHolder.getContext().setAuthentication(authenticated);
// 加载用户详情
UserDetails userDetails = userService.loadUserByUsername(username);
// 4. 生成令牌
String token = jwtTokenProvider.generateToken(authenticated);
// 生成新的JWT令牌
String token = jwtUtils.generateToken(userDetails);
// 5. 创建响应对象
LoginResponse response = new LoginResponse();
response.setToken(token);
response.setExpiresIn(jwtTokenProvider.getJwtExpiration());
// 返回新令牌
Map<String, String> result = new HashMap<String, String>();
result.put("token", token);
result.put("refreshToken", refreshToken);
return result;
return response;
}
@Override
public Authentication validateToken(String token) {
JwtAuthenticationToken authentication = new JwtAuthenticationToken(token);
return authenticationManager.authenticate(authentication);
public void logout(String token) {
// 实现令牌失效逻辑(可选)
// 实际应用中可能需要将令牌加入黑名单
SecurityContextHolder.clearContext();
}
@Override
public User register(User user) {
return userService.register(user);
public Authentication getAuthentication(String token) {
if (jwtTokenProvider.validateToken(token)) {
return jwtTokenProvider.getAuthentication(token);
}
return null;
}
}
${AnsiColor.GREEN}
_ _ _ __ __ ____ _ _ _ _ _
| | (_)_ __ | | _\ \ / /__ / ___| |__ __ _| |_ / \ _ _| |_| |__
| | | | '_ \| |/ /\ \ /\ / / _ \ | | '_ \ / _` | __| / _ \| | | | __| '_ \
| |___| | | | | < \ V V / __/ |___| | | | (_| | |_ / ___ \ |_| | |_| | | |
|_____|_|_| |_|_|\_\ \_/\_/ \___|\____|_| |_|\__,_|\__/_/ \_\__,_|\__|_| |_|
${AnsiColor.BRIGHT_WHITE}
Spring Boot Version: ${spring-boot.version}
\ No newline at end of file
......@@ -40,7 +40,7 @@ spring:
# 配置中心
config:
# 命名空间id(此处不用public,因public初始化的空间, id为空)
namespace: d2446fdc-2683-4c82-aa86-61242c61b5cd
namespace: c1e4cbcf-d8b7-4da9-a75a-7b75890fc390
# nacos的ip地址和端口
server-addr: 139.224.145.34:8848
# 这个就表示 在我们nacos命名空间id为 dev中 有一个data-id 为 demo-service.yml 的配置文件 读取这个里面的配置
......@@ -49,6 +49,11 @@ spring:
# 共享配置, 可以把公共配置放在同个命名空间下,然后创建一个 common.yml 文件 ,里面可以放共用的配置
shared-configs[0]:
dataId: yd-common.yml
group: YD_GROUP
refresh: true
extension-configs: # 扩展配置
- data-id: yd-auth-core.yml
group: YD_GROUP
refresh: true
# 发布到注册中心 (如果没有使用可以不配)
discovery:
......@@ -75,8 +80,9 @@ spring:
config-retry-time: 300000
# 共享配置, 可以把公共配置放在同个命名空间下,然后创建一个 common.yml 文件 ,里面可以放共用的配置
shared-configs[0]:
dataId: linkwe-common.yml
dataId: yd-common.yml
refresh: true
group: YD_GROUP
# 发布到注册中心 (如果没有使用可以不配)
discovery:
# 命名空间id(此处不用public,因public初始化的空间, id为空)
......
#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2
#开启日志过滤
filter=true
#排序sql包含QRTZ的sql 多个逗号隔离
exclude=QRTZ,sys_oper_log
\ No newline at end of file
......@@ -28,7 +28,6 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
......
......@@ -9,6 +9,13 @@ import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
//import com.yd.common.model.R;
//import org.springframework.http.HttpStatus;
//import org.springframework.security.authentication.BadCredentialsException;
//import org.springframework.web.bind.annotation.ExceptionHandler;
//import org.springframework.web.bind.annotation.ResponseStatus;
//import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理器
*/
......@@ -45,4 +52,16 @@ public class GlobalExceptionHandler {
log.error("系统异常: ", e);
return Result.fail("系统异常,请联系管理员");
}
// @ExceptionHandler(BadCredentialsException.class)
// @ResponseStatus(HttpStatus.UNAUTHORIZED)
// public R<?> handleBadCredentialsException(BadCredentialsException e) {
// return R.fail(401, "用户名或密码错误");
// }
//
// @ExceptionHandler(JwtTokenProvider.JwtAuthenticationException.class)
// @ResponseStatus(HttpStatus.UNAUTHORIZED)
// public R<?> handleJwtAuthenticationException(JwtTokenProvider.JwtAuthenticationException e) {
// return R.fail(401, e.getMessage());
// }
}
package com.yd.gateway.config;
import com.yd.gateway.filter.AuthenticationFilter;
import com.yd.auth.core.security.JwtTokenProvider;
import com.yd.auth.core.security.JwtTokenProvider.JwtAuthenticationException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository;
import reactor.core.publisher.Mono;
/**
* 网关安全配置
*/
@Configuration
@EnableWebFluxSecurity
public class GatewaySecurityConfig {
private final AuthenticationFilter authenticationFilter;
private final JwtTokenProvider jwtTokenProvider;
public GatewaySecurityConfig(AuthenticationFilter authenticationFilter) {
this.authenticationFilter = authenticationFilter;
public GatewaySecurityConfig(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
@Bean
@Order(-1)
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http
http
.csrf().disable()
.securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
.authorizeExchange()
// 放行登录和刷新令牌接口
.pathMatchers("/auth/login", "/auth/refresh-token").permitAll()
// 放行健康检查接口
.pathMatchers("/actuator/health/**").permitAll()
// 其他请求需要认证
.anyExchange().authenticated()
.and()
.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION)
.build();
.authorizeExchange(exchanges -> exchanges
.pathMatchers(
"/auth/**",
"/swagger-ui/**",
"/v3/api-docs/**"
).permitAll() // 放行认证和Swagger路径
.anyExchange().authenticated() // 其他请求需要认证
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt
.jwtDecoder(token -> {
try {
// 验证令牌有效性
jwtTokenProvider.validateToken(token);
// 将字符串转换为 Jwt 对象
Jwt jwtObject = Jwt.withTokenValue(token).build();
return Mono.just(jwtObject);
} catch (JwtAuthenticationException e) {
return Mono.error(e);
}
})
)
);
return http.build();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment