1、SpringSecurity授权
授权即认证通过后,系统给用户赋予一定的权限,用户只能根据权限访问系统中的某些资源。RBAC是业界普遍采用的授权方式,它有两种解释:
Role-Based Access Control
基于角色的访问控制,即按角色进行授权。比如在企业管理系统中,主体角色为总经理可以查询企业运营报表
Resource-Based Access Control
基于资源的访问控制,即按资源(或权限)进行授权。比如在企业管理系统中,用户必须 具有查询报表权限才可以查询企业运营报表
2、权限表设计
用户角色,角色权限都是多对多关系,即一个用户拥有多个角色,一个角色属于多个用户;一个角色拥有多个权限,一个权限属于多个角色。这种方式需要指定用户有哪些角色,而角色又有哪些权限。
3、自定义查询权限
@Service
public class MySecurityService implements UserDetailsService {
@Autowired
@Qualifier(value = "userMapper")
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 1、查询条件
QueryWrapper<Users> wrapper = new QueryWrapper<Users>().eq("username", username);
// 2、查询用户
Users users = userMapper.selectOne(wrapper);
if(users==null){
return null;
}
// 3.查询用户所有权限
List<Permission> permissions = userMapper.findPermissionByUsername(username);
// 4.将自定义的权限集合转为Security的权限类型集合
List<GrantedAuthority> list = new ArrayList<>();
for (Permission permission:permissions) {
list.add(new SimpleGrantedAuthority(permission.getUrl()));
}
// 3、封装UserDetails对象
UserDetails userDetails = User.withUsername(users.getUsername()).password(users.getPassword()).authorities(list).build();
return userDetails;
}
}
3.1自定义访问权限
根据请求的路径进行拦截,如果user没有访问url的权限则状态码为403
// 需要认证的资源
http.authorizeHttpRequests()
.antMatchers("/login.html").permitAll()//登录页不需要认证
.antMatchers("/fail").permitAll()//失败页面不需要认证
//需要认证的权限
.antMatchers("/reportform/find").hasAuthority("/reportform/find")
.antMatchers("/salary/find").hasAuthority("/salary/find")
.antMatchers("/tax/find").hasAuthority("/tax/find")
.anyRequest().authenticated();//其余所有请求都需要认证
@Secured
通过@Secured注解添加访问权限(权限必须以ROLE_开头)不常用
@SpringBootApplication
@MapperScan
@EnableGlobalMethodSecurity(securedEnabled = true)//开启secured注解扫描
public class SpringSecurity2Application {
public static void main(String[] args) {
SpringApplication.run(SpringSecurity2Application.class, args);
}
}
// 对权限进行拦截必须以ROLE_开头,数据也必须以ROLE_开头
@Secured("ROLE_/reportform/find")
@GetMapping("/reportform/find")
@ResponseBody
public String testUrl1(){
System.out.println("/reportform/find");
return "/reportform/find权限拦截";
}
@Secured("/salary/find")//403没有权限
@GetMapping("/salary/find")
@ResponseBody
public String testUrl2(){
System.out.println("/salary/find");
return "/salary/find权限拦截";
}
@Secured("/tax/find")//403没有权限
@GetMapping("/tax/find")
@ResponseBody
public String testUrl3(){
System.out.println("/tax/find");
return "/tax/find权限拦截";
}
@PreAuthorize(推荐)
该注解可以在方法执行前判断用户是否具有权限
// 默认放行首页和失败页
http.authorizeHttpRequests()
.antMatchers("/login.html").permitAll()//登录页不需要认证
.antMatchers("/fail").permitAll()//失败页面不需要认证
//需要认证的权限
// .antMatchers("/reportform/find").hasAuthority("/reportform/find")
// .antMatchers("/salary/find").hasAuthority("/salary/find")
// .antMatchers("/tax/find").hasAuthority("/tax/find")
.anyRequest().authenticated();//其余所有请求都需要认证
@SpringBootApplication
@MapperScan
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启@PreAuthorize注解扫描
public class SpringSecurity2Application {
public static void main(String[] args) {
SpringApplication.run(SpringSecurity2Application.class, args);
}
}
//url权限匹配
@PreAuthorize("hasAnyAuthority('/salary/find')")
@GetMapping("/salary/find")
@ResponseBody
public String testUrl2(){
System.out.println("/salary/find");
return "/salary/find权限拦截";
}
@PreAuthorize("hasAnyAuthority('/tax/find')")
@GetMapping("/tax/find")
@ResponseBody
public String testUrl3(){
System.out.println("/tax/find");
return "/tax/find权限拦截";
}
前端控制访问权限
添加xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5",sec:authorize="hasAnyAuthority('/url')”若user有访问该url权限则显示此菜单
<!--前端控制访问权限依赖-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<title>主页面</title>
</head>
<body>
<span>主页面</span>
<span sec:authorize="hasAnyAuthority('/tax/find')"><a href="/tax/find">菜单一</a></span>
<span sec:authorize="hasAnyAuthority('/reportform/find')"><a href="/reportform/find">菜单二</a></span>
<span sec:authorize="hasAnyAuthority('/salary/find')"><a href="/salary/find">菜单三</a></span>
<a href="/logout">退出登录</a>
</body>
</html>
SpringSecurity自定义权限不足页面,解决403权限异常
//自定义权限不足页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>权限异常</title>
</head>
<body>
<span>权限不足</span>
</body>
</html>
定义权限不足处理器类需要实现AccessDeniedHandler接口实现其中的handle方法
public class NoPermissionHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
System.out.println("权限不足");
response.sendRedirect("/noPermission.html");
}
}
SecurityConfig权限配置类中添加自定义的权限不足处理器
// 权限不足异常
http.exceptionHandling()
.accessDeniedHandler(new NoPermissionHandler());