oauth2授权码模式遇到的坑,1.走网关无法返回授权码 2.refresh_token新token丢失用户信息

主要有2个坑:

1.通过网关访问/oauth/authorize的时候,无法跳转到redirect_uri返回授权码
2.访问/oauth/token 刷新token的时候,新的token解析后用户信息丢失,用户信息变成了用户名

问题一

通过网关访问/oauth/authorize的时候,会把信息缓存到session中,跳转到登录页登录后,正常来说会从session中取出信息,然后跳转到redirect_uri,但是通过网关访问时,跳到的login登录页是授权服务的,点击登录也是直接访问的授权服务,并没有通过网关,所以需要跳转到login登录页的时候,把ip和端口都替换成网关的,具体代码如下


@TsfGatewayFilter
public class ResponseGlobalFilter extends AbstractTsfGlobalFilter {//    @Value("${cors.crossOriginPath}")private String crossOriginPath = "网关地址";@Overridepublic int getOrder() {//WRITE_RESPONSE_FILTER 之前执行return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1;}@Overridepublic boolean shouldFilter(ServerWebExchange exchange, GatewayFilterChain chain) {return true;}@Overridepublic Mono<Void> doFilter(ServerWebExchange exchange, GatewayFilterChain chain) {String path = exchange.getRequest().getPath().value();if (path.contains("/oauth/authorize") || path.contains("login")) {//构建响应包装类HttpResponseDecorator responseDecorator = new HttpResponseDecorator(exchange.getRequest(), exchange.getResponse(), crossOriginPath);return chain.filter(exchange.mutate().response(responseDecorator).build());}return chain.filter(exchange);}}
public class HttpResponseDecorator extends ServerHttpResponseDecorator {private String proxyUrl;private ServerHttpRequest request;/*** 构造函数** @param delegate*/public HttpResponseDecorator(ServerHttpRequest request, ServerHttpResponse delegate, String proxyUrl) {super(delegate);this.request = request;this.proxyUrl = proxyUrl;}@Overridepublic Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {HttpStatus status = this.getStatusCode();if (status.equals(HttpStatus.FOUND)) {String domain = "";if (StringUtils.isBlank(proxyUrl)) {domain = request.getURI().getScheme() + "://" + request.getURI().getAuthority() + "/oauth"; //这是授权服务的服务名} else {domain = proxyUrl + "/oauth";}String location = getHeaders().getFirst("Location");
//            for (int i = 0; i < 3; i++) {
//                location = location.substring(location.indexOf("/") + 1);
//            }String replaceLocation = location.replaceAll("^((ht|f)tps?):\\/\\/(\\d{1,3}.){3}\\d{1,3}(:\\d+)?", domain);if (location.contains("code=")) {
//                getHeaders().set("Location",location );} else {getHeaders().set("Location", replaceLocation);}}this.getStatusCode();return super.writeWith(body);}
}

我这是用的腾讯的tsf服务,AbstractTsfGlobalFilter 是腾讯包里的,普通微服务需要写gateway的拦截器,或者zuul的拦截器,gateway就是implements GlobalFilter, Ordered,这样每次访问/oauth/authorize的时候会先走这个过滤器,然后把重定向地址,也就是Location,替换成网关的ip+端口+授权服务名称,这样跳到login页面的时候,就会通过网关跳转,而不是授权服务,就可以获取授权码了。

问题二

在这里插入图片描述
就是这个原因,所以我们需要重写extractAuthentication方法


/*** 用户认证转化器* /根据 oauth/check_token 的结果转化用户信息** @author zhuowen* @since 2019/06/21*/
@Component
public class ZWUserAuthenticationConverter extends DefaultUserAuthenticationConverter {private static final String USER_ID = "user_id";private static final String DEPT_ID = "dept_id";private static final String ROLE_ID = "role_id";private static final String NAME = "name";private static final String TENANT_ID = "tenant_id";private static final String N_A = "N/A";/*** Extract information about the user to be used in an access token (i.e. for resource servers).** @param authentication an authentication representing a user* @return a map of key values representing the unique information about the user*/@Overridepublic Map<String, ?> convertUserAuthentication(Authentication authentication) {Map<String, Object> response = new LinkedHashMap<>();response.put(USERNAME, authentication.getName());if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities()));}return response;}/*** Inverse of {@link #convertUserAuthentication(Authentication)}. Extracts an Authentication from a map.** @param map a map of user information* @return an Authentication representing the user or null if there is none*/@Overridepublic Authentication extractAuthentication(Map<String, ?> map) {if (map.containsKey(USERNAME)) {Collection<? extends GrantedAuthority> authorities = getAuthorities(map);String username = (String) map.get(USERNAME);String name = (String) map.get(NAME);Integer userId = (Integer) map.get("userId");ZWUser zwUser = new ZWUser(userId.longValue(),username,name,"N/A",true,true,true,true,authorities);
//            String userStr =  (String)map.get("userInfo");
//            System.out.println("userObj=========="+userStr);
//            ObjectMapper objectMapper = new ObjectMapper();
//            ZWUser user = objectMapper.convertValue(userObj, ZWUser.class);
//            System.out.println("user=========="+user.toString());
//            System.out.println(jsonObject.toJSONString());
//            SysUser user = JSON.parseObject(jsonObject.toJSONString(), SysUser.class);return new UsernamePasswordAuthenticationToken(zwUser, N_A, authorities);}return null;}private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {Object authorities = map.get(AUTHORITIES);if (authorities instanceof String) {return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);}if (authorities instanceof Collection) {return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.collectionToCommaDelimitedString((Collection<?>) authorities));}throw new IllegalArgumentException("Authorities must be either a String or a Collection");}
}

重写完后,我们需要在token增强里配置一下

@Beanpublic JwtAccessTokenConverter accessTokenConverter() {JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter() {/*** 重写增强token的方法* 自定义返回相应的信息**/@Overridepublic OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {// 与登录时候放进去的UserDetail实现类一直查看link{SecurityConfiguration}ZWUser userInfo = (ZWUser) authentication.getUserAuthentication().getPrincipal();/* 自定义一些token属性 ***/final Map<String, Object> additionalInformation = new HashMap<>(18);String name = userInfo.getName();Long userId = userInfo.getUser_id();additionalInformation.put("name", name);additionalInformation.put("userId", userId);((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation);return super.enhance(accessToken, authentication);}};accessTokenConverter.setSigningKey(SIGNING_KEY);((DefaultAccessTokenConverter) accessTokenConverter.getAccessTokenConverter()).setUserTokenConverter(zwUserAuthenticationConverter);return accessTokenConverter;}

最后一行代码accessTokenConverter.getAccessTokenConverter()).setUserTokenConverter(zwUserAuthenticationConverter);把ZWUserAuthenticationConverter 注入到token增强的类里,刷新token后,用户信息就不会丢失了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/46628.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信开发者工具代码仓的管理以及错误:Push failed Error: invalid authentication scheme 的解决办法,微信小程序代码仓项目删除

文章目录 1、新建代码仓2、报错&#xff1a;Push failed Error: invalid authentication scheme 的解决办法3、代码仓项目的删除 1、新建代码仓 如果你的代码已经存在&#xff0c;单还是没有推送过&#xff0c;可先从以下位置进入到微信的GitHub仓库新建一个仓库。 新建一个…

微信授权登录返回code无效,签名不一致

在项目中&#xff0c;微信授权登录偶尔出现code无效&#xff0c;签名不一致的返回提示&#xff0c;但是就是偶然性 原因&#xff1a;没有调用wx.login()就获取用户的encryptedData、signature等信息 先看下官方的登录流程 很多开发者会把 login 和 getUserInfo 捆绑调用当成登…

Android集成网易云IM实现单聊和群聊

本人一直对即时通信感兴趣,但是我的日常工作与这个没有任何接触,所以一直没有时间去看,去研究,刚好最近有点空闲时间,便乘机去学习了一些皮毛 废话和客套话也不多说,先看效果 界面做的比较丑,大家不要在意哦,主要是实现功能 首页(登录网易云信IM) 单聊 群聊

从ChatGPT聊天服务上深挖Http、WebScoket和SSE推送技术的区别

简述 —— 三种方式进行通讯 回忆TCP/IP协议 其中&#xff0c;三次握手过程的步骤为&#xff1a; 客户端向服务端发送 SYN 报文&#xff0c;其中 seq 表示客户端的初始序列号。服务端收到 SYN 报文后&#xff0c;向客户端发送 SYNACK 报文&#xff0c;其中 ack 表示服务端收到…

Android腾讯云通信集成记录(快速实现聊天功能)

利用小假期的时间学习了一下怎么使用腾讯云通信&#xff0c;过程中的坑还是比较多&#xff0c;写篇博客记录一下集成过程方便自己以后查看。 先看下效果图&#xff1a; 首先需要去腾讯云通信的官网去登录&#xff0c;并且创建一个云通信应用。 免费的就好&#xff0c;腾讯云…

技术干货 | 网易云信大规模聊天室系统架构解析

导读&#xff1a;聊天室是一类非常重要的 IM 系统&#xff0c;不同于单聊和群聊&#xff0c;聊天室是一种大规模的实时消息分发系统。本文我们来详细介绍一下网易云信大规模聊天室系统的具体架构以及实践应用案例。 文&#xff5c;曹佳俊 网易云信资深服务端开发工程师 聊天室有…

2022倒带-NutUI

前言 时光飞逝&#xff0c;流年似水&#xff0c;让我们倒带 2022&#xff0c;回首这跌宕起伏一年走过的 “升级之路”。 NutUI 表现如何&#xff1f; 成绩单等着您打分&#xff01; 2022 是 NutUI 在技术长廊中探索和成长的第四个年头&#xff0c;悄然度过了自己的“孩提“时…

chatgpt赋能python:Python量化开发:实现金融市场的策略化投资

Python量化开发&#xff1a;实现金融市场的策略化投资 随着金融市场竞争的日益激烈&#xff0c;传统的以人工分析及定量研究为主的投资方法已经无法满足投资者的需求。因此&#xff0c;数字化投资逐渐成为趋势&#xff0c;采用量化投资来实现金融市场的策略化投资已经成为了投…

英语基础:四级431、六级没过,考研英语78分经验分享 (23考研)

前言 博主备考时的英语基础&#xff1a;英语四级431分, 六级没过 研究生英语二分数&#xff1a;78分 ps&#xff1a;也许这个分数段不是一些大佬的目标分数 (80)&#xff0c;本篇文章的目的只是帮助一些英语基础差的同学&#xff0c;提供一些备考经验。 一、基础阶段 时间&…

考研复试_英语面试_必备的30个问题

前言&#xff1a; 本人英语口语处于那种的“哑巴式”&#xff0c;没有准备就根本不知道扯啥。于是整理了一些出现频率最高的英语问题&#xff08;回答对我而言两三句简单句就撑死了&#xff0c;因没有参考价值大家就还是自己准备回答&#xff09;&#xff0c;以防到时候陷入迷之…

国外问卷调查有哪几种类型?

大家好&#xff0c;我是小飞匠&#xff0c;今天来聊聊国外问卷调查分为哪几种&#xff1f;新手适合做哪种&#xff1f;国外问卷调查项目最近一直很火&#xff0c;咨询的人也比较多。因为国外问卷调查其实分为很多种类。通过不同的展现方式、付款方式&#xff0c;我们称为不同的…

什么是海外调查问卷?都有哪些形式

国内外有很多正规的公司都是做这个行业的。为什么会有这么多公司在做这个行业&#xff1f;主要是由于市场上问卷调查需求较多决定的&#xff0c;很多商家在进行新产品研发前的需求以及产品销售后的一些满意度征集时&#xff0c;往往会通过这种问卷调查公司收集特定人群的意见与…

国外问卷调查好做吗?为大家分享干货!

随着5G的出现&#xff0c;2021可谓是真正的进入到了互联网时代。互联网时代的出现更大的为人们提供了更多的机会&#xff0c;让人们的工作以及生活都得到了更大的便利。也使人们的创业的机会变得更多了起来。 在互联网的背景下&#xff0c;足不出户的进行互联网的创业的人们多了…

开源的问卷调查系统

一、项目简介 今天推荐一款基于 JAVA WEB 的开源问卷表单系统。 二、实现功能 支持创建问卷 支持设计问卷 支持基础题型 支持收集卷子 支持默认统计 支持原始答卷 三、技术选型 后台开发&#xff1a;Java、SpringBoot【企业版】&#xff0c;Struts2【开源版】 前端开…

海外调查问卷中的站点查

国内外很多正规公司都在从事这个行业。为什么有这么多公司在做这个行业&#xff1f;主要是由于市场上对问卷调查的需求量很大。很多商家在收集新产品研发前的需求和产品销售后的一些满意度时&#xff0c;往往会通过这种问卷调查公司来收集特定人群的意见和想法。这些问卷调查公…

微信端问卷调查

上周&#xff0c;股份公司突然需要问卷调查功能&#xff0c;要的很着急。和一同事用了大约两天时间&#xff0c;将该功能完成。 项目情况是&#xff1a;要求在PC、微信端可以填写内容&#xff1b;微信端根据二维码打开问卷页面。 UI框架&#xff1a; bootstrap 效果如下&…

微信小程序-调查问卷

调查问卷 搭建本地服务器新建小程序注意 搭建本地服务器 使用node.js&#xff08;要安装node.js&#xff09;搭建本地HTTP服务器&#xff0c;在小程序所在目录创建web目录 &#xff0c;并在web目录下打开CMD&#xff0c;初始化项目 npm init -y然后安装express框架 npm inst…

在当前就业形势下,如何提高应届生在职场中的竞争力,让ChatGPT帮你解答

在当前就业形势下&#xff0c;应届生要提高自身的竞争力&#xff0c;可以从以下几个方面入手&#xff1a; 学习技能&#xff1a;不断学习提升自身专业和技能水平&#xff0c;获取行业认证证书&#xff0c;参加培训课程。 实习和项目实践&#xff1a;通过实践课程&#xff0c;公…

泰裤辣!ChatGPT帮你制定个人发展计划,助力你实现职场腾飞……

作为一名职场人&#xff0c;你是否曾经感到自己的职业生涯缺乏方向和规划&#xff1f; 是否曾经为了应对工作中的挑战而感到力不从心&#xff1f; 如果你的答案是肯定的&#xff0c;那么认真制定自己的个人发展计划&#xff0c;为自己的职业生涯打下坚实的基础就是你必须要做…

ChatGPT-看一看你还有多久失业

需求&#xff1a;将下列表格中的数据导入mysql数据库并且可以将mysql数据库上的数据导出到excel&#xff0c;如果让你做需要多久时间 第1次询问ChatGPT&#xff1a;一个excel内部有多个sheet&#xff0c;每个sheet的表头都是章节号、测试项、测试子项、用例名称、用例表示、测试…