基于角色或权限进行访问控制
hasAuthority方法
如果当前的主体具有指定的权限,则返回true,否则返回false
在配置类中设置当前访问地址有哪些权限:
@Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin() // 自定义登录页面.loginPage("/login.html") // 登录页面配置.loginProcessingUrl("/user/login") // 登录访问的路径(只需要写个地址即可,具体的逻辑已经由SpringSecurity进行了实现).defaultSuccessUrl("/index") // 登录成功后跳转的路径.permitAll()// 定义被保护和不被保护的url(被访问的路径是否需要登录).and().authorizeRequests().antMatchers("/", "/hello", "/user/login")// 不认证也可以访问的路径.permitAll()// 使用hasAuthority方法,控制当前登录用户只能拥有指定权限才能访问.antMatchers("/index").hasAuthority("admin") // 拥有admin权限的用户才能访问/index// 其他请求需要登录才能访问.anyRequest().authenticated()// 关闭csrf防护.and().csrf().disable();}
在自定义的UserDetailsService中,从数据库读取用户的权限:
@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 查询数据库获取用户的密码QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();wrapper.eq("username", username);UserInfo userInfo = userInfoMapper.selectOne(wrapper);if(userInfo == null) {// 该用户不存在throw new UsernameNotFoundException("user[" + username + "]不存在");}String password = userInfo.getPassword();BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();String passwordEncode = encoder.encode(password);// 从数据库读取用户的权限Integer userid = userInfo.getUserid();QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();userRoleQueryWrapper.eq("userid", userid);List<UserRole> userRoles = userRoleMapper.selectList(userRoleQueryWrapper); // 获取数据库查询结果// 将数据库查询出的权限转换为GrantedAuthority类型集合List<GrantedAuthority> roleList = new ArrayList<>();userRoles.forEach(userRole -> roleList.add(new SimpleGrantedAuthority(userRole.getRolename())));return new User(username, passwordEncode, roleList);}
验证:
登录没有admin权限的用户,访问/index时会返回 403 Forbidden、
登录有admin权限的用户,可以正常访问/index。
hasAnyAuthority方法
如果当前的主体有任何提供的权限的话(以逗号分隔的权限列表),就返回true
示例:
@Overrideprotected void configure(HttpSecurity http) throws Exception {// .......// 使用hasAnyAuthority方法, 拥有 admin或者 test 权限的用户都可以访问 /index.antMatchers("/index").hasAnyAuthority("admin,test")// .....}
hasRole方法
如果用户具备给定角色就允许访问,否则就出现403。如果当前主体具有指定的角色就返回true。
角色其实是带有
ROLE_前缀的权限。
示例:
// 当前登录用户只能拥有指定角色才能访问// 底层中会将role前面拼上 ROLE_,即用户真正应该拥有的的权限为:ROLE_admin.antMatchers("/index").hasRole("admin")
自定义的UserDetailsService在添加用户权限时,需要加上ROLE_前缀,或者使用UserBuilder的roles(角色名)方法创建用户并添加角色:
// 查询数据库获取用户的权限List<GrantedAuthority> roleList = new ArrayList<>();userRoles.forEach(userRole ->// 权限添加ROLE_前缀roleList.add(new SimpleGrantedAuthority("ROLE_" + userRole.getRolename())));
hasAnyRole方法
如果用户拥有任何一个给定的角色就允许访问
示例:
// 拥有admin或者test角色的用户才能访问/index,即权限为(ROLE_admin、ROLE_test).antMatchers("/index").hasAnyRole("admin,test")
