Spring Cloud OAuth2中/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返回内容格式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • spring cloud oauth2 实现用户认证登录的示例代码

    需求 在微服务架构中,我们有很多业务模块,每个模块都需要有用户认证,权限校验.有时候也会接入来自第三方厂商的应用.要求是只登录一次,即可在各个服务的授权范围内进行操作.看到这个需求,立马就想到了这不就是单点登录吗?于是基于这样的需求,作者使用spring-cloud-oauth2去简单的实现了下用户认证和单点登录. 相关介绍 OAuth2 OAuth2是一个关于授权的网络标准,他定制了设计思路和执行流程.OAuth2一共有四种授权模式:授权码模式(authorization code).简化模式

  • Spring Cloud下OAUTH2注销的实现示例

    接上文Spring Cloud下基于OAUTH2认证授权的实现,我们将基于Spring Cloud实现OAUTH2的注销功能. 1 增加自定义注销Endpoint 所谓注销只需将access_token和refresh_token失效即可,我们模仿org.springframework.security.oauth2.provider.endpoint.TokenEndpoint写一个使access_token和refresh_token失效的Endpoint: @FrameworkEndpoi

  • Spring Cloud OAuth2 实现用户认证及单点登录的示例代码

    OAuth 2 有四种授权模式,分别是授权码模式(authorization code).简化模式(implicit).密码模式(resource owner password credentials).客户端模式(client credentials),具体 OAuth2 是什么,可以参考这篇文章.(http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html) 本文我们将使用授权码模式和密码模式两种方式来实现用户认证和授权管理. OAuth2 其

  • Spring cloud oauth2如何搭建认证资源中心

    一 认证中心搭建 添加依赖,如果使用spring cloud的话,不管哪个服务都只需要这一个封装好的依赖即可 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> 配置spring security /** * security配置类 */

  • Spring Cloud下基于OAUTH2认证授权的实现示例

    在Spring Cloud需要使用OAUTH2来实现多个微服务的统一认证授权,通过向OAUTH服务发送某个类型的grant type进行集中认证和授权,从而获得access_token,而这个token是受其他微服务信任的,我们在后续的访问可以通过access_token来进行,从而实现了微服务的统一认证授权. 本示例提供了四大部分: discovery-service:服务注册和发现的基本模块 auth-server:OAUTH2认证授权中心 order-service:普通微服务,用来验证认

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

    目录 背景 实现原理 代码实现 相关类 关键切面拦截器 背景 在前后端分离的项目中,一般后端返回给前端的格式是一个固定的json格式.在这个前提下,Spring Cloud OAuth2 生成access token的请求/oauth/token的返回内容就需要自定义. 访问/oauth/token示例如下: 原始返回值的格式如下: 我们希望使用我们自己固定的json格式,如下: 实现原理 原理就是通过切面编程实现对/oauth/token端点请求的结果进行拦截封装处理,由于/oauth/tok

  • Spring Cloud OAuth2实现自定义token返回格式

    目录 问题描述 解决方案 总结 最近读者朋友针对Spring Security OAuth2.0 想要陈某补充一些知识,如下: 今天这篇文章就来回答其中一个问题:如何自定义token的返回格式? 问题描述 Spring Security OAuth的token返回格式都是默认的,但是往往这个格式是不适配系统,/oauth/token返回的格式如下: { "access_token": token "token_type": "bearer", &

  • 微服务间调用Retrofit在Spring Cloud Alibaba中的使用

    目录 前置知识 搭建 使用 集成与配置 服务间调用 服务限流 熔断降级 总结 前置知识 在微服务项目中,如果我们想实现服务间调用,一般会选择Feign.之前介绍过一款HTTP客户端工具Retrofit,配合SpringBoot非常好用!其实Retrofit不仅支持普通的HTTP调用,还能支持微服务间的调用,负载均衡和熔断限流都能实现.今天我们来介绍下Retrofit在Spring Cloud Alibaba下的使用,希望对大家有所帮助! SpringBoot实战电商项目mall(50k+star

  • 详解spring cloud ouath2中的资源服务器

    资源服务器就是业务服务 如用户服务,订单服务等 第三方需要到资源服务器调用接口获取资源 ResourceServerConfig ResourceServerConfig是资源服务器的核心配置 用于验证token 与网关配置相似 其中.antMatchers("/**").access("#oauth2.hasScope('user')") 需要oauth_client_details表的scope配合 意思是访问所有资源 需要客户端有scope需要有user @C

  • spring cloud oauth2 feign 遇到的坑及解决

    目录 springcloudoauth2feign遇到的坑 客户端模式 基于springsecurity springcloud微服务增加oauth2权限后feign调用报null 一般是这样实现的 spring cloud oauth2 feign 遇到的坑 关于oauth2相关的内容这里不重复描述,在spring cloud中在管理内部api时鉴权相信有很多人会有疑问,这里描述两种比较low的用法,由于公司内部使用的是阿里云edas这里仅仅是记录一下,如果有更好的用法在请赐教,不喜勿喷! 客

  • Spring Cloud oauth2 认证服务搭建过程示例

    目录 安装httpie 导入数据库脚本 sts中导入项目 修改 POM文件 修改配置文件 修改主类文件 编译,运行 测试 查看Redis缓存 安装httpie 安装httpie 需要 python 环境 pip install --upgrade httpie 进入D:\Project目录,在此目录下打开CMD,调用httpie,创建 oauth2 项目 http -d https://start.spring.io/starter.zip javaVersion==17 groupId==co

  • 浅析Spring Cloud Gateway中的令牌桶限流算法

    目录 前言 回顾限流算法 计数器/时间窗口法 漏桶法 令牌桶法 主要逻辑分析 前言 在一个分布式高并发的系统设计中,限流是一个不可忽视的功能点.如果不对系统进行有效的流量访问限制,在双十一和抢票这种流量洪峰的场景下,很容易就会把我们的系统打垮.而作为系统服务的卫兵的网关组件,作为系统服务的统一入口,更需要考虑流量的限制,直接在网关层阻断流量比在各个系统中实现更合适.Spring Cloud Gateway的实现中,就提供了限流的功能,下面主要分析下Spring Cloud Gateway中是如何

  • Spring Cloud Ribbon 中的 7 种负载均衡策略的实现方法

    目录 Ribbon介绍 负载均衡设置 7种负载均衡策略 1.轮询策略 2.权重策略 3.随机策略 4.最小连接数策略 5.重试策略 6.可用性敏感策略 7.区域敏感策略 项目源码 总结 负载均衡通器常有两种实现手段,一种是服务端负载均衡器,另一种是客户端负载均衡器,而我们今天的主角 Ribbon 就属于后者——客户端负载均衡器. 服务端负载均衡器的问题是,它提供了更强的流量控制权,但无法满足不同的消费者希望使用不同负载均衡策略的需求,而使用不同负载均衡策略的场景确实是存在的,所以客户端负载均衡就

随机推荐