1 保护 Web
配置 Spring Security,在扩展 WebSecurityConfigurerAdapter 的 bean 上,添加 @EnableWebSecurity 注解,启用 Web 安全功能,并在类中重写 configure 的 3 个方法。
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
//配置用户存储
@Override
protected void configure(AuthenticationManagerBuilder auth){
super.configure(auth);
}
//拦截请求
@Override
protected void configure(HttpSecurity http){
super.configure(http);
}
//认证用户
@Override
protected void configure(WebSecurity web){
super.configure(web);
}
}
1.1 配置用户存储
1)基于内存
调用 AuthenticationManagerBuilder 类的 inMemoryAuthentication() 方法启用内存用户存储。 withUser() 方法为内存用户存储添加新的用户,返回 UserDetailsBuilder。
auth.inMemoryAuthentication().withUser("user").password("user").authorities("ROLE_USER");
2)基于数据库
passwordEncoder() 方法指定一个密码转码器(encoder) ,接受 PasswordEncoder 接口的任意实现。
auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery(...).PasswordEncoder(...);
3)基于 LDAP
auth.ldapAuthentication().userSearchFilter("{uid={0}}").groupSearchFilter("member={0}").contextSource().url(...);
4)自定义
如用户存储在非关系型数据库中,需要提供一个自定义的 UserDetailsService 接口实现。
1.2 拦截请求
http.authorizeRequests() 方法有多个子节点,每个 macher 按照他们的声明顺序执行。.permitAll() 都可以访问,.hasRole() 按角色,.access(“hasRole(‘’) and hasRole(‘’)”) 满足条件,.hasAnyRole(“”, “”)
http.authorizeRequests()
.antMatchers("/resources/**", "/signup", "/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
.antMatchers("/db/**").hasAnyRole("ADMIN", "DBA")
.anyRequest().authenticated().and()
.formLogin();
1.3 认证用户
1)认证
HttpSecurity 对象上调用 formLogin() 或 httpBasic()
2)Remember-me
HttpSecurity 对象上调用 rememberMe(),可指定 cookie 中 token 有效期
3)退出
HttpSecurity 对象上,loginPage() 指定退出连接,再调用 logout(),并可调用 logoutSuccessUrl() 表明在退出成功之后, 重定向到地址
2 保护方法
2.1 使用注解保护方法
Spring Security 提供了三种不同的安全注解:
- Spring Security 自带的 @Secured 注解;
- JSR-250 的 @RolesAllowed 注解;
- 表达式驱动的注解, 包括 @PreAuthorize、 @PostAuthorize、 @PreFilter 和 @PostFilter。
1)使用 @Secured 注解
在配置类上使用 @EnableGlobalMethodSecurity 启用基于注解的方法安全性
@Configuration
@EnableGlobalMethodSecurity(securedEnabled=true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}
如果 securedEnabled 属性的值为 true 的话, 将会创建一个切点, 这样的话 Spring Security 切面就会包装带有 @Secured 注解的方法。
@Secured("ROLE_SPITTER")
public void addSpittle(Spittle spittle) {
// ...
}
@Secured 注解会使用一个 String 数组作为参数。 每个 String 值是一个权限, 调用这个方法至少需要具备其中的一个权限。
2) 使用 @RolesAllowed 注解
@RolesAllowed 注解和 @Secured 注解在各个方面基本上都是一致的。 唯一显著的区别在于 @RolesAllowed 是 Java 标准注解,@Secured 是 Spring 注解。
将 @EnableGlobalMethodSecurity 的 jsr250Enabled 属性设置为 true, 以开启 @RolesAllowed
@Configuration
@EnableGlobalMethodSecurity(jsr250Enabled=true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}
2.2 使用表达式实现方法级别的安全性
安全性约束不仅仅涉及用户是否有权限。下面几个注解使用SpEL在方法调用上实现更有意思的安全性约束。
注 解 | 描 述 |
---|---|
@PreAuthorize | 在方法调用前验证权限 |
@PostAuthorize | 在方法调用之后验证权限,不符将抛异常 |
@PostFilter | 允许方法调用, 事后对方法的返回值进行过滤 |
@PreFilter | 允许方法调用, 事先对方法的参数进行过滤 |
将 @EnableGlobalMethodSecurity 注解的 prePostEnabled 属性设置为 true, 以启用:
@Configuration
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}