自定义spring security oauth2 /oauth/token以及token失效/过期的返回内容格式

2023-11-05

前言

在整合Spring Security Oauth2的时候,获取token的接口/oauth/token的返回内容格式为固定的,如下图所示:

而token过期或者无效的返回参数格式如下图所示:

实际在我们的项目中有时候会要求自定义返回内容格式,下面分别介绍获取token和token失效/过期的自定义返回内容格式。


自定义获取token接口的参数格式

1、创建接收获取token接口返回参数的实体

@Data
public class OauthResult {

    private String code;

    private String mesg;
}
@JsonSerialize(using = ResponseSerializer.class)
@Data
public class OauthResponse extends OauthResult{

    private Object data;
}

2、创建获取token接口返回值的转换类

创建一个类来完成对获取token接口的返回参数进行转换成我们自定义的格式,这里使用到了@JsonSerialize注解,该注解主要用于数据转换,不知道的可以自行百度

import com.bw.dsm.entity.OauthResponse;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.oauth2.common.OAuth2AccessToken;

import java.io.IOException;


public class ResponseSerializer extends StdSerializer<OauthResponse> {

    public ResponseSerializer() {
        super(OauthResponse.class);
    }

    @Override
    public void serialize(OauthResponse value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        OAuth2AccessToken oAuth2AccessToken = (OAuth2AccessToken) value.getData();

        gen.writeStartObject();
        if (oAuth2AccessToken != null){
            gen.writeStringField("code", value.getCode());
            gen.writeStringField("mesg", value.getMesg());

            gen.writeObjectFieldStart("data");
            gen.writeStringField("accessToken", oAuth2AccessToken.getValue());
            gen.writeNumberField("expiresIn",oAuth2AccessToken.getExpiresIn());
            gen.writeEndObject();
        } else {
            gen.writeStringField("code", "1");
            gen.writeStringField("mesg", "获取token失败");
        }

        gen.writeEndObject();
    }
}

3、新建切面类,将ResponseEntity进行重新组织,改变返回值

自定义切点,对postAccessToken方法进行增强,该方法是/oauth/token接口的返回方法,在这个方法的基础上改变返回值即可。

import com.bw.dsm.entity.OauthResponse;
import com.bw.dsm.util.AES128Util;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class AuthTokenAspect {

    private Logger logger = LoggerFactory.getLogger(getClass());

    /// @Around是可以改变controller返回值的
    @Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
    public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
        // 放行
        OauthResponse response = new OauthResponse();
        ObjectMapper mapper = new ObjectMapper();
        try {
            Object proceed = pjp.proceed();
            if (proceed != null) {
                ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity<OAuth2AccessToken>)proceed;
                OAuth2AccessToken body = responseEntity.getBody();
                if (responseEntity.getStatusCode().is2xxSuccessful()) {
                    response.setCode("0");
                    response.setMesg("");
                    response.setData(body);
                } else {
                    logger.error("error:{}", responseEntity.getStatusCode().toString());
                    response.setCode("1");
                    response.setMesg("获取token失败");
                }
            }
        } catch (Exception e){
            response.setCode("1");
            response.setMesg("获取token失败");
        }
        String result = mapper.writeValueAsString(response);
        return ResponseEntity
                .status(200)
                .body(AES128Util.JiaMi(result));
    }
}

我这里还另外对返回值进行了加密,如果不需要加密则直接返回response,即:

return ResponseEntity
        .status(200)
        .body(response);

这样,返回格式就成了我们自定义的格式了,下面可以看下未加密的自定义返回格式:

获取token接口调用成功:

获取token接口调用失败:

 

 


自定义token过期/无效的返回参数格式

1、在配置资源服务器的配置类中添加拦截

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        // 自定义token失效/错误返回信息
        OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
        authenticationEntryPoint.setExceptionTranslator(new CustomExceptionTranslator());
        resources.authenticationEntryPoint(authenticationEntryPoint);
    }
}

其他配置省略。按照各自业务需求来,这里只介绍自定义token过期/无效的返回参数格式。

2、自定义接收token无效/过期的错误信息转换类

import com.bw.dsm.util.AES128Util;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;

public class CustomExceptionTranslator extends DefaultWebResponseExceptionTranslator {

