引入依赖
引入依赖(实现拦截):
java
<!--引入springsecurity的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JWT相关 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
自定义登录逻辑
实现框架默认的UserDetailsService 自定义登录逻辑:
java
@Service
public class MyDetailsService implements UserDetailsService {
@Resource
private SysUserMapper sysUserMapper;
// 自定义认证逻辑
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 1.构造查询条件
QueryWrapper<SysUserDO> wrapper = new QueryWrapper<SysUserDO>().eq("user_account", username);
// 2.查询用户
SysUserDO user = sysUserMapper.selectOne(wrapper);
// 3.封装为UserDetails对象
UserDetails userDetails = User
.withUsername(user.getUserName())
.password(user.getUserPassword())
.authorities("admin")
.build();
// 4.返回封装好的UserDetails对象
return userDetails;
}
}
配置主配置类
配置主配置类(实现鉴权):
java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
MyDetailsService myDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
// return new BCryptPasswordEncoder();
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myDetailsService)
.passwordEncoder(passwordEncoder());
// auth.inMemoryAuthentication()
// .withUser("user").password("{noop}password").roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.successHandler(new LoginAuthenticationSuccessHandler())
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
//跨站点请求伪造
.csrf()
.disable()
.addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
;
}
/** 拦截器 **/
@Bean
public TokenAuthenticationFilter tokenAuthenticationFilter() {
return new TokenAuthenticationFilter();
}
}
配置鉴权成功处理类
配置鉴权成功处理类(AuthenticationSuccessHandler)实现返回token:
java
@Component
@Slf4j
public class LoginAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
// 生成 token
String username = userDetails.getUsername();
String token = JwtUtil.createJWT(UUID.randomUUID().toString(), userDetails.getUsername(),
3600L * 1000 * 6);
// 返回结果
log.info("==> 用户认证成功, username: {}, token: {}", username, token);
// 将token存储到HTTP响应头中
response.setHeader(HttpConstant.X_ACCESS_TOKEN, token);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
// 返回响应体
PrintWriter writer = response.getWriter();
//构造响应
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(userDetails);
stringObjectMap.put("token",token);
writer.write(new ObjectMapper().writeValueAsString(Result.buildSuccess(stringObjectMap)));
writer.flush();
writer.close();
}
}
配置Filter
配置Filter实现token:
java
@Slf4j
public class TokenAuthenticationFilter extends OncePerRequestFilter {
@Resource
private MyDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
ObjectMapper objectMapper = new ObjectMapper();
response.setCharacterEncoding("UTF-8");
String token = request.getHeader(HttpConstant.X_ACCESS_TOKEN);
String userName = null;
if (StringUtils.isNotBlank(token)) {
try {
userName = JwtUtil.parseJWT(token).getSubject();
} catch (Exception e) {
response.getWriter().write(objectMapper.writeValueAsString(Result.buildError("token校验失败!")));
return;
}
if (StringUtils.isNotBlank(userName)) {
// && Objects.isNull(SecurityContextHolder.getContext().getAuthentication())
UserDetails userDetails = null;
userDetails = userDetailsService.loadUserByUsername(userName);
// 将用户信息存入 authentication ThreadLocal,方便后续校验
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null,
userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// 用于鉴权
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
// 继续执行下一个过滤器
filterChain.doFilter(request, response);
}
}