目录
Spring Security授权_编写查询权限方法
Spring Security授权_配置类设置访问控制
Spring Security授权_自定义访问控制逻辑
Spring Security授权_注解设置访问控制
Spring Security授权_在前端进行访问控制
Spring Security授权_403处理方案
在认证后进行授权需要根据用户id查询到用户的权限,写法如下:
1、编写用户、角色、权限实体类
// 不要命名为User,避免和Spring Security提供的User混淆 @Data public class Users { private Integer uid; private String username; private String password; private String phone; } // 角色 @Data public class Role { private String rid; private String roleName; private String roleDesc; } // 权限 @Data public class Permission { private String pid; private String permissionName; private String url; }
2、编写UserMapper接口
// 根据用户名查询权限 List
findPermissionByUsername(String username); 3、在resources目录中编写UsersMapper的映射文件
4、测试方法
@SpringBootTest public class UsersMapperTest { @Autowired private UsersMapper usersMapper; @Test public void testFindPermissionByUsername(){ List
baizhan = usersMapper.findPermissionByUsername("tong"); baizhan.forEach(System.out::println); } } 5、修改认证逻辑,认证成功后给用户授权
// 自定义认证逻辑 @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1.构造查询条件 QueryWrapper
wrapper = new QueryWrapper ().eq("username",username); // 2.查询用户 Users users = userMapper.selectOne(wrapper); if (users == null){ return null; } // 3.查询用户权限 List permissions = userMapper.findPermissionByUsername(username); // 4.将自定义权限集合转为Security的权限类型集合 List grantedAuthorities = new ArrayList<>(); for (Permission permission : permissions) { grantedAuthorities.add(new SimpleGrantedAuthority(permission.getUrl())); } // 5.封装为UserDetails对象 UserDetails userDetails = User.withUsername(users.getUsername()) .password(users.getPassword()) .authorities(grantedAuthorities) .build(); // 6.返回封装好的UserDetails对象 return userDetails; }
在给用户授权后,我们就可以给系统中的资源设置访问控制,即拥 有什么权限才能访问什么资源。
1、编写控制器类,添加控制器方法资源
@RestController public class MyController { @GetMapping("/reportform/find") public String findReportForm() { return "查询报表"; } @GetMapping("/salary/find") public String findSalary() { return "查询工资"; } @GetMapping("/staff/find") public String findStaff() { return "查询员工"; } }
2、修改Security配置类
// 权限拦截配置 http.authorizeRequests() .antMatchers("/login.html").permitAll() //表示任何权限都可以访问 .antMatchers("/reportform/find").hasAnyAuthority("/reportform/find") // 给资源配置需要的权限 .antMatchers("/salary/find").hasAnyAuthority("/salary/find") .antMatchers("/staff/find").hasAnyAuthority("/staff/find") .anyRequest().authenticated(); //表示任何请求都需要认证后才能访问
3、测试访问资源,由于没有权限被拦截访问时会抛出403异常
如果资源数量很多,一条条配置需要的权限效率较低。我们可以自 定义访问控制逻辑,即访问资源时判断用户是否具有名为该资源 URL的权限。
1、自定义访问控制逻辑
@Service public class MyAuthorizationService { // 自定义访问控制逻辑,返回值为是否可以访问资源 public boolean hasPermission(HttpServletRequest request,Authentication authentication){ // 获取会话中的登录用户 Object principal = authentication.getPrincipal(); if (principal instanceof UserDetails){ // 获取登录用户的权限 Collection extends GrantedAuthority> authorities = ((UserDetails)principal).getAuthorities(); // 获取请求的URL路径 String uri = request.getRequestURI(); // 将URL路径封装为权限对象 SimpleGrantedAuthority authority = new SimpleGrantedAuthority(uri); // 判断用户的权限集合是否包含请求的URL权限对象 return authorities.contains(authority); } return false; } }
2、在配置文件中使用自定义访问控制逻辑
// 权限拦截配置 http.authorizeRequests() .antMatchers("/login.html").permitAll() //表示任何权限都可以访问 // 任何请求都使用自定义访问控制逻辑 .anyRequest().access("@myAuthorizationService.hasPermission(request,authentication)" );
除了配置类,在SpringSecurity中提供了一些访问控制的注解。这 些注解默认都是不可用的,需要开启后使用。
@Secured
该注解是基于角色的权限控制,要求UserDetails中的权限名必须以 ROLE_ 开头。
1、在配置类开启注解使用
@SpringBootApplication @MapperScan("com.tong.mysecurity.mapper") @EnableGlobalMethodSecurity(securedEnabled=true) public class MysecurityApplication { public static void main(String[] args) { SpringApplication.run(MysecurityApplication.class, args); } }
2、在控制器方法上添加注解
@Secured("ROLE_reportform") @GetMapping("/reportform/find") public String findReportForm() { return "查询报表"; }
@PreAuthorize
该注解可以在方法执行前判断用户是否具有权限
1、在配置类开启注解使用
@SpringBootApplication @MapperScan("com.tong.mysecurity.mapper") @EnableGlobalMethodSecurity(prePostEnabled = true) public class MysecurityApplication { public static void main(String[] args) { SpringApplication.run(MysecurityApplication.class, args); } }
2、在控制器方法上添加注解
@PreAuthorize("hasAnyAuthority('/reportform/find')") @GetMapping("/reportform/find") public String findReportForm() { return "查询报表"; }
SpringSecurity可以在一些视图技术中进行控制显示效果。例如 Thymeleaf中,只有登录用户拥有某些权限才会展示一些菜单。
1、在pom中引入Spring Security和Thymeleaf的整合依赖
org.thymeleaf.extras thymeleaf-extras-springsecurity5 2、在Thymeleaf中使用Security标签,控制前端的显示内容
主页面 主页面
退出登录3、这样面对不同权限的用户,前端可以显示不同的菜单
使用Spring Security时经常会看见403(无权限),这样的页面很 不友好,我们可以自定义403异常处理方案:
1、编写权限不足页面 noPermission.html
权限不足 您的权限不足,请联系管理员!
2、编写权限不足处理类
public class MyAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { response.sendRedirect("/noPermission.html"); } }
3、在Spring Security配置文件中配置异常处理
//异常处理 http.exceptionHandling(). accessDeniedHandler(new MyAccessDeniedHandler());