依赖引入
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@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter{}
至此Spring Security就被启用了,目前所有的请求都会被拦截。
配置
WebSecurityConfigurerAdapter
中有三个名为configure
的方法提供重载,三个方法的描述如下:
方法 | 描述 |
---|---|
configure(HttpSecurity) | 配置拦截模式 |
configure(AuthenticationManagerBuilder) | 配置用户信息 |
configure(WebSecurity) | 配置Spring Security的Filter链 |
配置用户信息
@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter{ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() // 基于内存的用户存储 .withUser("admin") .password("password") .roles("USER", "ADMIN"); }
配置拦截路径
@Configuration@EnableWebSecuritypublic 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@EnableWebSecuritypublic 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@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter{ @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().permitAll() .and() .csrf().disable(); }}
登录与注销
- 在重写
configure(HttpSecurity)
之前会有一个默认的登录页面,需要登录时会自动跳转到这个位于/login
下的页面,但一旦重写此方法后就会失去这个简单的登录页面。
启用默认登录页
@Configuration@EnableWebSecuritypublic 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@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter{ @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().permitAll() .and() .formLogin().loginPage("/login"); }}
指定自定义页面
@Configuration@EnableWebMvc@ComponentScanpublic class WebConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); }}
ViewControllerRegistry
可以用来直接转发请求到一个视图而无需编写控制器类。
注销
- 如果没有启用
CSRF
,直接访问\logout
就可实现登出 - 如果启用
CSRF
,用POST
方法访问\logout
并带上CSRF Token