相关链接
1. pom 引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.27</version>
</dependency>
2. 创建 UserBO 实现 UserDetails(spring security 中)
public class UserBO implements UserDetails {
private String password;
private String username;
private List<GrantedAuthority> authorities;
private boolean accountNonExpired;
private boolean accountNonLocked;
private boolean credentialsNonExpired;
private boolean enabled;
}
3. 创建 service 实现 UserDetailsService
@Service
public class UserDetailsDetailsService implements IUserDetailsService {
@Autowired
IAccountInfoService accountInfoService;
@Override
public UserBO loadUserByUsername(String username) throws UsernameNotFoundException {
AccountInfo ai = accountInfoService.findByUsername(username);
if (null == ai) {
throw new UsernameNotFoundException("用户名/密码错误");
}
return UserBO.trans(ai);
}
}
4. 创建自定义密码校验
@Component
public class CustomPasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
// 自定义加密方法
return rawPassword.toString();
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
String[] pwd = encodedPassword.split("&");
return new BCryptPasswordEncoder().matches(rawPassword.toString() + "&" + pwd[1], pwd[0]);
// 自定义验证方法
}
}
6. 创建 jwt 服务(可以按照自己的来)
public interface IJwtService {
/**
* 用户名
*
* @param token 令牌
* @return 名称
*/
String extractUsername(String token) throws AuthenticationException;
/**
* 验证
*
* @param token 令牌
* @return 结果
*/
Boolean validateToken(String token);
/**
* 获取token
*
* @param payload 信息
* @return token
*/
String generateToken(Object payload);
}
7. 创建 jwt 实例 (可以按照自己的来)
@Service
public class JwtService implements IJwtService {
static final JWTSigner JWT_SIGNER = JWTSignerUtil.hs256("!34ADASfhsrujwstrfhwdg@#$$@#efh3".getBytes());
@Override
public String extractUsername(String token) throws AuthenticationException {
JWTPayload payload = JWTUtil.parseToken(token).getPayload();
if (null != payload) {
return payload.getClaim("username").toString();
}
throw new AuthenticationException();
}
@Override
public Boolean validateToken(String token) {
return JWTUtil.verify(token, JWT_SIGNER);
}
@Override
public String generateToken(Object payload) {
return JWTUtil.createToken(BeanUtil.beanToMap(payload, "id", "username", "authorities"), JWT_SIGNER);
}
}
8. 创建 jwt 过滤器 (可以自定义)
@Component
public class JwtAuthFilter extends OncePerRequestFilter {
@Autowired
private IJwtService jwtService;
@Autowired
IUserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
String token = null;
String username = null;
if(authHeader != null && authHeader.startsWith("Bearer ")){
token = authHeader.substring(7);
username = jwtService.extractUsername(token);
}
if(username != null && SecurityContextHolder.getContext().getAuthentication() == null){
UserDetails details = userDetailsService.loadUserByUsername(username);
if(jwtService.validateToken(token)){
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(details, null, details.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
filterChain.doFilter(request, response);
}
}
9. 创建认证config
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
JwtAuthFilter jwtAuthFilter;
@Autowired
IUserDetailsService userDetailsService;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests((ahrc) ->
ahrc.requestMatchers("/auth/login")
.permitAll()
.requestMatchers("/**")
.authenticated())
.authenticationProvider(authenticationProvider())
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
.sessionManagement((smc) -> smc.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.build();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new CustomPasswordEncoder();
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
}
10. 编写登陆API
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
IJwtService jwtService;
@Autowired
AuthenticationManager authenticationManager;
@PostMapping("/login")
public IResult<?> login(@RequestParam("username") String username, @RequestParam("password") String password) {
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
if(authentication.isAuthenticated()){
Map<String, String> params = new HashMap<>();
params.put("username", username);
params.put("token", jwtService.generateToken(authentication.getPrincipal()));
return ResultVO.success(params);
} else {
throw new UsernameNotFoundException("错误的请求");
}
}
}