一、自定義登錄頁面
在實際項目開發中,根據需求設計業務系統的登錄界面,不會使用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接口,看下退出效果,已經在頁面上顯示

