Spring Security自定义表单登录页

(1)初步配置自定义表单登录页

首先覆盖config方法

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/myLogin.html")
                // 使登录页不设限访问
                .permitAll()
                .and()
            .csrf().disable();
    }
}

 

 

(2)认识HttpSecurity

HttpSecurity 实际上对应了 =Spring Security 命名空间配置方式中 XML 文件内的标签,允许我们为特定的 HTTP 请求配置安全策略。

在 XML 文件中,声明大量配置早已司空见惯;但在 Java 配置中,按照传统的方式,我们需要这样来调用。

Spring Security自定义表单登录页_第1张图片

HttpSecurity 首先被设计为链式调用,在执行每个方法后,都会返回一个预期的上下文,便于连续调用。我们不需要关心每个方法究竟返回了什么、如何进行下一个配置等细节。 

HttpSecurity 提供了很多配置相关的方法,分别对应命名空间配置中的子标签 。例如,authorizeRequests()、formLogin()、httpBasic()和 csrf()分别对应 标签。调用这些方法之后,除非使用 and()方法结束当前标签,上下文才会回到 HttpSecurity,否则链式调用的上下文将自动进入对应标签域。

authorizeRequests()方法实际上返回了一个 URL 拦截注册器,我们可以调用它提供的 anyanyRequest()、antMatchers()和 regexMatchers()等方法来匹配系统的 URL,并为其指定安全策略。

formLogin()方法和 httpBasic()方法都声明了需要 Spring Security 提供的表单认证方式,分别返回对应的配置器。其中,formLogin().loginPage(「/myLogin.html」)指定自定义的登录页/myLogin.html,同时,Spring Security 会用/myLogin.html 注册一个 POST 路由,用于接收登录请求。

csrf()方法是 Spring Security 提供的跨站请求伪造防护功能,当我们继承 WebSecurityConfigurer Adapter 时会默认开启 csrf()方法。关于 csrf()方法的更多内容会在后面的章节专门探讨,以使测试进程更加顺利。

重新启动服务后再次访问 localhost:8080,页面会自动跳转到 localhost:8080/myLogin.html。由于/myLogin.html 无法定位到页面资源,所以会显示一个 404 页面

 

Spring Security自定义表单登录页_第2张图片 

(3)编写表单登录页

在表单登录页中,仅有一个表单,用户名和密码分别为 username 和 password,并以 POST 的方式提交到/myLogin.html。

我们将其命名为 myLogin.html,放置在 resources/static/下。重启服务,再次访问 localhost:8080,即可看到自定义的表单登录页。

Spring Security自定义表单登录页_第3张图片

输入正确的用户名和密码后,单击「Login」按钮,即可成功跳转。

(4)其他表单配置项

在自定义表单登录页之后,处理登录请求的 URL 也会相应改变。如何自定义 URL 呢?很简单,Spring Security 在表单定制里提供了相应的支持。

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@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")
                // 使登录页不设限访问
                .permitAll()
                .and()
            .csrf().disable();
    }
}

 

此时,有些同学可能会有疑问,因为按照惯例,在发送登录请求并认证成功之后,页面会跳转回原访问页。在某些系统中的确是跳转回原访问页的,但在部分前后端完全分离、仅靠 JSON 完成所有交互的系统中,一般会在登录时返回一段 JSON 数据,告知前端成功登录成功与否,由前端决定如何处理后续逻辑,而非由服务器主动执行页面跳转。这在 Spring Security 中同样可以实现。 

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@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 AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                        response.setContentType("application/json;charset=utf-8");
                        PrintWriter out = response.getWriter();
                        out.write("欢迎登录系统!");
                    }
                })
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
                        response.setStatus(401);
                        PrintWriter out = response.getWriter();
                        out.write("登录失败!");
                    }
                })
                // 使登录页不设限访问
                .permitAll()
                .and()
            .csrf().disable();
    }
}

 

表单登录配置模块提供了 successHandler()和 failureHandler()两个方法,分别处理登录成功和登录失败的逻辑。其中,successHandler()方法带有一个 Authentication 参数,携带当前登录用户名及其角色等信息;而 failureHandler()方法携带一个 AuthenticationException 异常参数。具体处理方式需按照系统的情况自定义。

在形式上,我们确实使用了 Spring Security 的表单认证功能,并且自定义了表单登录页。但实际上,这还远远不够。例如,在实际系统中,我们正常登录时使用的用户名和密码都来自数据库,这里却都写在配置上。更进一步,我们可以对每个登录用户都设定详细的权限,而并非一个通用角色。这些内容将在后面章节讲解。

 

 

你可能感兴趣的:(Spring,Security,spring,security,自定义表单登录,spring,security)