自定義登入
在預設的情況下,Spring Security
為我們生成的登入登出頁面如下:
我們可以自定義登入和登出頁面,我們使用thymeleaf
來編寫登入頁面,程式碼如下:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<title>Please Log In</title>
</head>
<body>
<h1>Please Log In</h1>
<form th:action="@{/login}" method="post">
<div>
<input type="text" name="username" placeholder="Username"/>
</div>
<div>
<input type="password" name="password" placeholder="Password"/>
</div>
<input type="submit" value="Log in" />
</form>
</body>
</html>
配置自定義登入相關設定:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// 認證相關
http.authorizeRequests(authorize ->
authorize
// /login.html請求不需要驗證
.requestMatchers(new AntPathRequestMatcher("/login")).permitAll()
.anyRequest()
.authenticated()
);
// 開啟登入表單
http.formLogin(form -> {
form
// 自定義登入頁面
.loginPage("/login")
// 自定義登入URL
.loginProcessingUrl("/login")
// 登入成功之後跳轉的頁面
.defaultSuccessUrl("/index")
.permitAll();
});
// 關閉csrf防護
http.csrf().disable();
return http.build();
}
登入成功之後跳轉頁面:
在現在的專案開發過程中,一般都是前後端分離的專案,後端只需要返回JSON資料,由前端自己進行跳轉,那麼我們可以進行如下配置:
// 開啟登入表單
http.formLogin(form -> {
form
// 自定義登入頁面
.loginPage("/login")
// 自定義登入URL
.loginProcessingUrl("/login")
// 用於前後端分離的情況,登入成功之後返回JSON資料
.successHandler(new AuthenticationSuccessHandlerImpl())
// 用於前後端分離的情況,登入失敗之後返回JSON資料
.failureHandler(new AuthenticationFailureHandlerImpl())
.permitAll();
});
上面分別配置了登入成功返回的JSON
和登入失敗的JSON
。AuthenticationSuccessHandlerImpl
,AuthenticationFailureHandlerImpl
分別實現Spring Security
提供的介面AuthenticationSuccessHandler
,AuthenticationFailureHandler
。
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
Map<String,Object> map = new HashMap<>();
map.put("code", "200");
map.put("message", "成功");
map.put("data", authentication);
String json = new ObjectMapper().writeValueAsString(map);
// 構建返回
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(json);
}
}
public class AuthenticationFailureHandlerImpl implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
Map<String,Object> map = new HashMap<>();
map.put("code", "-1");
map.put("message", "登入失敗");
map.put("data", exception.getLocalizedMessage());
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(json);
}
}
使用Postman測試:
自定義登出
// 登出表單
http.logout(logout -> {
logout
// 自定義登出地址
.logoutUrl("/logout").
// 使用者前後端分離登出返回JSON
logoutSuccessHandler(new LogoutSuccessHandlerImpl());
});
實現LogoutSuccessHandler
介面:
public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
Map<String,Object> map = new HashMap<>();
map.put("code", "200");
map.put("message", "登出成功");
map.put("data", authentication.getName());
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(json);
}
}