一、Role 和 Authority 的区别 用户拥有的权限表示
1 2 roles("ADMIN" ,"学徒" ,"宗师" ) authorities("USER" ,"MANAGER" ); 
给资源授予权限(角色或权限)
1 2 3 4 5 //.antMatchers("/level1/**" ).hasRole("学徒" ) //.antMatchers("/level1/**" ).hasAnyRole("学徒" ,"ADMIN" )//拥有任何一个角色都可以访问 .antMatchers("/level1/**" ).hasAnyAuthority("学徒" ,"ADMIN" ) //拥有任何一个权限都可以访问 .antMatchers("/level2/**" ).hasRole("大师" ) .antMatchers("/level3/**" ).hasRole("宗师" ) 
roles  (“ADMIN”,”学徒”,”宗师”),增加”ROLE_“前缀存放:【"ROLE_ADMIN","ROLE_学徒","ROLE\_宗师"】
表示拥有的权限。一个角色表示的是多个权限,用户传入的角色不能以 ROLE_开头,否则会报错。ROLE_是自动加上的
如果我们保存的用户的角色:直接传入角色的名字,权限【new SimpleGrantedAuthority(“ROLE_“ + role)】保存即可
authorities (“USER”,”MANAGER”),原样存放:【"USER","MANAGER"】
表示拥有的权限。如果我们保存的是真正的权限;直接传入权限名字,权限【new SimpleGrantedAuthority(role)】保存
无论是 Role 还是 Authority 都保存在 List<GrantedAuthority>,每个用户都拥有自己的权限集合 -> List<GrantedAuthority>
验证用户权限
通过角色(权限)验证 1 2 .antMatchers("/level1/**" ).hasRole("学徒" ) .antMatchers("/level1/**" ).hasAnyRole("学徒" ,"ADMIN" ) 
拥有任何一个角色都可以访问,验证时会自动增加”ROLE_“进行查找验证:【”ROLE_学徒”,”ROLE_ADMIN”】
通过权限验证 1 2 .antMatchers("/level1/**" ).hasAuthority("学徒" ) .antMatchers("/level1/**" ).hasAnyAuthority("学徒" ,"ADMIN" ) 
拥有任何一个权限都可以访问,验证时原样查找进行验证:【”学徒”,”ADMIN”】
二、细粒度的资源控制 authenticated():通过认证的用户都可以访问
permitAll():允许所有人访问,即使未登录
authorizeRequests():更细粒度的控制
access(String): SpEL:Spring 表达式
 ==.access(“hasRole(‘大师’) AND  hasAuthority(‘user:delete’) OR  hasIpAddress(‘192.168.0.1’)”)==
三、细粒度的资源控制相应注解 开启注解控制权限模式
@EnableWebSecurity:开启 Spring Security 注解
@EnableGlobalMethodSecurity(prePostEnabled=true):开启全局的细粒度方法级别权限控制功能
几个权限检查注解
@PreAuthorize :方法执行前检查1 2 3 4 5 @PreAuthorize("hasRole('ADMIN')") public  void  addUser (User user) {         .... } 
@PostAuthorize :方法执行后检查,失败抛异常1 2 3 4 5 6 7 8 @PostAuthorize :允许方法调用,但是,如果表达式结果为false 抛出异常@PostAuthorize("returnObject.user.username==principal.username") public  User getUser (int  userId) {    ...     return  user; } 
@PostFilter :允许方法调用,但是按照表达式过滤方法结果1 2 3 4 5 6 7 @PostFilter("returnObject.user.sex=='男' ") public  List<User> getUserList () {         ...     return  user; } 
@PreFilter :允许方法调用,但必须在进入方法前过滤输入值@Secured :拥有指定角色才可以访问方法1 @Secured('ADMIN')    等价于    @PreAuthorize("hasRole('ADMIN')") 
四、细粒度的资源控制注解中可写的表达式 所有能使用的表达式见下面文档连接: 
https://docs.spring.io/spring-security/site/docs/4.0.1.RELEASE/reference/htmlsingle/#el-common-built-in 
五、细粒度权限控制实现步骤 1、开启全局的细粒度方法级别权限控制功能 1 2 3 4 @EnableGlobalMethodSecurity(prePostEnabled = true) @Configuration @EnableWebSecurity public  class  AppWebSecurityConfig  extends  WebSecurityConfigurerAdapter  {
2、将手动授权的方式注释掉 3、给访问资源的方法增加注解,进行访问授权 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Controller public  class  GongfuController  {	 	@PreAuthorize("hasRole('学徒') AND hasAnyAuthority('putong:luohanquan')")  	@GetMapping("/level1/1")  	public  String leve1Page1 () { 		return  "/level1/1" ; 	} 	@PreAuthorize("hasRole('学徒') AND hasAnyAuthority('putong:wudangchangquan')")  	@GetMapping("/level1/2")  	public  String leve1Page2 () { 		return  "/level1/2" ; 	} 	@PreAuthorize("hasRole('学徒') AND hasAnyAuthority('putong:quanzhenjianfa')")  	@GetMapping("/level1/3")  	public  String leve1Page3 () { 		return  "/level1/3" ; 	} } 
4、通过数据库加载用户权限 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 @Component public  class  UserDetailsServiceImpl  implements  UserDetailsService  {    @Autowired      JdbcTemplate jdbcTemplate;     @Override      public  UserDetails loadUserByUsername (String username)  throws  UsernameNotFoundException {         String  queryUser  =  "SELECT * FROM `t_admin` WHERE loginacct=?" ;                  Map<String, Object> map = jdbcTemplate.queryForMap(queryUser, username);                  String  sql1  =  "SELECT t_role.* FROM t_role LEFT JOIN t_admin_role ON t_admin_role.roleid=t_role.id WHERE t_admin_role.adminid=?" ;         List<Map<String, Object>> roleList = jdbcTemplate.query(sql1, new  ColumnMapRowMapper (), map.get("id" ));         System.out.println("roleList=" +roleList);                  String  sql2  =  "SELECT distinct t_permission.* FROM t_permission LEFT JOIN t_role_permission ON t_role_permission.permissionid = t_permission.id LEFT JOIN t_admin_role ON t_admin_role.roleid=t_role_permission.roleid WHERE t_admin_role.adminid=?" ;         List<Map<String, Object>> permissionList = jdbcTemplate.query(sql2, new  ColumnMapRowMapper (), map.get("id" ));         System.out.println("permissionList=" +permissionList);                  Set<GrantedAuthority> authorities = new  HashSet <GrantedAuthority>();         for  (Map<String, Object> rolemap : roleList) {             String  rolename  =  rolemap.get("name" ).toString();             authorities.add(new  SimpleGrantedAuthority ("ROLE_"  + rolename));         }         for  (Map<String, Object> permissionmap : permissionList) {             String  permissionName  =  permissionmap.get("name" ).toString();             if  (!StringUtils.isEmpty(permissionName)) {                 authorities.add(new  SimpleGrantedAuthority (permissionName));             }         }         System.out.println("authorities=" +authorities);                                    return  new  User (map.get("loginacct" ).toString(), map.get("userpswd" ).toString(), authorities);     } 
5、准备数据  测试所需的表请从 https:oy6090.top  获取, 以下是表中需要修改的测试数据
admin  表
t_admin_role  表
t_role  表
t_permission  表
t_role_permission  表
6、测试 访问 level1/1 和 / leve1/2 都是正常