历览千载书,时时见遗烈。这篇文章主要讲述SpringBoot+SpringSecurity系列八:整合JWT#yyds干货盘点#相关的知识,希望能为你提供帮助。
数据库:
文章图片
第一步:当用户在没有授权时返回的指定信息的Handler
@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< MenuItem> menuItemList; /** * 用户的密码 */ private String password; /** * 用户角色code+权限code的字符串 */ private String auth;
@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");
【SpringBoot+SpringSecurity系列八(整合JWT#yyds干货盘点#)】相关代码
@Service
@CacheConfig(cacheManager = "cacheManager")
public class UserServiceImpl extends ServiceImpl<
UserMapper, User>
implements UserService
@Resource
RedisService<
User>
userRedisServiceImpl;
@Resource
private RoleService roleService;
@Resource
private UserPermissionService userPermissionService;
@Resource
private PermissionService permissionService;
@Resource
private RolePermissionService rolePermissionService;
@Override
public MenuItemAuth getAuthoritiesPermissions(String username)
List<
MenuItem>
menuItemList = new ArrayList<
>
();
//根据用户名查找用户
User user = baseMapper.selectOne(new QueryWrapper<
User>
()
.select("id", "username", "password", "nickname", "email", "tel", "gender", "birth", "avatar", "role_id")
.eq("username", username)
.eq("status", BaseStatus.Status.ok));
//查找角色
Role role = roleService.getOne(new QueryWrapper<
Role>
()
.select("id", "name", "code")
.eq("status", BaseStatus.Status.ok)
.eq("id", user.getRoleId()));
menuItemList.add(MenuItem.builder()
.id(role.getId())
.name(role.getName())
.code(role.getCode())
.pid(-1) // -1表示是角色
.build());
String authorities = "ROLE_" + role.getCode() + ",";
// 当前用户拥有的权限permission的id的集合
List<
Integer>
permissionIdList = new ArrayList<
>
();
//在tb_role_permission中查找Role所对应的角色
List<
RolePermission>
rolePermissionList = rolePermissionService.list(new QueryWrapper<
RolePermission>
()
.select("permission_id")
.eq("role_id", role.getId())
.eq("status", BaseStatus.Status.ok));
List<
Integer>
pid1 = rolePermissionList.stream().map(item ->
item.getPermissionId()).collect(Collectors.toList());
permissionIdList.addAll(pid1);
//在tb_user_permission中查找权限
List<
UserPermission>
userPermissionList = userPermissionService.list(new QueryWrapper<
UserPermission>
()
.select("permission_id")
.eq("user_id", user.getId())
.eq("status", BaseStatus.Status.ok));
List<
Integer>
pid2 = userPermissionList.stream().map(item ->
item.getPermissionId()).collect(Collectors.toList());
permissionIdList.addAll(pid2);
//查找具体的权限信息
List<
Permission>
permissionList = permissionService.list(new QueryWrapper<
Permission>
()
.select("id", "name", "code", "pid")
.eq("status", BaseStatus.Status.ok)
.in("id", permissionIdList));
List<
MenuItem>
permissionMenuItemList = permissionList.stream().map(item ->
MenuItem.builder()
.id(item.getId())
.name(item.getName())
.code(item.getCode())
.pid(item.getPid())
.build()).collect(Collectors.toList());
menuItemList.addAll(permissionMenuItemList);
String permissions = permissionList.stream().map(item ->
item.getCode() + ",").collect(Collectors.joining());
System.out.println(permissions);
//去掉最后一个逗号
permissions = permissions.substring(0, permissions.length() - 1);
System.out.println(authorities + permissions);
MenuItemAuth res = MenuItemAuth.builder()
.menuItemList(menuItemList)
.auth(authorities + permissions)
.password(user.getPassword())
.build();
return res;
推荐阅读
- 鸿蒙基于开放式测试方案发布原子化服务的实战
- #yyds干货盘点#关于 Java 的可变参数你真的了解吗()
- LVS负载均衡群集与NAT模式LVS负载均衡部署
- Go 语言入门很简单 -- Go 语言转化为 JSON #私藏项目实操分享#
- #私藏项目实操分享# ABAP 调用第三方 API,遇到乱码该怎么办()
- Apache 网页与安全优化
- #yyds干货盘点#制作简易计算器
- python 全解坦克大战 辅助类 附完整代码雏形
- 关于C#/.NET程序中的应用程序域程序集线程区域性的个人理解