基于角色或权限进行访问控制

hasAuthority方法

如果当前的主体具有指定的权限,则返回true,否则返回false

在配置类中设置当前访问地址有哪些权限:

  1. @Override
  2. protected void configure(HttpSecurity http) throws Exception {
  3. http.formLogin() // 自定义登录页面
  4. .loginPage("/login.html") // 登录页面配置
  5. .loginProcessingUrl("/user/login") // 登录访问的路径(只需要写个地址即可,具体的逻辑已经由SpringSecurity进行了实现)
  6. .defaultSuccessUrl("/index") // 登录成功后跳转的路径
  7. .permitAll()
  8. // 定义被保护和不被保护的url(被访问的路径是否需要登录)
  9. .and()
  10. .authorizeRequests()
  11. .antMatchers("/", "/hello", "/user/login")// 不认证也可以访问的路径
  12. .permitAll()
  13. // 使用hasAuthority方法,控制当前登录用户只能拥有指定权限才能访问
  14. .antMatchers("/index").hasAuthority("admin") // 拥有admin权限的用户才能访问/index
  15. // 其他请求需要登录才能访问
  16. .anyRequest().authenticated()
  17. // 关闭csrf防护
  18. .and().csrf().disable();
  19. }

在自定义的UserDetailsService中,从数据库读取用户的权限:

  1. @Override
  2. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  3. // 查询数据库获取用户的密码
  4. QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
  5. wrapper.eq("username", username);
  6. UserInfo userInfo = userInfoMapper.selectOne(wrapper);
  7. if(userInfo == null) {
  8. // 该用户不存在
  9. throw new UsernameNotFoundException("user[" + username + "]不存在");
  10. }
  11. String password = userInfo.getPassword();
  12. BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
  13. String passwordEncode = encoder.encode(password);
  14. // 从数据库读取用户的权限
  15. Integer userid = userInfo.getUserid();
  16. QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
  17. userRoleQueryWrapper.eq("userid", userid);
  18. List<UserRole> userRoles = userRoleMapper.selectList(userRoleQueryWrapper); // 获取数据库查询结果
  19. // 将数据库查询出的权限转换为GrantedAuthority类型集合
  20. List<GrantedAuthority> roleList = new ArrayList<>();
  21. userRoles.forEach(userRole -> roleList.add(new SimpleGrantedAuthority(userRole.getRolename())));
  22. return new User(username, passwordEncode, roleList);
  23. }

验证:

登录没有admin权限的用户,访问/index时会返回 403 Forbidden、

登录有admin权限的用户,可以正常访问/index。

hasAnyAuthority方法

如果当前的主体有任何提供的权限的话(以逗号分隔的权限列表),就返回true

示例:

  1. @Override
  2. protected void configure(HttpSecurity http) throws Exception {
  3. // .......
  4. // 使用hasAnyAuthority方法, 拥有 admin或者 test 权限的用户都可以访问 /index
  5. .antMatchers("/index").hasAnyAuthority("admin,test")
  6. // .....
  7. }

hasRole方法

如果用户具备给定角色就允许访问,否则就出现403。如果当前主体具有指定的角色就返回true。

角色其实是带有 ROLE_前缀的权限。

示例:

  1. // 当前登录用户只能拥有指定角色才能访问
  2. // 底层中会将role前面拼上 ROLE_,即用户真正应该拥有的的权限为:ROLE_admin
  3. .antMatchers("/index").hasRole("admin")

自定义的UserDetailsService在添加用户权限时,需要加上ROLE_前缀,或者使用UserBuilderroles(角色名)方法创建用户并添加角色:

  1. // 查询数据库获取用户的权限
  2. List<GrantedAuthority> roleList = new ArrayList<>();
  3. userRoles.forEach(userRole ->
  4. // 权限添加ROLE_前缀
  5. roleList.add(new SimpleGrantedAuthority("ROLE_" + userRole.getRolename())));

hasAnyRole方法

如果用户拥有任何一个给定的角色就允许访问

示例:

  1. // 拥有admin或者test角色的用户才能访问/index,即权限为(ROLE_admin、ROLE_test)
  2. .antMatchers("/index").hasAnyRole("admin,test")