依赖引入
org.springframework.security
spring-security-core
org.springframework.security
spring-security-config
org.springframework.security
spring-security-web
启用Spring Security
- 首先创建一个继承
AbstractSecurityWebApplicationInitializer
的类。这个操作会导致一个名为DelegatingFilterProxy
的Filter
被注册,它会拦截发往应用中的请求,并将请求委托给ID为SpringSecurityFilterChain
的bean
public class SecurityWebInitializer extends AbstractSecurityWebApplicationInitializer
{
}
- 再创建一个配置类
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
}
至此Spring Security就被启用了,目前所有的请求都会被拦截。
配置
WebSecurityConfigurerAdapter
中有三个名为configure
的方法提供重载,三个方法的描述如下:
方法 | 描述 |
---|---|
configure(HttpSecurity) | 配置拦截模式 |
configure(AuthenticationManagerBuilder) | 配置用户信息 |
configure(WebSecurity) | 配置Spring Security的Filter链 |
配置用户信息
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.inMemoryAuthentication() // 基于内存的用户存储
.withUser("admin")
.password("password")
.roles("USER", "ADMIN");
}
配置拦截路径
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.antMatchers("/info").authenticated()
.antMatchers(HttpMethod.GET, "/health").hasAnyAuthority("ADMIN")
.anyRequest().permitAll();
}
}
启用HTTPS
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.anyRequest().permitAll()
.and()
.requiresChannel()
.antMatchers("/bankInfo").requiresSecure() // enable HTTPS
.antMatchers("/").requiresInsecure(); // disable HTTPS
}
}
禁用CSRF
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.anyRequest().permitAll()
.and()
.csrf().disable();
}
}
登录与注销
- 在重写
configure(HttpSecurity)
之前会有一个默认的登录页面,需要登录时会自动跳转到这个位于/login
下的页面,但一旦重写此方法后就会失去这个简单的登录页面。
启用默认登录页
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.anyRequest().permitAll()
.and()
.formLogin();
}
}
自定义登录页面
如果不想做多余的配置,那么自定义的页面里:
form
的action
应该提交到/login
- 包含
username
的输入域且name
属性为username
- 包含
password
的输入域且name
属性为password
指定URL
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.anyRequest().permitAll()
.and()
.formLogin().loginPage("/login");
}
}
指定自定义页面
@Configuration
@EnableWebMvc
@ComponentScan
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
ViewControllerRegistry
可以用来直接转发请求到一个视图而无需编写控制器类。
注销
- 如果没有启用
CSRF
,直接访问\logout
就可实现登出 - 如果启用
CSRF
,用POST
方法访问\logout
并带上CSRF Token