    @Override
    public ResponseEntity translate(Exception e) throws Exception {
        ResponseEntity translate = super.translate(e);
        ObjectMapper mapper = new ObjectMapper();
        OAuth2Exception body = (OAuth2Exception) translate.getBody();
        CustomOauthException customOauthException = new CustomOauthException(body.getMessage(), body.getOAuth2ErrorCode(), String.valueOf(body.getHttpErrorCode()));
//        ResponseEntity response = new ResponseEntity<>(customOauthException, translate.getHeaders(), translate.getStatusCode());
        return ResponseEntity
                .status(translate.getStatusCode())
                .header(String.valueOf(translate.getHeaders()))
                .body(AES128Util.JiaMi(mapper.writeValueAsString(customOauthException)));
    }
}

同样的这里我也将返回参数加密处理,如果不需要加密,如下所示:

public class CustomExceptionTranslator extends DefaultWebResponseExceptionTranslator {

    @Override
    public ResponseEntity translate(Exception e) throws Exception {
        ResponseEntity translate = super.translate(e);
        ObjectMapper mapper = new ObjectMapper();
        OAuth2Exception body = (OAuth2Exception) translate.getBody();
        CustomOauthException customOauthException = new CustomOauthException(body.getMessage(), body.getOAuth2ErrorCode(), String.valueOf(body.getHttpErrorCode()));
        ResponseEntity response = new ResponseEntity<>(customOauthException, translate.getHeaders(), translate.getStatusCode());
        return response;
    }
}

3、创建自定义token无效/过期返回参数格式类

@JsonSerialize(using = CustomOauthExceptionSerializer.class)
public class CustomOauthException extends OAuth2Exception {

    private String code;

    private String mesg;

    public CustomOauthException(String msg, String code, String mesg){
        super(msg);
        this.code = code;
        this.mesg = mesg;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMasg() {
        return mesg;
    }

    public void setMasg(String mesg) {
        this.mesg = mesg;
    }
}

4、token无效或过期返回值转换类

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;

public class CustomOauthExceptionSerializer extends StdSerializer {

    public CustomOauthExceptionSerializer() {
        super(CustomOauthException.class);

    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        gen.writeObjectField("code","1");
        gen.writeObjectField("mesg","token无效或已过期");
        gen.writeEndObject();
    }
}

这样,返回格式就成了我们自定义的格式了,下面可以看下未加密的自定义返回格式:

token无效返回:

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义spring security oauth2 /oauth/token以及token失效/过期的返回内容格式 的相关文章

随机推荐

  • Kubernetes 集群部署 ------ UI界面(三)

    官方文件 https github com kubernetes kubernetes tree master cluster addons dashboard 五 UI界面部署 在master01上操作 创建dashborad工作目录 r
  • springboot集成定时任务框架quartz

    springboot集成定时任务框架quartz quartz框架可以很方便的执行定时任务 任务可以持久化到数据库中 这里使用的数据库为postgres 集成步骤 1 quartz和数据库驱动maven依赖
  • 关于写代码的习惯

    写代码 是一项复杂的工作 但是 代码的质量不仅在于代码的功能 还在于它是否条理清晰 简略易懂 以下内容是希望大家写代码时有好习惯 在正确的前提下 长循环放在内层 可以减少cpu跨切循环的次数 代码一定要简略易懂 不要做无效操作 这样做只会浪
  • matlab 提取图片ARGB8888数据,输出到TXT

    image imread ss png 读入图片 A rgb2gray image 提取A值的矩阵 R image 1 提取R值的矩阵 G image 2 提取G值的矩阵 B image 3 提取B值的矩阵 ranks R size R 提
  • 移植外设后可以跳转但显示未定义

    提示例如 GPC S axf Error L6218E Undefined symbol FLASH EraseSector int referred from protocolalarm o 原因就是C跟C 公用 c 引用了C的文件 C的
  • matlab内存管理

    转自 http my donews com deng 2006 09 24 vijgqxehmkxiruywdauvxyiafogtskeymhyw 用 Matlab 进行大规模科学计算或仿真时 内存是一个需要时常注意的问题 当你写的 Ma
  • 数据结构之基:从根儿上了解数据结构的特性

