1 github: 源码地址 2 security05 子工程自定义登录成功、登录失败处理程序
自定义匿名访问无权、已认证无权访问处理程序
自定义记住我认证、退出登录成功处理程序
4.0.0 com.yzm security 0.0.1-SNAPSHOT ../pom.xml security05 0.0.1-SNAPSHOT jar security05 Demo project for Spring Boot com.yzm common 0.0.1-SNAPSHOT org.springframework.boot spring-boot-maven-plugin
项目结构
application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test04?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
username: root
password: root
main:
allow-bean-definition-overriding: true
mybatis-plus:
mapper-locations: classpath:/mapper
@Slf4j
public class SecLoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
log.info("登录成功");
// 重定向到/home
response.sendRedirect(request.getContextPath() + "/home");
}
}
package com.yzm.security05.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
public class SecLoginFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
log.info("登录失败:" + exception.getMessage());
// 重定向到登录页
response.sendRedirect(request.getContextPath() + "/auth/login?error");
}
}
在SecurityConfig#configure
//配置资源权限规则
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// 关闭CSRF跨域
.csrf().disable()
// 登录
.formLogin()
.loginPage("/auth/login") //指定登录页的路径,默认/login
.loginProcessingUrl("/login") //指定自定义form表单请求的路径(必须跟login.html中的form action=“url”一致)
//.defaultSuccessUrl("/home", true) // 登录成功后的跳转url地址,默认是 "/"
//.failureUrl("/auth/login?error") // 登录失败后的跳转url地址,默认是 "/login?error"
.successHandler(new SecLoginSuccessHandler())
.failureHandler(new SecLoginFailureHandler())
.permitAll()
.and()
...
// 访问路径URL的授权策略,如注册、登录免登录认证等
.authorizeRequests()
.antMatchers("/", "/home", "/register", "/auth/login").permitAll() //指定url放行
.antMatchers("/hello").rememberMe()
.anyRequest().authenticated() //其他任何请求都需要身份认证
;
}
3.1 测试
启动项目,登录时输入错误的密码
然后再输入正确的密码
package com.yzm.security05.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
public class SecAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response.sendRedirect(request.getContextPath() + "/auth/login?authentication");
}
}
package com.yzm.security05.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
public class SecAccessDeniedHandler extends AccessDeniedHandlerImpl {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
log.info("授权失败:" + accessDeniedException.getMessage());
// 重定向到登录页
response.sendRedirect(request.getContextPath() + "/401");
}
}
在SecurityConfig#configure
//配置资源权限规则
@Override
protected void configure(HttpSecurity http) throws Exception {
http
...
// 登录
.formLogin()
.loginPage("/auth/login") //指定登录页的路径,默认/login
.loginProcessingUrl("/login") //指定自定义form表单请求的路径(必须跟login.html中的form action=“url”一致)
//.defaultSuccessUrl("/home", true) // 登录成功后的跳转url地址,默认是 "/"
//.failureUrl("/auth/login?error") // 登录失败后的跳转url地址,默认是 "/login?error"
.successHandler(new SecLoginSuccessHandler())
.failureHandler(new SecLoginFailureHandler())
.permitAll()
.and()
// 异常处理
.exceptionHandling()
.authenticationEntryPoint(new SecAuthenticationEntryPoint()) // 需要认证
//.accessDeniedPage("/401") // 拒接访问跳转页面
.accessDeniedHandler(new SecAccessDeniedHandler()) // 授权失败
.and()
// 访问路径URL的授权策略,如注册、登录免登录认证等
.authorizeRequests()
.antMatchers("/", "/home", "/register", "/auth/login").permitAll() //指定url放行
.antMatchers("/hello").rememberMe()
.anyRequest().authenticated() //其他任何请求都需要身份认证
;
}
4.1 测试
重启项目,访问/home,点击用户详情
登录yzm,访问/admin
@Slf4j
public class SecAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
log.info("使用记住我功能,认证成功:" + authentication.getPrincipal());
}
}
package com.yzm.security05.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
public class SecLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
if (authentication != null) {
Object principal = authentication.getPrincipal();
if (principal instanceof User) {
String username = ((User) principal).getUsername();
log.info("退出成功,用户名:{}", username);
}
}
// 重定向到登录页
response.sendRedirect(request.getContextPath() + "/auth/login?logout");
}
}
在SecurityConfig#configure
@Override
protected void configure(HttpSecurity http) throws Exception {
http
...
// 自动登录
.rememberMe()
.tokenValiditySeconds(120)
.authenticationSuccessHandler(new SecAuthenticationSuccessHandler())
.and()
// 退出登录
.logout().permitAll()
.deletecookies("JSESSIONID")
//.logoutSuccessUrl("/auth/login?logout") // 默认是 "/login?logout"
.logoutSuccessHandler(new SecLogoutSuccessHandler())
.permitAll()
.and()
// 访问路径URL的授权策略,如注册、登录免登录认证等
.authorizeRequests()
.antMatchers("/", "/home", "/register", "/auth/login").permitAll() //指定url放行
.antMatchers("/hello").rememberMe()
.anyRequest().authenticated() //其他任何请求都需要身份认证
;
}
5.1 测试
重启,登录yzm,选中记住我,然后关闭浏览器,重开浏览器。访问 /home
点击注销



