一、SecurityConfigurer
- SecurityConfigurer是security配顶层置类,主要规定了初始化和配置方法
- WebSecurityConfigurer是SecurityConfigurer子接口,仅作为标识接口,并未增加方法
- WebSecurityConfigurerAdapter抽象类是WebSecurityConfigurer的配置适配器,也是Security中主要使用的配置类,里面包含常见验证的所有方法
- 当需要指定特定配置时,需要继承WebSecurityConfigurerAdapter类,并在其中配置对应信息
二、指定登录页面
- 虽然 Spring Security 默认提供了登录页面,但实际项目中,通常使用自己开发的登录页面,所以 Spring Security 中不仅仅提供了默认登录页面,还支持用户自定义登录页面,只需要修改配置类即可
- 自定义登录页面
- 注意:登录地址为/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>
- 编写配置类,设置登录页面信息,配置类需要继承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():关闭
- formLogin():开启表单登录
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();
}
}
- 编写控制器
@RequestMapping("/toCore")
public String core() {
return "redirect:/core.html";
}
- 重启服务,然后访问任意路径,即可跳转到指定登录页面
三、定制登录参数
- 上面登录页面中可以看到action和username、password为固定名称,如果不使用此名称后端将无法接收
- 默认的参数名配置可以在UsernamePasswordAuthenticationFilter过滤器中找到
- org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
- usernameParameter:登录用户参数名
- passwordParameter:登录密码参数名
- postOnly:默认只能使用post登录
3. 可以通过配置指定usernameParameter和passwordParameter,然后在登录页面中修改表单名称
- 此处并未修改,只是设置了默认名称,两者保持一致即可
// 表单登录
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>
四、定制成功处理器
- 上述成功之后通过successForwardUrl()跳转路径为/toCore,是在内部controller控制的服务器内跳转,通过successHandler()方法进行控制成功后交给哪个类进行处理
- 默认处理类为ForwardAuthenticationSuccessHandler
- org.springframework.security.web.authentication.ForwardAuthenticationSuccessHandler
- 在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);
}
}
- 在 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"));
- 重启服务,验证成功之后将会跳转到指定网址,在第三方授权中,此处可以设置为登录成功后的回调地址