    学好数据结构 就等于成功了一半 程序是对现实的模拟 现实是由时间和空间组成的 高效的人都是用最少的时间 最少的空间来做最伟大的事 程序亦是如此 我们要选择最合理的算法和最合理的数据结构 来写最好的代码 这也正是时间复杂度和空间复杂度的要求
  • osgEarth获取显卡和硬件信息

    osgEarth Capabilities类负责获取显卡和硬件信息
  • 【单元测试】使用PowerMock框架进行Java静态方法的单元测试

    简介 一般来说 Java中的静态方法无法用传统的Jmock进行单测 这也就给研发人员和测试人员造成了一定的困扰 本文介绍一种使用PowerMock执行静态方法单元测试的手段 其实网上也有使用如Mockito的方法 大家可以自行搜索 静态方法
  • DSP的cache一般在何时会生效,防止在cache使用造成数据不一致

    在使用DSP的cache使能所有的ddr操作时 发现如果只是写操作 根据cache的机制 如果没有在了L1级hit 则直接使用write buffer来完成写操作 假如hit的话 那之前一定发生过读操作 比如移位某个字 肯定是先读入L2 L
  • C++ 序列化和反序列化

    序列化 序列化 1 背景 2 定义 3 序列化评价指标 4 序列化实例 参考 序列化 1 背景 1 在TCP的连接上 它传输数据的基本形式就是二进制流 也就是一段一段的1和0 2 在一般编程语言或者网络框架提供的API中 传输数据的基本形式
  • HFSS常用操作汇总

    HFSS常用操作 操作类 convert to read only 切角 Non Model 圆极化天线使用Discrete扫频 peakGain and GainTotal 局部区域的电流或电场等的分布 没收敛需要检查的地方 带状线设置l
  • Android界面-attrs自定义属性

    知识点 1 路径 values attrs xml 2 结构 根标签 下一级declare styleable 子标签为attr 3 arr标签 包含属性 name 该属性名称 format 该属性的值格式 子标签 enum 列举出固定的取
  • M个梨子放N个盘子

    M个梨子放N个盘子 题目描述 Macro非常喜欢吃梨 有一天他得到了ACMICPC组委会送给他的一筐梨子 他比较心疼学生 就打算把梨子分给学生吃 现在他要把M个梨子放到N个盘子里面 我们允许有的盘子为空 你能告诉Macro有多少种分法吗 请
  • 基于ResNet的MSTAR数据集目标分类

    基于ResNet的MSTAR数据集目标分类 文章目录 基于ResNet的MSTAR数据集目标分类 说在前面 1 MSART数据集介绍 2 SAR目标分类网络 3 ResNet代码及训练 4 结尾 附录 代码 说在前面 前两篇文章主要讨论了C
  • [网络安全自学篇] 一 web学习及异或解密

    开始学习杨秀璋老师的网络安全 文章会经过优化 来作为学习打卡的标志 本文为CSDN博主 Eastmount 的原创文章 一 工具 术语 1 网安术语 常见安全网站及论坛 看雪 https bbs pediy com 安全客 https ww
  • Vuejs——(7)过渡(动画)

    本篇资料来于官方文档 http cn vuejs org guide transitions html 本文是在官方文档的基础上 更加细致的说明 代码更多更全 简单来说 更适合新手阅读 二十四 过渡动画 过渡动画的定义 简单来说 就是当模块
  • Junit源码与设计模式欣赏

    先介绍下这篇博文的由来 之前已经对JUnit的使用经行了深入的介绍和演示 参考JUnit学习 一 JUnit学习 二 其中的部分功能是通过分析JUnit源代码找到的 得益于这个过程有幸完整的拜读了JUnit的源码十分赞叹作者代码的精美 一直
  • 2022人机交互-考题复习

    最下面有2022的人机交互考题 简答题 什么是人机交互 Human Computer Interaction HCI 是一门专注于设计 评估和实施供人类使用的交互式计算系统的学科 人类处理机模型 最著名的信息处理模型 Card等 1983
  • 自定义spring security oauth2 /oauth/token以及token失效/过期的返回内容格式

    前言 在整合Spring Security Oauth2的时候 获取token的接口 oauth token的返回内容格式为固定的 如下图所示 而token过期或者无效的返回参数格式如下图所示 实际在我们的项目中有时候会要求自定义返回内容格