SpringBoot整合SpringSecurity系列(3)-登录成功控制

1,230 阅读4分钟

一、SecurityConfigurer

  1. SecurityConfigurer是security配顶层置类,主要规定了初始化和配置方法
  2. WebSecurityConfigurer是SecurityConfigurer子接口,仅作为标识接口,并未增加方法
  3. WebSecurityConfigurerAdapter抽象类是WebSecurityConfigurer的配置适配器,也是Security中主要使用的配置类,里面包含常见验证的所有方法
  4. 当需要指定特定配置时,需要继承WebSecurityConfigurerAdapter类,并在其中配置对应信息

二、指定登录页面

  1. 虽然 Spring Security 默认提供了登录页面,但实际项目中,通常使用自己开发的登录页面,所以 Spring Security 中不仅仅提供了默认登录页面,还支持用户自定义登录页面,只需要修改配置类即可
  2. 自定义登录页面
    • 注意:登录地址为/login、用户名:username、密码:password
<!DOCTYPE html>
<html lang="zh">
<head>
     <meta charset="UTF-8">
     <title>系统登录</title>
</head>
<body>
  <form action="/login" method="post">
      用户名:<input type="text" name="username" /><br/>
      密码:<input type="password" name="password" /><br/>
      <input type="submit" value="登录"/>
  </form>
</body>
</html>
  1. 编写配置类,设置登录页面信息,配置类需要继承WebSecurityConfigurerAdapte,并重写 configure 方法
    • protected void configure(HttpSecurity http) throws Exception {}
    • 配置内容详解,HttpSecurity http顶层配置
      • formLogin():开启表单登录
        • loginPage("/login.html"):指定登录页面地址,不能丢弃/
        • loginProcessingUrl("/login"):表单提交路径,和登录表单action一致(不要求controller中必须存在)
        • successForwardUrl("/toCore"):成功跳转路径,默认POST请求
      • authorizeRequests(): 指定授权信息,解析规则从上到下,先配置先生效
        • antMatchers("/login.html").permitAll():/login.html允许访问
        • anyRequest().authenticated():所有请求都需要认证
      • csrf():跨站请求伪造保护
        • disable():关闭
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 表单登录
        http.formLogin()
            // 指定登录页面,/不能舍弃
            .loginPage("/login.html")
            // 表单提交路径,和登录表单配置一样
            .loginProcessingUrl("/login")
            // 成功跳转路径,默认POST请求
            .successForwardUrl("/toCore");

        // 授权信息,解析规则从上到下
        http.authorizeRequests()
            // /login.html不拦截
            .antMatchers("/login.html").permitAll()
            // 所有请求都拦截
            .anyRequest().authenticated();

        // 关闭csrf保护
        http.csrf().disable();
    }

    /**
     * 密码加密器
     */
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
  1. 编写控制器
@RequestMapping("/toCore")
public String core() {
    return "redirect:/core.html";
}
  1. 重启服务,然后访问任意路径,即可跳转到指定登录页面

三、定制登录参数

  1. 上面登录页面中可以看到action和username、password为固定名称,如果不使用此名称后端将无法接收
  2. 默认的参数名配置可以在UsernamePasswordAuthenticationFilter过滤器中找到
    • org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
    • usernameParameter:登录用户参数名
    • passwordParameter:登录密码参数名
    • postOnly:默认只能使用post登录

在这里插入图片描述 3. 可以通过配置指定usernameParameterpasswordParameter,然后在登录页面中修改表单名称

  • 此处并未修改,只是设置了默认名称,两者保持一致即可
// 表单登录
http.formLogin()
    // 指定登录页面,/不能舍弃
    .loginPage("/login.html")
    // 表单提交路径,和登录表单配置一样
    .loginProcessingUrl("/login")
    // 成功跳转路径,和登录表单中的一样,默认POST请求
    .successForwardUrl("/toCore")
    // 失败跳转地址
    //.failureUrl("/error.html");
    // 失败跳转路径
    .failureForwardUrl("/toError")
    // 指定表单登录名称:UsernamePasswordAuthenticationFilter
    // 默认username、password,如果修改修改需要和表单里面的保持一致
    .usernameParameter("username")
    .passwordParameter("password");
<!DOCTYPE html>
<html lang="zh">
<head>
     <meta charset="UTF-8">
     <title>系统登录</title>
</head>
<body>
  <form action="/login" method="post">
      用户名:<input type="text" name="username"/><br/>
      密码:<input type="password" name="password"/><br/>
      <input type="submit" value="登录"/>
  </form>
</body>
</html>

四、定制成功处理器

  1. 上述成功之后通过successForwardUrl()跳转路径为/toCore,是在内部controller控制的服务器内跳转,通过successHandler()方法进行控制成功后交给哪个类进行处理
  2. 默认处理类为ForwardAuthenticationSuccessHandler
    • org.springframework.security.web.authentication.ForwardAuthenticationSuccessHandler
  3. 在formLogin()中通过successHandler(AuthenticationSuccessHandler successHandler)指定授权成功处理器,所以自定义成功处理器时可以实现此接口,然后指定处理规则
    • 下面实现为进行重定向,而不是转发
import com.codecoord.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
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.util.Collection;

@Slf4j
public class AdvanceAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    /**
     * 指定跳转地址
     */
    private final String url;

    public AdvanceAuthenticationSuccessHandler(String url) {
        this.url = url;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {
        Object principal = authentication.getPrincipal();
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        log.info("授权主题【{}】", JsonUtil.toJson(principal));
        log.info("授权信息【{}】", JsonUtil.toJson(authorities));

        // 服务器重定向,例如需要跳转到外部网站
        response.sendRedirect(url);
    }
}
  1. formLogin() 中指定处理规则
    • successHandler(new AdvanceAuthenticationSuccessHandler("www.codecoord.com"))
    • 指定鉴权成功处理器,指定之后上面成功跳转配置失效
// 表单登录
http.formLogin()
    // 指定登录页面,/不能舍弃
    .loginPage("/login.html")
    // 表单提交路径,和登录表单配置一样
    .loginProcessingUrl("/login")
    // 成功跳转路径,和登录表单中的一样,默认POST请求
    .successForwardUrl("/toCore")
    // 失败跳转地址
    //.failureUrl("/error.html");
    // 失败跳转路径
    .failureForwardUrl("/toError")
    // 指定表单登录名称:UsernamePasswordAuthenticationFilter
    // 默认username、password
    .usernameParameter("username")
    .passwordParameter("password")
    // 指定鉴权成功处理器,指定之后上面成功跳转配置失效
    .successHandler(new AdvanceAuthenticationSuccessHandler("http://www.codecoord.com"));
  1. 重启服务,验证成功之后将会跳转到指定网址,在第三方授权中,此处可以设置为登录成功后的回调地址