让我为您详细讲解一下“Springboot+SpringSecurity+JWT实现用户登录和权限认证示例”的攻略。
首先,需要安装以下工具:
- Java开发环境
- Maven构建工具
然后,我们需要按照以下步骤进行实现:
1.添加依赖
在pom.xml文件中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2.配置JWT
在配置类中添加JWT的秘钥,过期时间等信息:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final String SECRET_KEY = "secretKey";
private static final long EXPIRATION_TIME = 864_000_000; // 10 days
@Bean
public JwtBuilder jwtBuilder() {
return Jwts.builder().setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(Keys.hmacShaKeyFor(SECRET_KEY.getBytes()));
}
}
3.实现用户校验
自定义UserDetailsService,实现用户校验,并将其注入到Spring Security中:
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserRepository userRepository;
public UserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<User> userOptional = userRepository.findByUsername(username);
if (userOptional.isEmpty()) {
throw new UsernameNotFoundException("User not found");
}
User user = userOptional.get();
return new UserPrincipal(user.getUsername(), user.getPassword(), Collections.emptyList());
}
}
其中,User是自定义的用户实体类,UserRepository是自定义的用户DAO层。
4.实现AuthenticationProvider
自定义一个AuthenticationProvider,实现用户自定义校验:
@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String TOKEN_PREFIX = "Bearer ";
private final JwtParser jwtParser;
public JwtAuthenticationProvider(JwtParser jwtParser) {
this.jwtParser = jwtParser;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String authorizationHeader = request.getHeader(AUTHORIZATION_HEADER);
if (StringUtils.isEmpty(authorizationHeader) || !authorizationHeader.startsWith(TOKEN_PREFIX)) {
throw new BadCredentialsException("Authorization token not found");
}
String token = authorizationHeader.replace(TOKEN_PREFIX, "");
Claims claims = jwtParser.parseClaimsJws(token).getBody();
String username = claims.getSubject();
if (username == null) {
throw new BadCredentialsException("Invalid token");
}
return new UsernamePasswordAuthenticationToken(username, "", Collections.emptyList());
}
@Override
public boolean supports(Class<?> aClass) {
return JwtAuthenticationToken.class.isAssignableFrom(aClass);
}
}
其中,JwtAuthenticationToken是自定义的Token类,JwtParser是JWT解析器。
5.配置Spring Security
在WebSecurityConfigurerAdapter子类中重写configure方法,配置拦截规则和认证方式:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
private final JwtBuilder jwtBuilder;
private final JwtParser jwtParser;
public SecurityConfig(UserDetailsService userDetailsService, JwtBuilder jwtBuilder, JwtParser jwtParser) {
this.userDetailsService = userDetailsService;
this.jwtBuilder = jwtBuilder;
this.jwtParser = jwtParser;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager(), jwtBuilder))
.addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtParser))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new JwtAuthenticationProvider(jwtParser));
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
其中,JwtAuthenticationFilter是自定义的Token过滤器,JwtAuthorizationFilter是自定义的权限过滤器。
至此,我们已经成功地实现了Springboot+SpringSecurity+JWT的用户登录和权限认证。
下面,我们来看一下示例代码:
示例1:用户登录
@PostMapping("/login")
public LoginResponse login(@RequestBody LoginRequest request) {
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
String token = jwtBuilder.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.setSubject(request.getUsername())
.compact();
return new LoginResponse(token);
}
其中,LoginRequest是请求实体类,LoginResponse是响应实体类。
示例2:根据权限获取用户信息
@GetMapping("/me")
@PreAuthorize("hasAnyRole('ADMIN')")
public UserResponse me() {
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
User user = userRepository.findByUsername(userDetails.getUsername()).orElseThrow(() -> new RuntimeException("User not found"));
return new UserResponse(user.getUsername(), user.getEmail());
}
其中,PreAuthorize是Spring Security的注解,表示请求需要具有特定的角色或权限。
希望这段内容能够对您有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Springboot+SpringSecurity+JWT实现用户登录和权限认证示例 - Python技术站