Spring Boot整合Spring Security简记-方

作者: 78240024406c | 来源:发表于2018-01-29 01:02 被阅读103次

    new無语 转载请注明原创出处,谢谢!

    Spring Security学习目录

    本章专讲基于表达式的访问控制。

    内置表达式:


    表达式 备注
    hasRole([role]) 如果有当前角色,则返回true(会自动添加ROLE_前缀)
    hasAnyRole([role1,role2]) 如果有任一角色即可通过校验,返回true(会自动添加ROLE_前缀)
    hasAuthority([authority]) 如果有指定权限,则返回true
    hasAnyAuthority([authority1,authority2]) 如果有指定任一权限,则返回true
    principal 获取当前用户的主体对象
    authentication 获取当前用户Authentication对象,身份验证主体
    permitAll 总是返回true,表示全部允许
    denyAll 总是返回false,表示全部拒绝
    isAnonymous() 如果为匿名验证,则返回true
    isRememberMe() 如果为Remember-Me自动认证,则返回true
    isAuthenticated() 如果用户不是匿名登陆,则返回true
    isFullyAuthenticated() 如果用户不是匿名登陆或Remember-Me自动认证则返回true
    hasPermission(Object target, Object permission)
    hasPermission(Object targetId, String targetType, Object permission)

    hasIpAddress


    该表达式hasIpAddress是特定于Web安全性的附加内置表达式。它是由WebSecurityExpressionRoot类定义的。
    这个表达式作用为,该URL域下,受到IP访问控制。这里0:0:0:0:0:0:0:1为本机。

    .antMatchers("/db/**").access("hasIpAddress('0:0:0:0:0:0:0:1')")
    

    在WEB安全表达式中使用自定义Bean


    如果你想扩展自定义表达式,在这里可以很轻易的引用你自己的Bean。例如下面WebSecurity

    public class WebSecurity {
            public boolean check(Authentication authentication, HttpServletRequest request) {
                    ...
            }
    }
    

    使用方法:

    http
            .authorizeRequests()
                    .antMatchers("/user/**").access("@webSecurity.check(authentication,request)")
                    ...
    

    安全表达式中的路径变量


    考虑REST风格的URL的应用,可以提取URL中的变量信息。
    例如

    public class WebSecurity {
            public boolean checkUserId(Authentication authentication, int id) {
                    ...
            }
    }
    
    http
            .authorizeRequests()
                    .antMatchers("/user/{userId}/**").access("@webSecurity.checkUserId(authentication,#userId)")
                    ...
    

    安全表达式注释


    前面也说到了,表达式的注释有四种,分别是@PreAuthorize@PreFilter@PostAuthorize@PostFilter。启动方式前面也有提过,这里就不说了。
    最常用的注释就是@PreAuthorize,它来决定此次请求是否可以调用当前方法。

    @PreAuthorize("hasRole('ADMIN')")
    public void create(Contact contact);
    
    @PreAuthorize("#username == principal")
    @RequestMapping("test11")
    public String test11(String username) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return "参数名与认证用户名一致。" + principal;
    }
    

    这里大家看到,第二个代码块中的方法可以使用Spring-EL(在表达式中可以使用任何Spring-EL功能)进行获取参数进行校验方法调用权限。这里是参数不为当前认证用户名的情况下,不能进行请求调用方法。

    • 处理参数还有一种方式,就是Spring Security的@P注释,如果@P注释出现在方法的单个参数上,则会使用该值。它的好处是,在使用之后,可以不包含任何参数名称的信息。
    import org.springframework.security.access.method.P;
    
    ...
    
    @PreAuthorize("#c.name == authentication.name")
    public void doSomething(@P("c") Contact contact);
    
    • 如果Spring Data 的@Param的注解在方法参数上使用,也会使用该参数。
    import org.springframework.data.repository.query.Param;
    
    ...
    
    @PreAuthorize("#n == authentication.name")
    Contact findContactByName(@Param("n") String name);
    

    如果你有需求需要对方法进行后置校验,你就可以使用@PostAuthorize,它可以通过内置表达式returnObject进行返回值校验。

    @PostAuthorize("returnObject == 'test1'")
    @RequestMapping("test12")
    public String test12(String param) {
        return param;
    }
    

    使用@PreFilter@PostFilter进行过滤

    Spring Security还支持对集合和数组的过滤。
    当使用@PostFilter注释时,Spring Security会遍历返回的集合并删除提供的表达式为false的所有元素。
    filterObject指的是返回集合中的当前对象。

    @PostFilter("filterObject.username == 'testuser2'")
    @RequestMapping("getAll")
    public List<UserDetails> getAll() {
        UserDetails details = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getDetails();
        List<UserDetails> list = new ArrayList<>();
        list.add(details);
        return list;
    }
    

    您也可以在方法调用之前进行筛选@PreFilter,尽管这是一个不太常见的要求。语法是一样的,但如果有多个参数是一个集合类型,那么你必须使用filterTarget这个注释的属性来选择一个名称。

    请注意,过滤显然不能替代您的数据检索查询。如果你正在过滤大集合并删除很多条目,那么这可能是低效的。

    相关文章

      网友评论

        本文标题:Spring Boot整合Spring Security简记-方

        本文链接:https://www.haomeiwen.com/subject/rdbooxtx.html