美文网首页
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