SpringSecurityConfig:
package com.hhk.springBoot.config.security;
import java.util.List;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.hhk.springBoot.config.security.component.JWTAuthenticationFilter;
import com.hhk.springBoot.pojo.User;
import com.hhk.springBoot.service.UserService;
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig {
@Autowired
private JWTAuthenticationFilter jwtAuthenticationFilter;
@Autowired
private UserService userService;
@Autowired
private JsonAuthenticationEntryPoint jsonAuthenticationEntryPoint;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
http
.csrf(csrf->csrf.disable())
.authorizeHttpRequests(authz-> authz
.requestMatchers("/public/**","/swagger-ui/**","/v3/api-docs/**").permitAll()
.anyRequest().authenticated()
// .anyRequest().permitAll()
)
.addFilterBefore(jwtAuthenticationFilter,UsernamePasswordAuthenticationFilter.class)
.sessionManagement((session) -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.httpBasic(Customizer.withDefaults());
// 添加自定义未登录结果返回
http.exceptionHandling((excep)->excep
.authenticationEntryPoint(jsonAuthenticationEntryPoint));
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
// authenticationProvider.setUserDetailsService(userDetailsService);
// authenticationProvider.setPasswordEncoder(passwordEncoder);
ProviderManager providerManager = new ProviderManager(authenticationProvider);
// 可以在这里设置更多的ProviderManager属性
return providerManager;
}
}
JsonAuthenticationEntryPoint:
package com.hhk.springBoot.config.security;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Component
public class JsonAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
// 设置响应状态码和内容类型
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
// 构建自定义 JSON 响应体
Map<String, Object> body = new HashMap<>();
body.put("code", 401);
body.put("message", "未登录,请先认证--");
body.put("path", request.getRequestURI());
// 将 Map 转换为 JSON 并写入响应流
new ObjectMapper().writeValue(response.getOutputStream(), body);
}
}
JWTAuthenticationFilter:
package com.hhk.springBoot.config.security.component;
import java.io.IOException;
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.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import com.hhk.springBoot.service.impl.CustomUserDeatailsService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Component
public class JWTAuthenticationFilter extends OncePerRequestFilter{
@Autowired
private CustomUserDeatailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
System.out.println("JWTAuthenticationFilter doFilterInternal-------------------------");
String header = request.getHeader("Authorization");
System.out.println("header:"+header);
JwtUtil jwtUtil = new JwtUtil();
if (header != null && header.startsWith("Bearer ")) {
String token = header.substring(7);
System.out.println("token:"+token);
if (jwtUtil.validateToken(token) && userDetailsService!=null) {
String username = jwtUtil.parseToken(token);
System.out.println("userDetailsService"+userDetailsService);
// 加载用户权限
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
System.out.println("token:"+username);
// System.out.println("token:"+userDetails);
// 设置安全上下文
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
filterChain.doFilter(request, response);
}
}
JwtUtil:
package com.hhk.springBoot.config.security.component;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Component
public class JwtUtil{
private static final String CLAIM_KEY_USERNAME="sub";
private static final String CLAIM_KEY_CREATE="created";
private static final String secret="woyouyigemengxiangnajiushidailingjiarentuopingwoyouyigemengxiangnajiushidailingjiarentuoping";
private static final Long expiration = (long) 604800;
// 生成 JWT
public String generateToken(UserDetails userDetails) {
Map<String,Object> claims=new HashMap<>();
claims.put(CLAIM_KEY_USERNAME,userDetails.getUsername());
claims.put(CLAIM_KEY_CREATE,new Date());
System.out.println("claims:"+claims);
return generateToken(claims);
}
// 从token中获取登录用户名
public String getUserNameFromToken(String token){
String userName;
try{
Claims claims=getClaimFromToken(token);
userName=claims.getSubject();
}catch (Exception e){
userName=null;
}
return userName;
}
// 从token中获取荷载
private Claims getClaimFromToken(String token){
Claims claims = null;
try{
claims= Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)))
.build()
.parseClaimsJws(token)
.getBody();
return claims;
}catch (Exception e){
e.printStackTrace();
}
return claims;
}
// 解析 JWT
public String parseToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)))
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
}
//验证token是否失效
public boolean validateToken(String token,UserDetails userDetails){
String userName = getUserNameFromToken(token);
return userName.equals(userDetails.getUsername())&&!isTokenExpired(token);
}
//判断token是否失效
private boolean isTokenExpired(String token){
Date expireDate=getExpiredDateFromToken(token);
return expireDate.before(new Date());
}
// 判断token是否可以被刷新
public boolean canRefresh(String token){
return !isTokenExpired(token);
}
// 根据荷载生成jwt Token
private String generateToken(Map<String,Object> claims){
try{
return Jwts.builder()
.setClaims(claims)
.setExpiration(generateExpirationDate())
.signWith(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)),SignatureAlgorithm.HS512)
.compact();
}catch (ExpiredJwtException e){
e.getClaims();
return null;
}
}
//刷新token
public String refreshToken(String token){
Claims claims = getClaimFromToken(token);
claims.put(CLAIM_KEY_CREATE,new Date());
return generateToken(claims);
}
// 从token中获取过期时间
private Date getExpiredDateFromToken(String token){
Claims claims = getClaimFromToken(token);
return claims.getExpiration();
}
//验证 JWT 有效性
public boolean validateToken(String token) {
try {
String parseToken = parseToken(token);
System.out.println("parseToken:"+parseToken+"-----isTokenExpired:"+isTokenExpired(token));
if (parseToken == null) {
return false;
}else{
return true;
}
// return isTokenExpired(token);
} catch (JwtException | IllegalArgumentException e) {
return false;
}
}
//生成token失效时间
private Date generateExpirationDate(){
return new Date(System.currentTimeMillis()+expiration*1000);
}
}