前置博客:JWT工具类
数据库:
@Slf4j
@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws ServletException {
log.info("用户访问没有授权资源:{}", e.getMessage());
response.setContentType("application/json;charset=utf-8");
response.setCharacterEncoding("utf-8");
try (PrintWriter out = response.getWriter();) {
Result result = ResultUtil.fail("用户访问未授权资源").setCode(HttpServletResponse.SC_UNAUTHORIZED);
out.write(JsonUtil.obj2String(result));
out.flush();
} catch (IOException exception) {
log.error(e.getMessage());
e.printStackTrace();
}
}
}
第二步:访问受限资源时未登录或未携带正确token时返回信息的EntryPoint
@Slf4j
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws ServletException, IOException {
log.info("登录失败or用户访问资源没有携带正确的token:{}", e.getMessage());
response.setContentType("application/json;charset=utf-8");
response.setCharacterEncoding("utf-8");
try (PrintWriter out = response.getWriter();) {
Result result = ResultUtil.fail("用户访问资源没有携带正确的token").setCode(HttpServletResponse.SC_UNAUTHORIZED);
out.write(JsonUtil.obj2String(result));
out.flush();
} catch (IOException exception) {
log.error(e.getMessage());
e.printStackTrace();
}
}
}
第三步:定义JWT认证过滤器
@Slf4j
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Resource
private JwtUtil jwtUtil;
@Resource
private UserDetailsServiceImpl userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
String token = request.getHeader(jwtUtil.getHeader());
log.info("header token:{}", token);
//如果请求头中有token,则进行解析,并且设置认证信息
if (token != null && token.trim().length() > 0) {
//根据token获取用户名
String username = jwtUtil.getSubjectFromToken(token);
// 验证username,如果验证合法则保存到SecurityContextHolder
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// JWT验证通过,使用Spring Security 管理
if (jwtUtil.validateToken(token, userDetails)) {
//加载用户、角色、权限信息
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
//如果请求头中没有Authorization信息则直接放行
chain.doFilter(request, response);
}
}
第四步:自定义UserDetailsService
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Resource
private UserService userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
MenuItemAuth menuItemAuth = userService.getAuthoritiesPermissions(username);
System.out.println(JsonUtil.obj2String(menuItemAuth));
UserDetails userDetails = org.springframework.security.core.userdetails.User.withUsername(username)
.password(menuItemAuth.getPassword())
.authorities(menuItemAuth.getAuth().split(","))
.build();
//UserDetails userDetails = new org.springframework.security.core.userdetails.User(username, passwordEncoder.encode("1234"),
// AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_vip,user:list,user:update"));
return userDetails;
}
}
相关的代码如下所示:
MenuItem.java
@Getter
@Setter
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class MenuItem {
private Integer id;
private String name;
private String code;
private Integer pid;
}
MenuItemAuth.java
@Getter
@Setter
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MenuItemAuth {
List
第五步:定义SpringSecurity配置类
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityJwtConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Resource
private JwtAccessDeniedHandler jwtAccessDeniedHandler;
@Resource
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Resource
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// 禁用session
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests()
//login 不拦截
.antMatchers("/user/login").permitAll()
.antMatchers("/user/login0").permitAll()
.antMatchers("/init/redis").permitAll()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/").permitAll()
.anyRequest().authenticated();
//用户访问没有授权资源
http.exceptionHandling().accessDeniedHandler(jwtAccessDeniedHandler);
//授权错误信息处理
//用户访问资源没有携带正确的token
http.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint);
// 使用自己定义的拦截机制验证请求是否正确,拦截jwt
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Controller
@RestController
@RequestMapping("/authority")
public class AuthorityController {
@PostMapping("/login")
public Result login(@RequestBody User user) {
// 登陆验证
UsernamePasswordAuthenticationToken token0 =
new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
Authentication authentication = authenticationManager.authenticate(token0);
SecurityContextHolder.getContext().setAuthentication(authentication);
//生成token,返回给客户端
MenuItemAuth menuItemAuth = userService.getAuthoritiesPermissions(user.getUsername());
UserDetails userDetails = org.springframework.security.core.userdetails.User.withUsername(user.getUsername())
.password(menuItemAuth.getPassword())
.authorities(menuItemAuth.getAuth().split(","))
.build();
String token = jwtUtil.generateToken(userDetails, user1.getId() + "");
return ResultUtil.success().setData("token", token);
}
@GetMapping("/fun1")
@PreAuthorize("hasRole("vip")")
public Result fun1() {
return ResultUtil.success("fun1");
}
@GetMapping("/fun2")
@PreAuthorize("hasRole("admin")")
public Result fun2() {
return ResultUtil.success("fun2");
}
@GetMapping("/fun3")
@PreAuthorize("hasAuthority("user:list")")
public Result fun3() {
return ResultUtil.success("fun3");
}
@GetMapping("/fun4")
@PreAuthorize("hasAuthority("user:delete")")
public Result fun4() {
return ResultUtil.success("fun4");
}
}
相关代码
@Service @CacheConfig(cacheManager = "cacheManager") public class UserServiceImpl extends ServiceImplimplements UserService { @Resource RedisService userRedisServiceImpl; @Resource private RoleService roleService; @Resource private UserPermissionService userPermissionService; @Resource private PermissionService permissionService; @Resource private RolePermissionService rolePermissionService; @Override public MenuItemAuth getAuthoritiesPermissions(String username) { List



