1 Spring Security

Wu Jun 2018-12-18 21:52:33
06 Spring > 06 Security

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 提供了三种不同的安全注解:

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 {
}