feat:
- 完善Spring Security
This commit is contained in:
parent
23f65a4e5d
commit
45da0753f6
6
pom.xml
6
pom.xml
@ -132,6 +132,12 @@
|
|||||||
<artifactId>mockito-core</artifactId>
|
<artifactId>mockito-core</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains</groupId>
|
||||||
|
<artifactId>annotations</artifactId>
|
||||||
|
<version>RELEASE</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@ -31,16 +31,17 @@ public class SecurityConfig {
|
|||||||
public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtUtil jwtUtil, JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint) throws Exception {
|
public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtUtil jwtUtil, JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint) throws Exception {
|
||||||
http
|
http
|
||||||
.csrf(AbstractHttpConfigurer::disable)
|
.csrf(AbstractHttpConfigurer::disable)
|
||||||
|
.sessionManagement(AbstractHttpConfigurer::disable)
|
||||||
.exceptionHandling(ex -> ex
|
.exceptionHandling(ex -> ex
|
||||||
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
|
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
|
||||||
.accessDeniedHandler((request, response, accessDeniedException) -> response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied"))
|
.accessDeniedHandler((request, response, accessDeniedException) ->
|
||||||
|
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied"))
|
||||||
)
|
)
|
||||||
.authorizeHttpRequests(auth -> auth
|
.authorizeHttpRequests(auth -> auth
|
||||||
.requestMatchers("/login").permitAll()
|
.requestMatchers("/login").permitAll()
|
||||||
.requestMatchers("/users", "/users/**").authenticated()
|
.requestMatchers("/users", "/users/**").authenticated()
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
)
|
)
|
||||||
.sessionManagement(AbstractHttpConfigurer::disable)
|
|
||||||
.addFilterBefore(
|
.addFilterBefore(
|
||||||
new JwtAuthenticationFilter(jwtUtil, jwtUserDetailsService),
|
new JwtAuthenticationFilter(jwtUtil, jwtUserDetailsService),
|
||||||
UsernamePasswordAuthenticationFilter.class
|
UsernamePasswordAuthenticationFilter.class
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
@ -32,32 +34,34 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
private final UserDetailsService userDetailsService;
|
private final UserDetailsService userDetailsService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request,
|
protected void doFilterInternal(@NotNull HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
@NotNull HttpServletResponse response,
|
||||||
FilterChain filterChain) throws ServletException, IOException {
|
@NotNull FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
|
||||||
String token = getTokenFromRequest(request);
|
String token = getTokenFromRequest(request);
|
||||||
log.info("token: {}", token);
|
log.info("token: {}", token);
|
||||||
|
|
||||||
if (StringUtils.hasText(token) && jwtUtil.validateToken(token)) {
|
if (StringUtils.hasText(token) && jwtUtil.validateToken(token)) {
|
||||||
// get username from token
|
// 解析token获取username
|
||||||
String username = jwtUtil.parseToken(token).getSubject();
|
String username = jwtUtil.parseToken(token).getSubject();
|
||||||
|
log.info("username: {}", username);
|
||||||
|
|
||||||
// load the user associated with token
|
// 根据token获取的username,加载当前登录中userDetails
|
||||||
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||||
|
log.info("userDetails: {}", userDetails);
|
||||||
|
|
||||||
UsernamePasswordAuthenticationToken authenticationToken
|
UsernamePasswordAuthenticationToken authenticationToken
|
||||||
= new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
= new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||||
|
log.info("authenticationToken: {}", authenticationToken);
|
||||||
|
|
||||||
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTokenFromRequest(HttpServletRequest request) {
|
private @Nullable String getTokenFromRequest(HttpServletRequest request) {
|
||||||
String bearerToken = request.getHeader("Authorization");
|
String bearerToken = request.getHeader("Authorization");
|
||||||
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
|
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
|
||||||
return bearerToken.substring(7);
|
return bearerToken.substring(7);
|
||||||
|
|||||||
@ -52,7 +52,7 @@ public class JwtUtil {
|
|||||||
public String generateToken(Authentication authentication, boolean isRememberMe) {
|
public String generateToken(Authentication authentication, boolean isRememberMe) {
|
||||||
// 1. 构建签名密钥
|
// 1. 构建签名密钥
|
||||||
Key key = key();
|
Key key = key();
|
||||||
|
log.info("key: {}", key);
|
||||||
// 2. 当前时间
|
// 2. 当前时间
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
|
|
||||||
@ -63,10 +63,10 @@ public class JwtUtil {
|
|||||||
// 4. 构建 JWT
|
// 4. 构建 JWT
|
||||||
String username = authentication.getName();
|
String username = authentication.getName();
|
||||||
JwtBuilder builder = Jwts.builder()
|
JwtBuilder builder = Jwts.builder()
|
||||||
.setSubject(username)
|
.setSubject(username)
|
||||||
.setIssuedAt(now)
|
.setIssuedAt(now)
|
||||||
.setExpiration(expiration)
|
.setExpiration(expiration)
|
||||||
.signWith(key);
|
.signWith(key);
|
||||||
|
|
||||||
// 5. 返回生成的 token 字符串
|
// 5. 返回生成的 token 字符串
|
||||||
return builder.compact();
|
return builder.compact();
|
||||||
@ -81,12 +81,12 @@ public class JwtUtil {
|
|||||||
public Claims parseToken(String token) {
|
public Claims parseToken(String token) {
|
||||||
try {
|
try {
|
||||||
Key key = key();
|
Key key = key();
|
||||||
|
log.info("key: {}", key);
|
||||||
return Jwts.parserBuilder()
|
return Jwts.parserBuilder()
|
||||||
.setSigningKey(key)
|
.setSigningKey(key)
|
||||||
.build()
|
.build()
|
||||||
.parseClaimsJws(token)
|
.parseClaimsJws(token)
|
||||||
.getBody();
|
.getBody();
|
||||||
} catch (ExpiredJwtException e) {
|
} catch (ExpiredJwtException e) {
|
||||||
log.error("Token 已过期: {}", token, e);
|
log.error("Token 已过期: {}", token, e);
|
||||||
throw new JwtException("Token 已过期", e);
|
throw new JwtException("Token 已过期", e);
|
||||||
@ -106,10 +106,17 @@ public class JwtUtil {
|
|||||||
* @return true-token正确 false-token错误
|
* @return true-token正确 false-token错误
|
||||||
*/
|
*/
|
||||||
public boolean validateToken(String token) {
|
public boolean validateToken(String token) {
|
||||||
|
Key key = key();
|
||||||
|
log.info("token: {}; key: {}", token, key);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Jwts.parserBuilder().setSigningKey(key()).build().parseClaimsJws(token);
|
Jwts.parserBuilder()
|
||||||
|
.setSigningKey(key)
|
||||||
|
.build()
|
||||||
|
.parseClaimsJws(token);
|
||||||
return true;
|
return true;
|
||||||
} catch (JwtException e) {
|
} catch (JwtException e) {
|
||||||
|
log.error("Token <UNK>: {}", token, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,32 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="asia.yulinling.workflow.mapper.UserMapper">
|
<mapper namespace="asia.yulinling.workflow.mapper.UserMapper">
|
||||||
<insert id="saveUser">
|
|
||||||
INSERT INTO `wk_user` (`username`,
|
|
||||||
`nickname`,
|
|
||||||
`password`,
|
|
||||||
`salt`,
|
|
||||||
`email`,
|
|
||||||
`phone`,
|
|
||||||
`status`,
|
|
||||||
`create_time`,
|
|
||||||
`last_login_time`,
|
|
||||||
`update_time`)
|
|
||||||
VALUES (#{user.name},
|
|
||||||
#{user.nickname},
|
|
||||||
#{user.password},
|
|
||||||
#{user.salt},
|
|
||||||
#{user.email},
|
|
||||||
#{user.phone},
|
|
||||||
#{user.status},
|
|
||||||
#{user.createTime},
|
|
||||||
#{user.lastLoginTime},
|
|
||||||
#{user.updateTime})
|
|
||||||
</insert>
|
|
||||||
|
|
||||||
<delete id="deleteById">
|
|
||||||
DELETE
|
|
||||||
FROM `wk_user`
|
|
||||||
WHERE id = #{id}
|
|
||||||
</delete>
|
|
||||||
</mapper>
|
</mapper>
|
||||||
@ -52,10 +52,6 @@ class JwtUtilTest {
|
|||||||
.build();
|
.build();
|
||||||
Authentication authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
|
Authentication authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
|
||||||
String token = jwtUtil.generateToken(authentication, false);
|
String token = jwtUtil.generateToken(authentication, false);
|
||||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
|
||||||
String rawPassword = "admin";
|
|
||||||
String encodedPassword = encoder.encode(rawPassword);
|
|
||||||
System.out.println(encodedPassword);
|
|
||||||
assertTrue(jwtUtil.validateToken(token));
|
assertTrue(jwtUtil.validateToken(token));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user