Spring Security JSON交互

本文将介绍如何对 Spring Security 进行改造,以适应使用 JSON 交互的前后端分离开发模式。

一、JSON 交互

在现如今的 Web 开发中,前后端分离的开发模式是绝对的主流。在这种开发模式下,前后端将独立,后端只提供接口,接收请求并返回数据。

此时,Spring Security 相对 “老旧” 的设计就会显得过时,比如:

  • 在未登录、无权限时,返回登录页面要求登录(而非返回 JSON,并在 JSON 中指示权限不足)
  • 当登录成功后,跳转至首页(而非返回登录成功的结果)

因此,对 Spring Security 做 JSON 改造是十分有必要的。

二、配置

1. 登录成功处理器

(1) 编写

编写类,继承 AuthenticationSuccessHandler,在方法中返回 JSON 即可。

1
2
3
4
5
6
7
8
@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
PrintWriter writer = response.getWriter();
writer.println("Success Login");
}
}

(2) 配置

在配置类中配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
LoginSuccessHandler loginSuccessHandler;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.successHandler(loginSuccessHandler)
}
}

2. 登录失败处理器

(1) 编写

编写类,继承 AuthenticationFailureHandler,在方法中返回 JSON 即可。

1
2
3
4
5
6
7
8
@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
PrintWriter writer = response.getWriter();
writer.println("Failure Login");
}
}

(2) 配置

在配置类中配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
LoginFailureHandler loginFailureHandler;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.failureHandler(loginFailureHandler)
}
}

3. 登出处理器

(1) 编写

编写类,继承 LogoutSuccessHandler,在方法中返回 JSON 即可。

1
2
3
4
5
6
7
8
@Component
public class LogoutHandler implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
PrintWriter writer = response.getWriter();
writer.println("Success Logout");
}
}

(2) 配置

在配置类中配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
LogoutHandler logoutHandler;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.logoutSuccessHandler(logoutHandler)
}
}

4. 未登录处理器

(1) 编写

编写类,继承 AuthenticationEntryPoint,在方法中返回 JSON 即可。

1
2
3
4
5
6
7
8
@Component
public class AuthenticationEntryPoint implements org.springframework.security.web.AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
PrintWriter writer = response.getWriter();
writer.println("Please Login");
}
}

(2) 配置

在配置类中配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
AuthenticationEntryPoint authenticationEntryPoint;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
}
}

5. 无权限处理器

(1) 编写

编写类,继承 LogoutSuccessHandler,在方法中返回 JSON 即可。

1
2
3
4
5
6
7
8
@Component
public class AccessDeniedHandler implements org.springframework.security.web.access.AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
PrintWriter writer = response.getWriter();
writer.println("Access Denied");
}
}

(2) 配置

在配置类中配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
AccessDeniedHandler accessDeniedHandler;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
}
}

参考