SpringSecurity+JWT 角色权限
时间: 2024-02-01 14:02:18 浏览: 222
springsecurity角色和权限
Spring Security是一个基于Spring的安全框架,它提供了一组可以在Spring应用程序中配置的安全服务。JWT(JSON Web Token)是一种用于在网络应用间传递信息的简洁的、URL安全的表述性声明规范。JWT通过在用户和服务器之间传递安全令牌来实现身份验证和授权。结合使用Spring Security和JWT可以实现角色权限控制。
具体实现步骤如下:
1.添加Spring Security和JWT的依赖。
2.创建一个实现UserDetailsService接口的类,用于从数据库中获取用户信息。
3.创建一个实现JwtTokenUtil接口的类,用于生成和解析JWT。
4.创建一个实现AuthenticationEntryPoint接口的类,用于处理未授权的请求。
5.创建一个实现AccessDeniedHandler接口的类,用于处理授权失败的请求。
6.创建一个继承WebSecurityConfigurerAdapter的类,用于配置Spring Security。
7.在配置类中添加一个JwtAuthenticationTokenFilter过滤器,用于验证JWT。
8.在需要进行权限控制的方法上添加@PreAuthorize注解,指定需要的角色或权限。
示例代码如下:
```java
// UserDetailsService实现类
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserService userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.getUserByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("用户名不存在");
}
return new JwtUserDetails(user);
}
}
// JwtTokenUtil实现类
@Component
public class JwtTokenUtilImpl implements JwtTokenUtil {
private static final String CLAIM_KEY_USERNAME = "sub";
private static final String CLAIM_KEY_CREATED = "created";
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
@Override
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername());
claims.put(CLAIM_KEY_CREATED, new Date());
return generateToken(claims);
}
@Override
public String getUsernameFromToken(String token) {
String username;
try {
Claims claims = getClaimsFromToken(token);
username = claims.getSubject();
} catch (Exception e) {
username = null;
}
return username;
}
@Override
public boolean validateToken(String token, UserDetails userDetails) {
JwtUserDetails user = (JwtUserDetails) userDetails;
String username = getUsernameFromToken(token);
return username.equals(user.getUsername()) && !isTokenExpired(token);
}
private Claims getClaimsFromToken(String token) {
Claims claims;
try {
claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
claims = null;
}
return claims;
}
private boolean isTokenExpired(String token) {
Date expirationDate = getExpirationDateFromToken(token);
return expirationDate.before(new Date());
}
private Date getExpirationDateFromToken(String token) {
Claims claims = getClaimsFromToken(token);
return claims.getExpiration();
}
private String generateToken(Map<String, Object> claims) {
Date expirationDate = new Date(System.currentTimeMillis() + expiration * 1000);
return Jwts.builder()
.setClaims(claims)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
}
// AuthenticationEntryPoint实现类
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "未授权的请求");
}
}
// AccessDeniedHandler实现类
@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "权限不足");
}
}
// 配置类
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private JwtAccessDeniedHandler jwtAccessDeniedHandler;
@Autowired
private JwtTokenFilter jwtTokenFilter;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(jwtAccessDeniedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
}
// JwtAuthenticationTokenFilter过滤器
@Component
public class JwtTokenFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String authToken = authHeader.substring(7);
String username = jwtTokenUtil.getUsernameFromToken(authToken);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
chain.doFilter(request, response);
}
}
// 在需要进行权限控制的方法上添加@PreAuthorize注解
@PreAuthorize("hasAnyRole('ADMIN','USER')")
public void someMethod() {
// do something
}
```
阅读全文