程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • SpringSecurity

    • Spring Security是什么
    • 认证与授权的基本概念
    • Spring Security 的默认配置
    • SpringSecurity的默认登录页
    • Spring Security 的 Filter 机制
    • HttpSecurity 与自定义登录页面
    • Spring Security 的核心组件与扩展
    • Spring Security 中的用户认证与角色管理
    • Spring Security 的授权机制与安全表达式
    • Security 的 Session 与 Token 管理
    • Spring Security 集成第三方登录
    • Spring Security 集成 QQ 登录与 JWT 认证
    • Spring Security 登录认证源码
    • Spring Security - JWT认证实战
    • Spring Security - JWT授权实战
    • Spring Security 异常处理与自定义逻辑
      • 1. 认证与授权异常处理
        • 1.1 认证失败处理
        • 1.2 授权失败处理
        • 1.3 Spring Security 配置异常处理器
      • 2. 登录、注销与记住我功能
        • 2.1 登录成功后的跳转逻辑
        • 2.2 记住我功能
        • 2.3 注销功能
  • SpringSecurity
  • SpringSecurity
scholar
2024-08-20
目录

Spring Security 异常处理与自定义逻辑

# Spring Security 异常处理与自定义逻辑

前言

在实际项目中,除了基本的认证和授权功能之外,处理异常和实现自定义逻辑也是非常重要的。本节将详细介绍如何在 Spring Security 中自定义认证与授权失败的处理逻辑、自定义登录成功后的跳转、以及实现“记住我”功能等。

# 1. 认证与授权异常处理

Spring Security 默认的异常处理会在认证失败或授权失败时重定向到一个标准的错误页面,通常为 /login?error 或 /access-denied。但在实际项目中,我们可能需要自定义这些处理逻辑。

# 1.1 认证失败处理

认证失败通常发生在用户登录时输入了错误的用户名或密码。我们可以通过自定义 AuthenticationFailureHandler 来处理这一场景。

代码示例:自定义认证失败处理器

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
        // 自定义认证失败后的响应
        Map<String, String> responseData = new HashMap<>();
        responseData.put("error", "认证失败");
        responseData.put("message", exception.getMessage());

        // 返回 JSON 数据
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().write(new ObjectMapper().writeValueAsString(responseData));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

重要参数说明:

  • AuthenticationFailureHandler:Spring Security 提供的接口,用于自定义认证失败后的处理逻辑。
  • AuthenticationException:包含了认证失败的详细信息,可以根据不同的异常类型返回不同的错误提示。

# 1.2 授权失败处理

授权失败通常发生在用户尝试访问无权限的资源时,默认会重定向到 /access-denied 页面。可以通过自定义 AccessDeniedHandler 来实现自定义处理。

代码示例:自定义授权失败处理器

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
        // 自定义授权失败后的响应
        Map<String, String> responseData = new HashMap<>();
        responseData.put("error", "无权限访问");
        responseData.put("message", accessDeniedException.getMessage());

        // 返回 JSON 数据
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.getWriter().write(new ObjectMapper().writeValueAsString(responseData));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

重要参数说明:

  • AccessDeniedHandler:Spring Security 提供的接口,用于自定义授权失败后的处理逻辑。
  • AccessDeniedException:包含了授权失败的详细信息,通常可以直接将其信息返回给前端。

# 1.3 Spring Security 配置异常处理器

将自定义的异常处理器集成到 Spring Security 中。

代码示例:Spring Security 配置异常处理

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/login", "/register").permitAll()
                .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")
                .failureHandler(new CustomAuthenticationFailureHandler()) // 配置自定义认证失败处理器
            .and()
            .exceptionHandling()
                .accessDeniedHandler(new CustomAccessDeniedHandler()); // 配置自定义授权失败处理器
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 2. 登录、注销与记住我功能

在实际项目中,登录后的跳转、记住我功能以及注销功能都是常见的需求。Spring Security 提供了丰富的配置选项,允许我们自定义这些功能。

# 2.1 登录成功后的跳转逻辑

Spring Security 提供了 AuthenticationSuccessHandler 接口用于自定义登录成功后的操作。你可以根据不同的角色或条件跳转到不同的页面,或者直接返回 JSON 数据给前端。

代码示例:自定义登录成功处理器

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        // 自定义登录成功后的响应
        Map<String, String> responseData = new HashMap<>();
        responseData.put("message", "登录成功");
        responseData.put("username", authentication.getName());

        // 返回 JSON 数据
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().write(new ObjectMapper().writeValueAsString(responseData));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

重要参数说明:

  • AuthenticationSuccessHandler:接口,用于自定义登录成功后的处理逻辑。
  • Authentication:封装了登录成功后的用户信息,可以根据此信息进行个性化的跳转或操作。

# 2.2 记住我功能

记住我功能允许用户在关闭浏览器后仍然保持登录状态。Spring Security 提供了 rememberMe() 方法来轻松实现此功能。

代码示例:配置记住我功能

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/login", "/register").permitAll()
                .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")
                .successHandler(new CustomAuthenticationSuccessHandler()) // 配置自定义登录成功处理器
            .and()
            .rememberMe()
                .key("uniqueAndSecret") // 配置一个唯一的密钥
                .tokenValiditySeconds(86400) // 记住我功能的有效期,单位为秒,这里设置为1天
                .userDetailsService(myUserDetailsService()); // 使用自定义的 UserDetailsService 进行用户加载
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

重要参数说明:

  • rememberMe().key("uniqueAndSecret"):设置一个唯一的密钥,用于生成记住我的 Token,这个密钥应当保密。
  • tokenValiditySeconds(int seconds):设置记住我的有效期,单位为秒。
  • userDetailsService(UserDetailsService service):配置用于加载用户的服务,通常使用你自定义的 UserDetailsService。

# 2.3 注销功能

Spring Security 提供了完善的注销功能,允许你自定义注销路径、注销成功后的跳转等。

代码示例:配置注销功能

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/login", "/register").permitAll()
                .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")
                .successHandler(new CustomAuthenticationSuccessHandler()) // 配置自定义登录成功处理器
            .and()
            .rememberMe()
                .key("uniqueAndSecret")
                .tokenValiditySeconds(86400)
                .userDetailsService(myUserDetailsService())
            .and()
            .logout()
                .logoutUrl("/logout")  // 配置自定义的注销路径
                .logoutSuccessUrl("/login?logout")  // 注销成功后跳转的路径
                .delete

Cookies("JSESSIONID")  // 注销时删除指定的 Cookie
                .permitAll();  // 允许所有用户访问注销路径
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

重要参数说明:

  • logoutUrl("/logout"):设置自定义的注销路径,用户访问该路径时将执行注销操作。
  • logoutSuccessUrl("/login?logout"):设置注销成功后的跳转路径,可以重定向到登录页面或其他页面。
  • deleteCookies(String... cookieNames):注销时删除指定的 Cookie,如 JSESSIONID。
  • permitAll():允许所有用户访问注销路径。

总结

通过自定义认证与授权失败的处理逻辑、自定义登录成功后的操作,以及配置记住我和注销功能,你可以灵活地控制用户登录、注销、异常处理等流程。这些配置不仅提升了用户体验,也为实现复杂的业务逻辑提供了扩展性。

编辑此页 (opens new window)
上次更新: 2024/12/29, 23:35:48
Spring Security - JWT授权实战

← Spring Security - JWT授权实战

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式