当前位置: 首页 > news >正文

Spring Security 基于表达式的权限控制

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

前言

spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。

常见的表达式

Spring Security可用表达式对象的基类是SecurityExpressionRoot。

表达式描述
hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去除参考Remove the ROLE_
hasAnyRole([role1,role2])用户拥有任意一个制定的角色时返回true
hasAuthority([authority])等同于hasRole,但不会带有ROLE_前缀
hasAnyAuthority([auth1,auth2])等同于hasAnyRole
permitAll永远返回true
denyAll永远返回false
anonymous当前用户是anonymous时返回true
rememberMe当前勇士是rememberMe用户返回true
authentication当前登录用户的authentication对象
fullAuthenticated当前用户既不是anonymous也不是rememberMe用户时返回true
hasIpAddress('192.168.1.0/24'))请求发送的IP匹配时返回true

部分代码:

......
private String defaultRolePrefix = "ROLE_"; //ROLE_前缀

	/** Allows "permitAll" expression */
	public final boolean permitAll = true; //全部true

	/** Allows "denyAll" expression */
	public final boolean denyAll = false; //全部false
public final boolean permitAll() {
		return true;
	}

	public final boolean denyAll() {
		return false;
	}

	public final boolean isAnonymous() {
		//是否是anonymous
		return trustResolver.isAnonymous(authentication);
	}

	public final boolean isRememberMe() {
		//是否是rememberme
		return trustResolver.isRememberMe(authentication);
	}
......

URL安全表达式

onfig.antMatchers("/person/*").access("hasRole('ADMIN') or hasRole('USER')")
                .anyRequest().authenticated();

这里我们定义了应用/person/*URL的范围,该URL只针对拥有ADMIN或者USER权限的用户有效。

在Web安全表达式中引用bean

config.antMatchers("/person/*").access("hasRole('ADMIN') or hasRole('USER')")
                .antMatchers("/person/{id}").access("@rbacService.checkUserId(authentication,#id)")
                .anyRequest()
                .access("@rbacService.hasPermission(request,authentication)");

RbacServiceImpl

@Component("rbacService")
@Slf4j
public class RbacServiceImpl implements RbacService {
    /**
     * uri匹配工具
     */
    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        log.info("【RbacServiceImpl】  --hasPermission={}", authentication.getPrincipal());
        Object principal = authentication.getPrincipal();

        boolean hasPermission = false;
        //有可能是匿名的anonymous
        if (principal instanceof SysUser) {
            //admin永远放回true
            if (StringUtils.equals("admin", ((SysUser) principal).getUsername())) {
                hasPermission = true;
            } else {
                //读取用户所拥有权限所有的URL 在这里全部返回true
                Set<String> urls = new HashSet<>();

                for (String url : urls) {
                    if (antPathMatcher.match(url, request.getRequestURI())) {
                        hasPermission = true;
                        break;
                    }
                }
            }
        }
        return hasPermission;
    }

	  public boolean checkUserId(Authentication authentication, int id) {
        return true;
    }
}

效果如下:

Method安全表达式

针对方法级别的访问控制比较复杂,Spring Security提供了四种注解,分别是@PreAuthorize , @PreFilter , @PostAuthorize 和 @PostFilter

使用method注解

  1. 开启方法级别注解的配置
    @Configuration
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class MerryyouSecurityConfig extends WebSecurityConfigurerAdapter {
    
  2. 配置相应的bean
     @Bean
     @Override
     public AuthenticationManager authenticationManagerBean() throws Exception {
         return super.authenticationManagerBean();
     }
    
     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
         auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
     }
    
     @Bean
     @ConditionalOnMissingBean(PasswordEncoder.class)
     public PasswordEncoder passwordEncoder(){
         return new BCryptPasswordEncoder();
     }
    
  3. 在方法上面使用注解
    /**
    * 查询所有人员 
    */ 
    @PreAuthorize(“hasRole(‘ADMIN’)”) 
    @ApiOperation(value = “获得person列表”, notes = “”) 
    @GetMapping(value = “/persons”) 
    public List getPersons() { 
        return personService.findAll(); 
    } 

PreAuthorize

@PreAuthorize 注解适合进入方法前的权限验证

@PreAuthorize("hasRole('ADMIN')")
    List<Person> findAll();

PostAuthorize

@PostAuthorize 在方法执行后再进行权限验证,适合验证带有返回值的权限。Spring EL 提供 返回对象能够在表达式语言中获取返回的对象return Object

@PostAuthorize("returnObject.name == authentication.name")
    Person findOne(Integer id);

PreFilter 针对参数进行过滤

//当有多个对象是使用filterTarget进行标注
@PreFilter(filterTarget="ids", value="filterObject%2==0")
public void delete(List<Integer> ids, List<String> usernames) {
   ...

}

PostFilter 针对返回结果进行过滤

 @PreAuthorize("hasRole('ADMIN')")
 @PostFilter("filterObject.name == authentication.name")
 List<Person> findAll();

效果如下:

转载于:https://my.oschina.net/liuyuantao/blog/1924776

相关文章:

  • Storm 0.9 集群搭建
  • vs2017使用rdlc实现批量打印
  • Click Magick – 下一代点击跟踪和链接管理
  • GitHub推出更多课程
  • HTML/CSS实现的一个列表页
  • python引用局部变量之nonlocal
  • OpenWrt backfire trunk源码下载及编译
  • CentOS 7上安装gitlab-runner
  • sql server实战
  • could not read block 0 in file base/16389/17624
  • MongoDB-C#驱动基本操作
  • Linux详细搭建httpd网站搭建服务(阿帕奇)
  • 集群负载均衡LVS
  • Julia 1.0 正式发布,这是新出炉的一份简单中文教程
  • 这就是生活
  • [iOS]Core Data浅析一 -- 启用Core Data
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • CAP 一致性协议及应用解析
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • JAVA SE 6 GC调优笔记
  • js对象的深浅拷贝
  • js数组之filter
  • Laravel Telescope:优雅的应用调试工具
  • leetcode98. Validate Binary Search Tree
  • Yii源码解读-服务定位器(Service Locator)
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 聊聊flink的BlobWriter
  • 如何选择开源的机器学习框架?
  • 思考 CSS 架构
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 译自由幺半群
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • ​LeetCode解法汇总2304. 网格中的最小路径代价
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #### go map 底层结构 ####
  • #{}和${}的区别?
  • #大学#套接字
  • (04)odoo视图操作
  • (23)Linux的软硬连接
  • (bean配置类的注解开发)学习Spring的第十三天
  • (二开)Flink 修改源码拓展 SQL 语法
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (区间dp) (经典例题) 石子合并
  • (十三)Flask之特殊装饰器详解
  • (五)IO流之ByteArrayInput/OutputStream
  • (已解决)什么是vue导航守卫
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • **PHP分步表单提交思路(分页表单提交)
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