美文网首页
Spring-security

Spring-security

作者: 16325 | 来源:发表于2020-03-02 17:10 被阅读0次

    概念

    Spring-security是一个认证+鉴权的支持库,通过一系列filter来处理用户的认证,以及对后端接口权限的控制。

    配置

    image.png

    截图里都是针对HttpSecurity请求的配置

     .authorizeRequests()
                        .anyRequest().authenticated()
                        .and()
    
    • 对http请求的处理,所有请求都需要认证。
    • 可以配置regexMatchers(),antMatcher() 等方法对请求进行精准的匹配。
    .formLogin()
                        .loginPage("/auth/login").permitAll()
                        .usernameParameter("username")
                        .passwordParameter("password")
                        .loginProcessingUrl("/auth/doAuth")
                        .defaultSuccessUrl("/auth/index")
                        .failureForwardUrl("/auth/failed")
                        .and()
    

    登录页面的处理

    • loginPage 登录页面,当没有权限访问的时候跳转到此页面,permitAll()指定这个页面无需鉴权。
    • usernameParameter,passwordParameter 指定登录页面的参数名称。
    • loginProcessingUrl 登录请求的后台 url
    • defaultSuccessUrl 登录成功后的跳转页面
    • failureForwardUrl 登录失败后的跳转页面

    看到这里,都是登录的配置,但是具体的认证操作是在哪里处理的呢?

    image.png
    • 一个AuthenticationManagerBuilder包含多个AuthenticationProvider
    • 一个AuthenticationManagerBuilder包含一个userDetailsService

    具体的一个AuthenticationProvider:


    image.png
    • suports方法,标识这个provider所能处理的认证凭证。
    • authenticate方法,具体的认证逻辑,返回一个Authentication的子类,比如这里返回UsernamePasswordAuthenticationToken,里边包括用户名密码以及权限信息。

    具体的UserDetailsService:


    image.png
    • AuthenticationProvider方法内部会使用UserDetailsService来查询用户的具体信息,用这个信息来认证。

    认证失败如何处理:


    image.png

    GrantedAuthorityDefaults

    我们用注解来验证权限的时候

        @GetMapping("/delUser")
        @PreAuthorize("hasAnyRole('ADMIN','USER_ALL','USER_DELETE')")
        public String delete() {
            return "具有【用户删除】权限";
        }
    

    验证的时候,通过查看 hasAnyRole源码,我们发现系统在做校验是默认会加一个角色前缀:private String defaultRolePrefix = "ROLE_";


    image.png

    如果不需要,可以在 WebSecurityConfig 中通过配置去掉这个默认前缀。

        @Bean
        GrantedAuthorityDefaults grantedAuthorityDefaults() {
            // Remove the ROLE_ prefix
            return new GrantedAuthorityDefaults("");
        }
    

    PasswordEncoder

        @Bean
        public PasswordEncoder passwordEncoder() {
            // 密码加密方式
            return new BCryptPasswordEncoder();
        }
    

    默认对密码字段都需要配置解密函数,同时要保证前台传来的是加密后的字符串。

    注解方式鉴权

    一、注解式方法级安全开启

    需要在WebSecuirtyConfig添加配置:

    @Configuration
    @EnableWebSecurity //启用Spring Security.
    ////会拦截注解了@PreAuthrize注解的配置.
    @EnableGlobalMethodSecurity(prePostEnabled=true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    }
    

    二、允许的注解

    这里主要@PreAuthorize, @PostAuthorize, @Secured这三个注解可以使用。

    • @Secured,当@EnableGlobalMethodSecurity(securedEnabled=true)的时候,@Secured可以使用:
    @GetMapping("/helloUser")
    @Secured({"ROLE_normal","ROLE_admin"})
    public String helloUser() {
        return "hello,user";
    }
    

    说明:拥有normal或者admin角色的用户都可以方法helloUser()方法。另外需要注意的是这里匹配的字符串需要添加前缀“ROLE_“。
    如果我们要求,只有同时拥有admin & noremal的用户才能方法helloUser()方法,这时候@Secured就无能为力了。

    • @PreAuthorize
      Spring的 @PreAuthorize/@PostAuthorize 注解更适合方法级的安全,也支持Spring 表达式语言,提供了基于表达式的访问控制。
      当@EnableGlobalMethodSecurity(prePostEnabled=true)的时候,@PreAuthorize可以使用:
    @GetMapping("/helloUser")
    @PreAuthorize("hasAnyRole('normal','admin')")
    public String helloUser() {
        return "hello,user";
    }
    

    说明:拥有normal或者admin角色的用户都可以方法helloUser()方法。
    此时如果我们要求用户必须同时拥有normal和admin的话,那么可以这么编码: @PreAuthorize("hasRole('normal') AND hasRole('admin')")

    • @PostAuthorize
      @PostAuthorize 注解使用并不多,在方法执行后再进行权限验证,适合验证带有返回值的权限,Spring EL 提供 返回对象能够在表达式语言中获取返回的对象returnObject。
      当@EnableGlobalMethodSecurity(prePostEnabled=true)的时候,@PostAuthorize可以使用:
    @GetMapping("/helloUser")
    @PostAuthorize(" returnObject!=null &&  returnObject.username == authentication.name")
    public User helloUser() {
            Object pricipal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            User user;
            if("anonymousUser".equals(pricipal)) {
                user = null;
            }else {
                user = (User) pricipal;
            }
            return user;
    }
    

    这三个最常用也就是@PreAuthorize这个注解了,在使用中主要是配合Spring EL表达式。

    相关文章

      网友评论

          本文标题:Spring-security

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