千家信息网

SpringBoot Security如何自定义异常处理

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这篇文章主要为大家展示了"SpringBoot Security如何自定义异常处理",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"SpringBoot Se
千家信息网最后更新 2026年11月03日SpringBoot Security如何自定义异常处理

这篇文章主要为大家展示了"SpringBoot Security如何自定义异常处理",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"SpringBoot Security如何自定义异常处理"这篇文章吧。

    SpringBoot Security自定义异常

    access_denied 方面异常

    原异常

    {    "error": "access_denied",    "error_description": "不允许访问"}

    现异常

    {    "success": false,    "error": "access_denied",    "status": 403,    "message": "不允许访问",    "path": "/user/get1",    "timestamp": 1592378892768}

    实现

    public class ResourceServerConfig extends ResourceServerConfigurerAdapter {    @Override    public void configure(ResourceServerSecurityConfigurer resources) {        // access_denied 方面异常        OAuth3AccessDeniedHandler oAuth3AccessDeniedHandler = new OAuth3AccessDeniedHandler();        oAuth3AccessDeniedHandler.setExceptionTranslator(new CustomWebResponseExceptionTranslator());        resources.accessDeniedHandler(oAuth3AccessDeniedHandler);    }}

    Invalid access token 方面异常

    原异常

    {    "error": "invalid_token",    "error_description": "Invalid access token: 4eb58ecf-e66de-4155-9477-64a1c9805cc8"}

    现异常

    {    "success": false,    "error": "invalid_token",    "status": 401,    "message": "Invalid access token: 8cd45925dbf6-4502-bd13-8101bc6e1d4b",    "path": "/user/get1",    "timestamp": 1592378949452}

    实现

    public class ResourceServerConfig extends ResourceServerConfigurerAdapter {    @Override    public void configure(ResourceServerSecurityConfigurer resources) {         // Invalid access token 方面异常        OAuth3AuthenticationEntryPoint authenticationEntryPoint = new OAuth3AuthenticationEntryPoint();        authenticationEntryPoint.setExceptionTranslator(new CustomWebResponseExceptionTranslator());        resources.authenticationEntryPoint(authenticationEntryPoint);    }}

    Bad credentials 方面异常(登陆出错)

    原异常

    {    "error": "invalid_grant",    "error_description": "用户名或密码错误"}

    现异常

    {    "success": false,    "error": "invalid_grant",    "status": 400,    "message": "用户名或密码错误",    "path": "/oauth/token",    "timestamp": 1592384576019}

    实现

    public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {     @Override    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {        endpoints.userDetailsService(detailsService)                .tokenStore(memoryTokenStore())                .exceptionTranslator(new CustomWebResponseExceptionTranslator())                .authenticationManager(authenticationManager)                //接收GET和POST                .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);    }}

    其他类

    @Getter@JsonSerialize(using = CustomOauthExceptionSerializer.class)public class CustomOauthException extends OAuth3Exception {    private String oAuth3ErrorCode;    private int httpErrorCode;    public CustomOauthException(String msg, String oAuth3ErrorCode, int httpErrorCode) {        super(msg);        this.oAuth3ErrorCode = oAuth3ErrorCode;        this.httpErrorCode = httpErrorCode;    }}
    public class CustomOauthExceptionSerializer extends StdSerializer {    private static final long serialVersionUID = 2652127645704345563L;    public CustomOauthExceptionSerializer() {        super(CustomOauthException.class);    }    @Override    public void serialize(CustomOauthException value, JsonGenerator gen, SerializerProvider provider) throws IOException {        gen.writeStartObject();        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();        gen.writeObjectField("success",false);        gen.writeObjectField("error",value.getOAuth3ErrorCode());        gen.writeObjectField("status", value.getHttpErrorCode());        gen.writeObjectField("message", value.getMessage());        gen.writeObjectField("path", request.getServletPath());        gen.writeObjectField("timestamp", (new Date()).getTime());        if (value.getAdditionalInformation()!=null) {            for (Map.Entry entry : value.getAdditionalInformation().entrySet()) {                String key = entry.getKey();                String add = entry.getValue();                gen.writeObjectField(key, add);            }        }        gen.writeEndObject();    }}
    public class CustomWebResponseExceptionTranslator extends DefaultWebResponseExceptionTranslator {    @Override    public ResponseEntity translate(Exception e) throws Exception {        ResponseEntity translate = super.translate(e);        OAuth3Exception body = translate.getBody();        CustomOauthException customOauthException = new CustomOauthException(body.getMessage(),body.getOAuth3ErrorCode(),body.getHttpErrorCode());        ResponseEntity response = new ResponseEntity<>(customOauthException, translate.getHeaders(),                translate.getStatusCode());        return response;    }}

    补充

    {    "error": "invalid_client",    "error_description": "Bad client credentials"}

    如果client_secret错误依然还是报错,如上内容,针对这个异常需要在如下方法中的addTokenEndpointAuthenticationFilter添加过滤器处理

      @Override    public void configure(AuthorizationServerSecurityConfigurer oauthServer) {      oauthServer                // 开启/oauth/token_key验证端口无权限访问                .tokenKeyAccess("permitAll()")                // 开启/oauth/check_token验证端口认证权限访问                .checkTokenAccess("isAuthenticated()")                .addTokenEndpointAuthenticationFilter(null)                .allowFormAuthenticationForClients();    }

    SpringSecurity自定义响应异常信息

    此处的异常信息设置的话,其中还是有坑的,比如你想自定义token过期信息,无效token这些,如果按照SpringSecurity的设置是不会生效的,需要加到资源的配置中。

    如果只是SpringSecurity的话,只需要实现AccessDeniedHandler和AuthenticationEntryPoint这2个接口就可以了。他们都是在ExceptionTranslationFilter中生效的。

    • AuthenticationEntryPoint 用来解决匿名用户访问无权限资源时的异常

    • ruAccessDeineHandler 用来解决认证过的用户访问无权限资源时的异常

    如果你想自定义token过期的话,需要实现AuthenticationEntryPoint这个接口,因为token过期了,访问的话也算是匿名访问。

    但是SpringSecurity的过滤器链中其实是有顺序的,校验token的OAuth3AuthenticationProcessingFilter在它前面,导致一直没有办法生效,所有需要添加到资源的配置上,demo如下:

    /** * @author WGR * @create 2021/8/23 -- 16:52 */@Componentpublic class SimpleAuthenticationEntryPoint implements AuthenticationEntryPoint {     @Override    public void commence(HttpServletRequest request, HttpServletResponse response,                         AuthenticationException authException) throws ServletException {        Throwable cause = authException.getCause();        try {            if (cause instanceof InvalidTokenException) {                Map map = new HashMap();                map.put("error", "无效token");                map.put("message", authException.getMessage());                map.put("path", request.getServletPath());                map.put("timestamp", String.valueOf(new Date().getTime()));                response.setContentType("application/json");                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);                try {                    ObjectMapper mapper = new ObjectMapper();                    mapper.writeValue(response.getOutputStream(), map);                } catch (Exception e) {                    throw new ServletException();                }            }        } catch (Exception e) {            e.printStackTrace();        }    }}

    则可以生效,返回信息具体如下:

    如果想设置没有权限的自定义异常信息的话:

    /** * @author WGR * @create 2021/8/23 -- 17:09 */@Componentpublic class SimpleAccessDeniedHandler implements AccessDeniedHandler {    @Override    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {        Map map = new HashMap();        map.put("message", "无权操作");        map.put("path", request.getServletPath());        map.put("timestamp", String.valueOf(new Date().getTime()));        response.setContentType("application/json");        response.setStatus(HttpServletResponse.SC_FORBIDDEN);        try {            ObjectMapper mapper = new ObjectMapper();            mapper.writeValue(response.getOutputStream(), map);        } catch (Exception e) {            throw new ServletException();        }    }}

    把它设置到springsecurity中,添加进去就可以了,如果不是想要捕获token过期的话,就直接添加进去也可以

    以上是"SpringBoot Security如何自定义异常处理"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

    信息 方面 权限 处理 内容 用户 资源 篇文章 错误 密码 接口 用户名 端口 过滤器 还是 学习 帮助 认证 配置 验证 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 上海喔噻互联网科技有限公司 深圳市人人互联网科技有限公司 广东万易互联网科技有限公司惠州分公司 广州大一互联网络科技有限公司 江苏根荣互联网科技 科技互联网公司装修 有马互联网科技 为想互联网科技 互联网金融科技委员会 互联网科技实习生岗位职责 中国互联网有什么科技含量 互联网科技公司有风险吗 互联网科技研发水平 互联网科技大赛获奖感言 徐州市互联网科技有限公司 合肥互联网科技公司公章图片 山东星卡互联网科技有限公司官网 上海创道互联网络科技有限公司 张家口科技产业互联网平台 10位科技互联网大佬 互联网扶贫科技 麻工互联网科技 迪茉互联网科技 丰台科技园 互联网 沃里互联网科技 宝灵互联网科技有限公司 中国互联网十大科技股排名 互联网保险科技创业 山东子淼互联网科技有限公司 互联网科技接地气
    0