一、自定义登录页面
在实际项目开发中,根据需求设计业务系统的登录界面,不会使用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
接口,看下退出效果,已经在页面上显示