Spring Cloud OAuth2中/oauth/token的返回内容格式

 更新时间:2021年07月30日 16:18:45   作者:CodingPioneer  
Spring Cloud OAuth2 生成access token的请求/oauth/token的返回内容就需要自定义,本文就详细介绍一下,感兴趣的可以了解一下

背景

在前后端分离的项目中,一般后端返回给前端的格式是一个固定的json格式。在这个前提下,Spring Cloud OAuth2 生成access token的请求/oauth/token的返回内容就需要自定义。

访问/oauth/token示例如下:

在这里插入图片描述

原始返回值的格式如下:

在这里插入图片描述

我们希望使用我们自己固定的json格式,如下:

在这里插入图片描述

实现原理

原理就是通过切面编程实现对/oauth/token端点请求的结果进行拦截封装处理,由于/oauth/token是Spring Cloud OAuth2的内部端点,因此需要对相关的Spring源码进行分析。最终定位到

org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken()

方法上。

代码实现

相关类

CodeEnum.java

package com.wongoing.common.model;

/**
 * @description: 代码枚举
 * @author: zheng
 * @date: Created in 2021/1/26 11:18
 * @version: 0.0.1
 * @modified By:
 */
public enum CodeEnum {
    SUCCESS(0),
    ERROR(1);

    private Integer code;

    CodeEnum(Integer code) {
        this.code = code;
    }

    public Integer getCode() {
        return this.code;
    }
}

Result.java

package com.wongoing.common.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * @description: Rest API 接口方法返回类型定义
 * @author: zheng
 * @date: Created in 2021/1/26 13:25
 * @version: 0.0.1
 * @modified By:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> implements Serializable {
    private T data;
    private Integer code;
    private String msg;

    public static <T> Result<T> of(T data, Integer code, String msg) {
        return new Result<>(data, code, msg);
    }

    public static <T> Result<T> succeed(String msg) {
        return of(null, CodeEnum.SUCCESS.getCode(), msg);
    }

    public static <T> Result<T> succeed(T model, String msg) {
        return of(model, CodeEnum.SUCCESS.getCode(), msg);
    }

    public static <T> Result<T> succeed(T model) {
        return of(model, CodeEnum.SUCCESS.getCode(), "");
    }

    public static <T> Result<T> failed(String msg) {
        return of(null, CodeEnum.ERROR.getCode(), msg);
    }

    public static <T> Result<T> failed(T model, String msg) {
        return of(model, CodeEnum.ERROR.getCode(), msg);
    }
}

关键切面拦截器

在uaa项目中定义OauthTokenAspect.java

package com.wongoing.oauth2.filter;

import com.wongoing.common.constant.SecurityConstants;
import com.wongoing.common.context.TenantContextHolder;
import com.wongoing.common.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.stereotype.Component;

import java.security.Principal;
import java.util.Map;

/**
 * @description: oauth-token拦截器
 * 1. 赋值租户
 * 2. 统一返回token格式
 *
 * @author: zheng
 * @date: Created in 2021/7/12 16:25
 * @version: 0.0.1
 * @modified By:
 */
@Slf4j
@Component
@Aspect
public class OauthTokenAspect {

    @Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
    public Object handleControllerMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            Object[] args = joinPoint.getArgs();
            Principal principal = (Principal) args[0];
            if (!(principal instanceof Authentication)) {
                throw new InsufficientAuthenticationException("There is no client authentication. Try adding an appropriate authentication filter.");
            }
            String clientId = this.getClientId(principal);
            Map<String, String> parameters = (Map<String, String>) args[1];
            String grantType = parameters.get(OAuth2Utils.GRANT_TYPE);

