文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SpringBoot Security如何自定义异常处理

2023-06-22 03:44

关注

这篇文章主要为大家展示了“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<CustomOauthException> {    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<String, String> 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<OAuth3Exception> translate(Exception e) throws Exception {        ResponseEntity<OAuth3Exception> translate = super.translate(e);        OAuth3Exception body = translate.getBody();        CustomOauthException customOauthException = new CustomOauthException(body.getMessage(),body.getOAuth3ErrorCode(),body.getHttpErrorCode());        ResponseEntity<OAuth3Exception> 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中生效的。

SpringBoot Security如何自定义异常处理

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

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

@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();        }    }}

SpringBoot Security如何自定义异常处理

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

SpringBoot Security如何自定义异常处理

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

@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如何自定义异常处理

SpringBoot Security如何自定义异常处理

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

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