回到序章
来来来,点这
情形
有一些接口或许要求不需要用户登陆便可以直接请求,还有一些接口是拥有某些权限某些角色才可以访问,这章便是讲述怎么配置的。
效果
啥人分配了啥权限,就能请求啥,没分配则请求不到。
正文
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
| import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/test1/a").hasAnyRole("ANONYMOUS") .antMatchers("/test1/b").hasAnyAuthority("ROLE_ANONYMOUS") .antMatchers("/test1/c").anonymous() .anyRequest().authenticated() .formLogin() .and() .csrf().disable(); } }
|
如注释一般, hasAnyRole("ANONYMOUS") = hasAnyAuthority("ROLE_ANONYMOUS") = anonymous() 意义相等,都是代表着未登录可以访问,但是登陆后便不再可以访问了。
如此,没登陆的用户( 匿名用户 )可以请求到 test1/a 、 /test1/b 、 /test1/c ,登录后这三个接口反而访问不到,只能访问其他的,例如 /test1/d 、 /test2/** 等。
匹配规则的话,是采用了 Ant 风格的路径匹配符,匹配规则如下:
| 通配符 |
含义 |
| ** |
匹配多层路径 |
| * |
匹配一层路径 |
| ? |
匹配任意单个字符 |
还有一些常用的配置会在下面逐一列出:
常用的权限配置
- hasAnyRole: 用户拥有某个角色可以请求
- hasAnyAuthority: 用户拥有某个权限可以请求
- authenticated: 已经登陆的用户可以请求
- anonymous: 匿名用户( 没有登陆的用户 )可以请求
- permitAll: 任何人都可以请求
- denyAll: 任何人都不能请求
- rememberMe: 使用记住我方式登陆的用户可以请求
- fullAuthenticated: 使用记住我方式登陆的用户不能请求
- hasIpAddress: 指定ip的用户可以请求
- not: 求反,上列配置的前置使用,代表相反意义
- access: 使用 Spring EL 表达式,可以参考 官方文档 中的进行折腾。
Spring EL 表达式
这种表达有啥用呢,举个栗子,比如我既想让一个请求可以匿名的时候请求,也可以被拥有 TEST 的角色用户请求,便需要用到了。
1
| .antMatchers("/test4/index").access("hasAnyRole('TEST') and isAnonymous()")
|
- and
- or
- hasRole(String role)
- hasAnyRole(String… roles)
- 拥有某些角色
- hasAnyRole(‘admin’, ‘user’)
- hasAuthority(String authority)
- 拥有某个权限
- hasAuthority(‘read’)
- hasAnyAuthority(String… authorities)
- 拥有某些权限
- hasAnyAuthority(‘read’, ‘write’)
- permitAll
- denyAll
- isAnonymous()
- isRememberMe()
- isAuthenticated()
- isFullyAuthenticated()
- hasPermission(Object target, Object permission)
- hasPermission(domainObject, ‘read’)
- hasPermission(Object targetId, String targetType, Object permission)
- hasPermission(1, ‘com.example.domain.Message’, ‘read’)
角色继承
简单的理解就是 上级角色 拥有完整的 下级角色 请求权限,白话文:下级能请求的,上级也能请求。
假如拷贝下面的配置类:
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
| import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.access.hierarchicalroles.RoleHierarchy; import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Bean protected UserDetailsService userDetailsService() { InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); manager.createUser(User.withUsername("admin2").password("{noop}123").roles("user").build()); return manager; }
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .userDetailsService(userDetailsService()) .and() .inMemoryAuthentication() .withUser("admin1").password("{noop}123").roles("admin"); }
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/test2/a").hasRole("admin") .antMatchers("/test2/b").hasRole("user") .anyRequest().authenticated() .and() .formLogin(); }
}
|
这段配置大概就是创建了俩个用户 admin1 和 admin2
其中 admin1 拥有 admin 的角色,admin2 拥有 user 的角色
拥有 admin 角色的可以请求接口 /test2/a,拥有 user 角色的可以请求接口 /test2/b,但是反过来请求的话则会返回 403( 没有权限 )
角色继承就是让拥有 admin 角色的可以请求 /test2/b
操作的话,先登陆 admin2 ,然后请求 /test2/b ,然后放开注释的代码,重新运行,再登陆 admin2 ,然后请求 /test2/b ,看看俩者有什么差别。
放行静态资源
1 2 3 4 5 6 7 8
| @Configuration public class SecurityWebConfiguration extends WebSecurityConfigurerAdapter {
@Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/static/**"); } }
|