【疑难杂症】-一种简单高效的Spring Security oauth token兼容JSON格式的办法

简介: 为了统一接口请求格式,要将Spring Security获取token接口改成接收JSON格式,如下是我的几种尝试,最后一种为简单有效办法。

在这里插入图片描述

为了统一接口请求格式,要将Spring Security获取token接口改成接收JSON格式,如下是我的几种尝试,最后一种为简单有效办法。

在Spring Cloud Gateway处理JSON转application/x-www-form-urlencoded(无效)

代码是这样的

@Component
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class PlatformRequestGlobalFilter implements GlobalFilter, Ordered {

    @Value("${project.gateway.filter.order: -10}")
    private int order;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        return DataBufferUtils.join(request.getBody())
                .flatMap(dataBuffer -> {
                    byte[] bytes = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(bytes);
                    String json = new String(bytes, StandardCharsets.UTF_8);
                    DataBufferUtils.release(dataBuffer);
                    try {
                        //json参数转换
                        HashMap<String, String> result =  new ObjectMapper().readValue(json, HashMap.class);
                        ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
                            @Override
                            public HttpHeaders getHeaders() {
                                HttpHeaders httpHeaders = new HttpHeaders();
                                httpHeaders.putAll(super.getHeaders());
                                httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
                                return httpHeaders;
                            }

                            @Override
                            public URI getURI() {
                                //json参数转换成key=value&key1=value1形式
                                String params = mapToString(result);
                                //只是测试,地址写死了,参数是拼接的
                                return URI.create("http://localhost:8010/oauth/token?" + params);
                            }
                        };
                        //替换request
                        return chain.filter(exchange.mutate().request(mutatedRequest).build());
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
                    
                    return chain.filter(exchange);

                });
    }

    private String mapToString(HashMap<String, String> map) {
        final StringBuilder strBuilder = StrUtil.builder();
        boolean isFirst = true;
        if (MapUtil.isNotEmpty(map)) {
            for (Entry<String, String> entry : map.entrySet()) {
                if (entry.getKey() != null && entry.getValue() != null) {
                    if (isFirst) {
                        isFirst = false;
                    } else {
                        strBuilder.append("&");
                    }
                    strBuilder.append(CharSequenceUtil.toUnderlineCase(entry.getKey())).append("=").append(Convert.toStr(entry.getValue()));
                }
            }
        }
        return strBuilder.toString();
    }

    @Override
    public int getOrder() {
        return order;
    }

}

原以为将json请求在网关层替换为application/x-www-form-urlencoded格式,并将参数转换key=value&key1=value1形式,拼接最后的请求地址
http://localhost:8010/oauth/token?key=value&key1=value1,这样就可以生效了,但测试后会报:java.lang.IllegalStateException: completed 错误

Filter RouteLocator 路由跳转形式(无效)

@Configuration
public class FilterConfig {

    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder, ObjectMapper objectMapper) {
        return builder
                .routes()
                .route("path_route_change",
                        r -> r.path("/oauth/token")
                                .filters(f -> f
                                        .modifyRequestBody(String.class,String.class,"application/x-www-form-urlencoded",new RequestBodyRewrite(objectMapper))
                                )
                                .uri("http://localhost:8010/oauth/token"))
                .build();
    }
}

stackoverflow 提供的方式(无效)

这种办法根本不进Filter,在独立应用的时候也测试了
可见地址:https://stackoverflow.com/questions/38165131/spring-security-oauth2-accept-json

包装 oauth/token接口(有效)

    @PostMapping("oauth/api/token")
    public OAuth2AccessToken getToken(@Valid @RequestBody AuthTokenReq authTokenReq) {
        Map<String, String> params = new HashMap<>();
        params.put("grant_type", authTokenReq.getGrantType());
        params.put("client_id", authTokenReq.getClientId());
        params.put("client_secret", authTokenReq.getClientSecret());

        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(authTokenReq.getClientId(), authTokenReq.getClientSecret(), new ArrayList<>());

        ResponseEntity<OAuth2AccessToken> oAuth2AccessToken = tokenEndpoint.postAccessToken(usernamePasswordAuthenticationToken, params);

        return oAuth2AccessToken.getBody();
    }

新写一个REST接口,调用TokenEndpoint 的postAccessToken方法,还是这种办法最简单有效。

这里我通过TokenEndpoint 直接调用了postAccessToken方法,而不是采用Http请求oauth/token再次自我请求的方式,这种方式显得更优雅,性能也更高。

相关文章
|
5月前
|
JSON 安全 Java
什么是JWT?如何使用Spring Boot Security实现它?
什么是JWT?如何使用Spring Boot Security实现它?
1072 5
|
5月前
|
XML Java 数据格式
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
本文介绍了在使用Spring框架时,如何通过创建`applicationContext.xml`配置文件来管理对象。首先,在resources目录下新建XML配置文件,并通过IDEA自动生成部分配置。为完善配置,特别是添加AOP支持,可以通过IDEA的Live Templates功能自定义XML模板。具体步骤包括:连续按两次Shift搜索Live Templates,配置模板内容,输入特定前缀(如spring)并按Tab键即可快速生成完整的Spring配置文件。这样可以大大提高开发效率,减少重复工作。
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
|
5月前
|
Java Spring
【Spring配置】idea编码格式导致注解汉字无法保存
问题一:对于同一个项目,我们在使用idea的过程中,使用汉字注解完后,再打开该项目,汉字变成乱码问题二:本来a项目中,汉字注解调试好了,没有乱码了,但是创建出来的新的项目,写的注解又成乱码了。
|
10月前
|
安全 Java 数据安全/隐私保护
使用Spring Security实现细粒度的权限控制
使用Spring Security实现细粒度的权限控制
|
10月前
|
安全 Java 数据库
实现基于Spring Security的权限管理系统
实现基于Spring Security的权限管理系统
|
10月前
|
安全 Java 数据安全/隐私保护
解析Spring Security中的权限控制策略
解析Spring Security中的权限控制策略
|
9月前
|
JSON JavaScript 前端开发
Unexpected token u in JSON at position 0
这篇文章解释了JavaScript中"Unexpected token u in JSON at position 0"错误的常见原因,通常是由于尝试解析undefined变量导致的,并建议检查是否有变量在JSON.parse()执行时未赋值或值为undefined。
Unexpected token u in JSON at position 0
|
11月前
|
JSON 安全 Java
Spring Security 6.x 微信公众平台OAuth2授权实战
上一篇介绍了OAuth2协议的基本原理,以及Spring Security框架中自带的OAuth2客户端GitHub的实现细节,本篇以微信公众号网页授权登录为目的,介绍如何在原框架基础上定制开发OAuth2客户端。
372 4
Spring Security 6.x 微信公众平台OAuth2授权实战
|
11月前
|
存储 安全 Java
Spring Security 6.x OAuth2登录认证源码分析
上一篇介绍了Spring Security框架中身份认证的架构设计,本篇就OAuth2客户端登录认证的实现源码做一些分析。
470 2
Spring Security 6.x OAuth2登录认证源码分析
|
11月前
|
安全 Java API
Spring Security 6.x 图解身份认证的架构设计
【6月更文挑战第1天】本文主要介绍了Spring Security在身份认证方面的架构设计,以及主要业务流程,及核心代码的实现
172 1
Spring Security 6.x 图解身份认证的架构设计