            //保存租户id
            TenantContextHolder.setTenant(clientId);
            Object proceed = joinPoint.proceed();
            if (SecurityConstants.AUTHORIZATION_CODE.equals(grantType)) {
                /**
                 * 如果使用 @EnableOAuth2Sso 注解不能修改返回格式,否则授权码模式可以统一改
                 * 因为本项目的 sso-demo/ss-sso 里面使用了 @EnableOAuth2Sso 注解,所以这里就不修改授权码模式的token返回值了
                 */
                return proceed;
            } else {
                ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity<OAuth2AccessToken>) proceed;
                OAuth2AccessToken body = responseEntity.getBody();
                return ResponseEntity
                        .status(HttpStatus.OK)
                        .body(Result.succeed(body));
            }
        } finally {
            TenantContextHolder.clear();
        }
    }

    private String getClientId(Principal principal) {
        Authentication client = (Authentication) principal;
        if (!client.isAuthenticated()) {
            throw new InsufficientAuthenticationException("The client is not authenticated.");
        }
        String clientId = client.getName();
        if (client instanceof OAuth2Authentication) {
            clientId = ((OAuth2Authentication) client).getOAuth2Request().getClientId();
        }
        return clientId;
    }
}

其中的常量值:

public abstract class OAuth2Utils {
	public static final String GRANT_TYPE = "grant_type";
}
public interface SecurityConstants {
	/**
     * 授权码模式
     */
    String AUTHORIZATION_CODE = "authorization_code";
}

到此这篇关于Spring Cloud OAuth2中/oauth/token的返回内容格式的文章就介绍到这了,更多相关Spring Cloud OAuth2返回内容格式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java+Mysql学生管理系统源码

    Java+Mysql学生管理系统源码

    这篇文章主要为大家详细介绍了Java+Mysql学生管理系统源码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • Jsoup解析HTML实例及文档方法详解

    Jsoup解析HTML实例及文档方法详解

    这篇文章主要介绍了Jsoup如何解析一个HTML文档、从文件加载文档、从URL加载Document等方法,对Jsoup常用方法做了详细讲解,最近提供了一个示例供大家参考 使用DOM方法来遍历一个文档 从元素抽取属性,文本和HTML 获取所有链接
    2013-11-11
  • 浅谈java Properties类的使用基础

    浅谈java Properties类的使用基础

    下面小编就为大家分享一篇浅谈java Properties类的使用基础,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • java处理图片背景颜色的方法

    java处理图片背景颜色的方法

    这篇文章主要为大家详细介绍了java处理图片背景颜色的方法,蓝底寸照批量转换为白底,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04
  • SpringBoot配置多数据源的四种方式分享

    SpringBoot配置多数据源的四种方式分享

    在日常开发中我们都是以单个数据库进行开发,在小型项目中是完全能够满足需求的,但是,当我们牵扯到大型项目的时候,单个数据库就难以承受用户的CRUD操作,那么此时,我们就需要使用多个数据源进行读写分离的操作,本文就给大家介绍SpringBoot配置多数据源的方式
    2023-07-07
  • 关于MVC与SpringMVC的介绍、区别、执行流程

    关于MVC与SpringMVC的介绍、区别、执行流程

    这篇文章主要介绍了关于MVC与SpringMVC的介绍、区别、执行流程,MVC框架的主要目标是将应用程序的业务逻辑(Model)与用户界面(View)分离开来,从而提高应用程序的可维护性和可扩展性,需要的朋友可以参考下
    2023-05-05
  • JAVA函数的定义、使用方法实例分析

    JAVA函数的定义、使用方法实例分析

    这篇文章主要介绍了JAVA函数的定义、使用方法,结合实例形式分析了JAVA函数的基本概念、功能、原理、定义、使用方法与操作注意事项,需要的朋友可以参考下
    2020-04-04
  • SpringBoot使用redis生成订单号的实现示例

    SpringBoot使用redis生成订单号的实现示例

    在电商系统中,生成唯一订单号是常见需求,本文介绍如何利用SpringBoot和Redis实现订单号的生成,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-09-09
  • AsyncConfigurerSupport自定义异步线程池处理异常

    AsyncConfigurerSupport自定义异步线程池处理异常

    这篇文章主要为大家介绍了AsyncConfigurerSupport自定义异步线程池处理异常详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • MyBatis-Plus中静态工具Db的多种用法及实例分析

    MyBatis-Plus中静态工具Db的多种用法及实例分析

    本文将详细讲解MyBatis-Plus中静态工具Db的各种用法,并结合具体案例进行演示和说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03

最新评论