<--spring security依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
加入依赖就可以进行HTTP基本认证,但绝大多数Web应用都不会选择这种认证方式,除了安全性差,无法携带cookie等因素外,灵活性不足 也是它的一个主要缺点。通常大家更愿意选择表单认证,自己实现表单登录页和验证逻辑,从而提高安全性。
一:表单认证
在WebSecurityConfigution配置类上贴**@EnableWebSecurity**注解,便会自动被Spring发现并注册(查看@EnableWebSecurity即可看拿到@Configuration注解已经存在,所以此处不需要额外添加)
查看WebSecurityConfigurerAdapter类对configure(HttpSecurity http)方法的 默认定义实现,如下:
protected void configure(HttpSecurity http) throws Exception {
this.logger.debug("Using default configure(HttpSecurity). "
+ "If subclassed this will potentially override subclass configure(HttpSecurity).");
http.authorizeRequests((requests) -> requests.anyRequest().authenticated());
http.formLogin(); //简单表单登录
http.httpBasic(); //HTTP基本登录
}
默认定义实现了3种功能:如下
1. 验证所有的请求。
2. 允许用户使用表单登录进行身份验证(spring Security提供了一个简单的表单登录页面)。
3. 允许用户使用HTTP基本认证。
1.HttpSecurity 实际上对应了=spring Security命名空间配置方式中XML文件内的标签,允许我们为特定的HTTP请求配置安全策略。HttpSecurity提供了很多配置相关的方法,分别对应命名空间配置中的子标签。例如,authorizeRequests(),formLogin(),httpBasic()和csrf()分别对应<intercept-url>,<form-login>,<http-basic>,和<csrf>
标签。调用这些方法之后,除非使用了and()方法结束当前标签,上下文才会回到HttpSecurity。否则链式调用的上下文将自动进入对应的标签域。
<http>
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login />
<anonymous />
<http-basic />
<logout />
<remember-me />
</http>
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin().loginPage("/myLogin.html")
.loginProcessingUrl("/login") //指定处理登录请求的路径
.successHandler(new SecurityAuthenticationSuccessHandler()) //指定登录成功时的处理逻辑
.failureHandler(new SecurityAuthenticationFailureHandler()) //指定登录失败时的处理逻辑
.permitAll()
.and()
.csrf().disable();
}
}
**2.authorizeRequests()**方法实际上返回了一个URL拦截注册器,我们可以调用它提供的anyRequest(),antMatchers和regexMatchers()等方法来匹配系统的URL,并为其制定安全策略。
**3.formLogin()**方法和httpbasic()方法都声明了需要Spring Security提供的表单认证方式,分别返回对应的是配置器。其中,formLogin().loginPage("/myLogin.html")指定自定义的登录页/myLogin.html,同时,Spring Security会用/myLogin.html注册一个POST路由,用于接收登录请求。在自定义表单登录之后,处理登录请求的URL也会相应改变,通过loginProcessingUrl("/login")设置。
**4.csrf()**方法是Spring Security提供的跨域请求伪造防护功能,当我们继承了WebSecurityConfigurerAdapter时会默认开启csrf()方法。
5.successHandler()指定登录成功时的处理逻辑,其类图,如下
public class SecurityAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
if (request.getHeader("accept").contains("application/json")) {
response.setContentType("application/json;charset=UTF-8");
PrintWriter out = response.getWriter();
out.write("{\"error_code\":\"0\", \"message\":\"欢迎登录系统\"}");
} else {
super.onAuthenticationSuccess(request, response, authentication);
}
}
}
6.failureHandler()指定登录失败时的处理逻辑,其类图,如下:
failureHandler()指定登录失败时的处理逻辑,其类图,如下:
public class SecurityAuthenticationFailureHandler extends ExceptionMappingAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
if (request.getHeader("accept").contains("application/json")) {
response.setContentType("application/json;charset=UTF-8");
response.setStatus(401);
PrintWriter out = response.getWriter();
// 输出失败的原因
out.write("{\"error_code\":\"401\", \"name\":\"" + e.getClass() + "\", \"message\":\"" + e.getMessage() + "\"}");
} else {
super.onAuthenticationFailure(request, response, e);
}
}
}
表单登录配置模块提供了successHandler() 和failureHandler()两个方法,分别处理登录成功和登录失败的逻辑。其中successHandler()方法带有一个Authentication 参数,携带当前登录用户名及其角色等信息。而failureHandler()方法携带了AuthenticationException异常参数