SpringSecurity5 (2) ——自定义登录页面
一、自定义登录页面
在实际项目开发中,根据需求设计业务系统的登录界面,不会使用security提供的默认登录页面,本文使用SpringBoot
集成thymeleaf
开发前端页面。
(一)开发登录页面
在resources目录下新建目录templates,存放模板文件,按照实际需求开发login.html
,登录页面的用户名和密码的登录框name需要使用username
和password
,如果需要改动,需要修改配置类。
<div><label> 用户名 : <input type="text" name="username"/> </label></div>
<div><label> 密码: <input type="password" name="password"/> </label></div>
(二)引入依赖
引入thymeleaf
模板引擎依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
(三)开发Controller
新建一个LoginController
,跳转到login.html
页面
@Controller
public class LoginController {
@GetMapping("/login")
public String skipLogin(){
return "login";
}
}
(四)修改配置类
在Java配置文件中修改以下方法,新增login()
配置和defaultSuccessUrl()
配置
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/hello/admin").hasRole("ROOT")
.antMatchers("/hello").hasRole("USER").anyRequest().permitAll()
.and()
.csrf().disable().
formLogin().loginPage("/login") //自定义登录页面跳转
.defaultSuccessUrl("/hello")//登录成功后跳转
.and().httpBasic().disable()
.sessionManagement().disable()
.cors()
.and()
.logout();
}
/***
defaultSuccessUrl 就是说,它会默认跳转到 Referer 来源页面,如果 Referer 为空,没有来源页,则跳转到默认设置的页面。如果有Referer则跳转到referer页面
successForwardUrl 表示不管你是从哪里来的,登录后一律跳转到 successForwardUrl 指定的地址。例如 successForwardUrl 指定的地址为 /index ,
**/
二、自定义登录成功、失败及退出逻辑
未登录时,我们访问后台接口服务/hello
或者/hello/admin
时,security会重定向到登录页面,当我们登录成功后,页面会重定向到登录前访问的url
,可以查看上面defaultSuccessUrl和successForwardUrl
的区别。
目前很多系统使用前后端分离方案,登录成功后,前端要求返回JSON
字符串并把相应的信息存储到localStorage
中,后续直接从取本地取出使用。
(一)开发登录成功逻辑
实现AuthenticationSuccessHandler
接口,重写onAuthenticationSuccess
方法,登录成功后不再重定向到/hello
接口,直接往前台返回相应JSON
字符串
@Component
public class AuthSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
//处理登录成功逻辑
response.setHeader("Content-Type", "application/json;charset=utf-8");
String jsonStr = "{username:\"张三\",token:\"avasdaeawaweqwe123123asdad1231dasdasd\"}";
response.getWriter().print(jsonStr);
response.getWriter().flush();
}
}
登录成功后如下图所示
(二)开发登录失败逻辑
实现AuthenticationFailureHandler
接口,重写onAuthenticationFailure
方法,认证失败不在返回到登录页面(/login?error
)直接往前台返回相应JSON
字符串
@Component
public class AuthFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
//处理认证失败逻辑
response.setHeader("Content-Type", "application/json;charset=utf-8");
String jsonStr = "{code:\"400\",message:\"认证失败\"}";
response.getWriter().print(jsonStr);
response.getWriter().flush();
}
}
(三)开发退出逻辑
@Component
public class AuthLogoutHandler implements LogoutHandler {
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
{
/**
根据实际需求编写实际代码,可以是删除缓存中用户信息返回登录页面,或者是重定向到其他页面等
等,在此为了简便,后台打印一句话,向浏览器输出字符串。
**/
UserDetails user = (UserDetails) authentication.getPrincipal();
System.out.println("删除用户信息"+user.getUsername());
response.setHeader("Content-Type", "application/json;charset=utf-8");
try {
response.getWriter().print("缓存中用户信息已删除");
response.getWriter().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(四)修改配置类
注入上面登录成功及失败的逻辑类
@Autowired
private AuthSuccessHandler authSuccessHandler;
@Autowired
private AuthFailureHandler authFailureHandler;
@Autowired
private AuthLogoutHandler authLogoutHandler;
增加successHandler
和failureHandler
配置
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/hello/admin").hasRole("ROOT")
.antMatchers("/hello").hasRole("USER").anyRequest().permitAll()
.and()
.csrf().disable().
formLogin().loginPage("/login") //自定义登录页面跳转
.defaultSuccessUrl("/hello")
.successForwardUrl("/hello/admin")//登录成功后跳转
.successHandler(authSuccessHandler)
.failureHandler(authFailureHandler)
.and().httpBasic().disable()
.sessionManagement().disable()
.cors()
.and() //退出的路径及退出后的逻辑操作
.logout().logoutUrl("/logout").addLogoutHandler(authLogoutHandler);
}
(五)验证效果
登录成功后效果:
登录失败后效果:
退出效果:
因没有开发退出按钮,从登录页面登录成功后,在浏览器上访问/logout
接口,看下退出效果,已经在页面上显示
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用