微服务中的鉴权怎么做?

大家好,我是苍何呀。

现在出去找工作,简历上不写上微服务的技术,仿佛自己跟不上时代了,面试官更是喜欢盯着微服务项目来提问。

但其实虽说微服务是主流,随着云原生架构的发展,微服务也是趋势,但很多公司特别是中小公司的中小业务,根本用不上微服务,你说一个简单的内部管理系统,非得上微服务,有点为了微服务而微服务的感觉了😂。

为了大家能有个可放在简历上「吹逼」的微服务项目,我们在单体版本的基础上又增加了微服务版本,并在接下来的一段时间内,持续分享单体应用微服务化的经验。

今天分享的是,在微服务架构中,如何做好鉴权

微服务架构

微服务简而言之就是单个独立的服务,可以独立开发部署维护。而微服务架构是指的多个微服务聚合起来的系统,这个系统涵盖多个微服务,服务与服务之间的通讯、服务监控、服务熔断降级、服务注册、分布式配置、分布式事务等各种解决方案聚合而成的架构体系。

微服务架构有如下优点:

  • 提高开发效率:团队可以并行开发不同的微服务,减少了开发和发布的时间。
  • 增强可维护性:小而专注的代码库更易于理解和维护,降低了技术债务。
  • 灵活的技术选型:不同的微服务可以根据需要使用最合适的技术栈,而无需在整个系统中保持一致。
  • 持续交付和部署:微服务架构支持持续集成和持续交付(CI/CD),使得新功能和修复能够快速上线。
  • 更好的故障隔离:一个微服务的故障不会影响其他微服务的正常运行,从而提高系统的可靠性。
  • 按需扩展:可以独立地扩展需要高负载处理的微服务,优化资源使用和成本。

鉴权基础

鉴权顾名思义就是需要进行权限认证和授权控制,你写好的系统不希望谁都可以访问吧?你写的牛逼的接口也不希望哪个人都可以来蹭一下访问吧?那就需要认证和授权。

专业做这块的有 Spring Security 和 Shiro 这两哥们,当然还有一些其他的框架也是可以做的,但无非核心都在做两件事:

  • 认证
  • 授权

认证,说白了就是登录,传统 web 登录是通过用户名和密码用 Cookie+Session 的方式,这种依赖于服务器本地内存,微服务中,显然不合适。

常见的鉴权方式有以下几种:

用户名和密码

是最传统和常见的鉴权方式,用户通过输入预先设置的用户名和密码进行登录,需要注意密码的存储和传输安全,如使用加盐哈希存储和HTTPS 传输。

多因素认证(MFA)

这是一种增强安全性的方法,通过要求多种不同类型的验证因素来确认用户身份,常见的因素包括:知识因子(密码)、拥有因子(手机验证码)、生物因子(指纹、面部识别)。

OAuth(开放授权)

这是一种一种授权协议,允许第三方应用以有限的权限访问用户资源,而无需暴露用户的凭证。常用于社交登录和API访问控制。

JWT(JSON Web Token)

一种基于 JSON 的开放标准(RFC 7519),用于在各方之间传递声明。JWT包含用户信息和签名,可用于鉴权和授权。我们这次也是采用的这种方式进行的鉴权。

微服务中鉴权

微服务架构中,通常有多个独立服务组成,这些服务可能部署在不同的服务器或数据中心, 鉴权机制需要在分布式环境中有效运作,确保各个服务能安全通信,且需要有统一认证中心,我们先来看一张微服务架构图:

微服务架构图(来源于网络)

通常会有一个单独的微服务来做认证,也就是认证服务,对于微服务系统而言,请求一般分为 2 种:

  • 通过 API 网关的请求
  • 微服务内部请求

对于这两种请求,都需要进行鉴权,但方式是不一样的,

微服务中如何做认证?

微服务中的认证最多的方式是通过 JWT 令牌的方式,但 JWT 实际上是无状态的,也就是没法确定登录的用户啥时候过期,所以大部分情况下会需要结合 Redis 来设置状态

将生成的 JWT 字符串在 Redis 上也保存一份,并设置过期时间,判断用户是否登录时,需要先去 Redis 上查看 JWT 字符串是否存在,存在的话再对 JWT 字符串做解析操作,如果能成功解析,就没问题,如果不能成功解析,就说明令牌不合法。

这是一个简单的流程图:

我的做法是,在认证服务中,检查用户名密码的正确性,正确的话就生成 JWT 字符串,同时再把数据存入到 Redis 上,然后返回 token 信息。登录请求先经过网关,网关再转发到认证服务,下面是一个具体的流程:

微服务中如何做授权?

授权是请求到达每个微服务后,需要对请求进行权限判定,看是否有权限访问,通常不会放在网关中来做。还是在微服务中自己来做。

我们说过,在微服务架构中,请求主要分为 2 种,外部请求和内部请求,下面是不同的授权思路。

外部请求

我的做法是:请求到达网关后,通过微服务的自定义请求头拦截器(可以放在公共包下面,每个服务都可以引用),配合自定义注解和 AOP,拦截请求头,获取用户和权限信息,然后进行比对,有权限则放行,没权限则抛出异常。

内部请求

对于内部的请求来说,正常是不需要鉴权的,内部请求可以直接处理。问题是如果使用了 OpenFeign,数据都是通过接口暴露出去的,不鉴权的话,又会担心从外部来的请求调用这个接口,对于这个问题,我们也可以自定义注解+AOP,然后在内部请求调用的时候,额外加一个头字段加以区分。

我采用的是自定义内部请求注解,然后 AOP 控制拦截。

/**
 * 内部认证注解
 * 
 * @author canghe
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InnerAuth
{
    /**
     * 是否校验用户信息
     */
    boolean isUser() default false;
}

AOP 的切面控制请求是否携带有内部请求的标识:

/**
 * 内部服务调用验证处理
 *
 * @author canghe
 */
@Aspect
@Component
public class InnerAuthAspect implements Ordered {
    @Around("@annotation(innerAuth)")
    public Object innerAround(ProceedingJoinPoint point, InnerAuth innerAuth) throws Throwable {
        String source = ServletUtils.getRequest().getHeader(SecurityConstants.FROM_SOURCE);
        // 内部请求验证
        if (!StringUtils.equals(SecurityConstants.INNER, source)) {
            throw new InnerAuthException("没有内部访问权限,不允许访问");
        }

        String userid = ServletUtils.getRequest().getHeader(SecurityConstants.DETAILS_USER_ID);
        String username = ServletUtils.getRequest().getHeader(SecurityConstants.DETAILS_USERNAME);
        // 用户信息验证
        if (innerAuth.isUser() && (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username))) {
            throw new InnerAuthException("没有设置用户信息,不允许访问 ");
        }
        return point.proceed();
    }

因为使用的是 OpenFeign,请求通过 OpenFeign 调用也需要鉴权,所以我实现了 feign.RequestInterceptor 接口来定义一个 OpenFeign 的请求拦截器,在拦截器中,统一为 OpenFeign 请求设置请求头信息。

/**
 * feign 请求拦截器
 *
 * @author canghe
 */
@Component
public class FeignRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        HttpServletRequest httpServletRequest = ServletUtils.getRequest();
        if (StringUtils.isNotNull(httpServletRequest)) {
            Map<String, String> headers = ServletUtils.getHeaders(httpServletRequest);
            // 传递用户信息请求头,防止丢失
            String userId = headers.get(SecurityConstants.DETAILS_USER_ID);
            if (StringUtils.isNotEmpty(userId)) {
                requestTemplate.header(SecurityConstants.DETAILS_USER_ID, userId);
            }
            String userKey = headers.get(SecurityConstants.USER_KEY);
            if (StringUtils.isNotEmpty(userKey)) {
                requestTemplate.header(SecurityConstants.USER_KEY, userKey);
            }
            String userName = headers.get(SecurityConstants.DETAILS_USERNAME);
            if (StringUtils.isNotEmpty(userName)) {
                requestTemplate.header(SecurityConstants.DETAILS_USERNAME, userName);
            }
            String authentication = headers.get(SecurityConstants.AUTHORIZATION_HEADER);
            if (StringUtils.isNotEmpty(authentication)) {
                requestTemplate.header(SecurityConstants.AUTHORIZATION_HEADER, authentication);
            }

            // 配置客户端IP
            requestTemplate.header("X-Forwarded-For", IpUtils.getIpAddr());
        }
    }

总结

微服务中的鉴权是很关键的,也是系统安全和完整性的最为核心的一步,微服务架构通过其独立性、模块化和灵活性,使得开发、部署和维护大型复杂系统变得更加高效和可控。然而,这种分布式系统带来了新的安全挑战,需要在系统设计中充分考虑和实现有效的鉴权机制。

以上是今天的分享,遗忘对你有帮助!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DOS学习-目录与文件应用操作经典案例-dir

欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一.前言 二.使用 三.练习 一.前言 dir是"directory"&#xff08;目录&#xff09;的缩写&#xff0c;它主要用于展示某个磁盘上的全部或特定文件目录。在DOS操作系统中&#…

ES6中数组新增了哪些扩展?

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;JavaScript篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:ES6中数组新增了哪些扩展&#xff1f; 目录 一、扩展运算符的应用 二、构造函数新…

Web3与物联网:构建智能连接的数字世界

引言 随着互联网的不断发展&#xff0c;物联网&#xff08;Internet of Things, IoT&#xff09;作为一种新兴的信息技术&#xff0c;正在逐渐渗透到我们的生活和工作中。而随着Web3的兴起&#xff0c;物联网将迎来新的发展机遇。本文将探讨Web3与物联网的结合&#xff0c;如何…

全面解析防静电措施:保障工业安全,预防静电危害

静电是一种常见的物理现象&#xff0c;由于电荷的不平衡而产生。在特定的环境中&#xff0c;静电可能会带来危害&#xff0c;如损坏电子设备、引起火灾等。因此&#xff0c;采取适当的防静电措施是非常重要的。以下是一些常见的防静电方法&#xff1a; 增加环境湿度&#xff1a…

崆峒酥饼:佳节馈赠的美味之选

崆峒酥饼&#xff1a;佳节馈赠的美味之选 在即将到来的端午节&#xff0c;人们开始忙碌地准备着走亲访友的礼物。而崆峒酥饼&#xff0c;作为一种传统的美食&#xff0c;不仅是节日里的美味享受&#xff0c;更是传递情谊的佳品。 崆峒酥饼&#xff0c;以其酥脆的口感和独特的风…

使用httpx异步获取高校招生信息:一步到位的代理配置教程

概述 随着2024年中国高考的临近&#xff0c;考生和家长对高校招生信息的需求日益增加。了解各高校的专业、课程设置和录取标准对于高考志愿填报至关重要。通过爬虫技术&#xff0c;可以高效地从各高校官网获取这些关键信息。然而&#xff0c;面对大量的请求和反爬机制的挑战&a…

【Python】语句与众所周知【自我维护版】

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 本篇博客是在之前的基础上进行的维护 目录 条…

HP6V18、HP6V65电比例功率控制泵放大器

HP6V18、HP6V65电比例压力负控制&#xff0c;电比例功率控制泵通过由BEUEC比例放大器控制改变阀的输入电流&#xff0c;将泵设置为一定压力。改变负载压力&#xff0c;为使调订压力恒定&#xff0c;泵摆角会增大或减小&#xff0c;从而改变流量。因此泵只能输出执行器可以接受的…

ubuntu下gcc编译器的安装

.gcc编译器的安装 一般linux下是覆盖含有的&#xff0c;如果没有执行更新命令 sudo apt update gcc安装成功&#xff0c;可以检查一下版本 可以看出我的gcc是9.4.0版本的

地表最强ChatGPT爆了!我来告诉你,它都有什么用

OpenAI刚刚发布了全新的 "GPT-4o"&#xff0c;它不仅可以通过语音、视觉和文本进行推理&#xff0c;还在速度和价格上有了巨大的突破。它的速度提高了2倍&#xff0c;价格却降低了50%&#xff0c;而且生成速率比GPT-4 Turbo高出5倍。最令人惊喜的是&#xff0c;它将对…

Verilog基础语法——条件语句if-else与case

Verilog基础语法——条件语句case、if-else 写在前面一、if-else语句二、case语句2.1 case语句2.2 casez语句2.3 casex语句 写在后面 写在前面 在Verilog语法中&#xff0c;常用的条件语句有if-else语句和case语句&#xff0c;用于判断条件是否为真&#xff0c;并执行判断条件后…

【NLP】文本分类

n-gram 的局限性 n-gram 只能对于填空这样的通顺性问题做出推测&#xff0c;但是没有办法完全解决句子的语义问题&#xff0c;从而无法实现文本的分类 文本的分类&#xff0c;就是将文本在语义的理解下划分到特定的主题下 手工规则 如一些垃圾过滤系统&#xff0c;需要人工制…

PHP开发中的不安全反序列化

序列化是开发语言中将某个对象转换为一串字节流的过程&#xff0c;转换后的字节流可以方便存储在数据库中&#xff0c;也可以方便在网络中进行传输。而反序列化则是将数据库取出的字节流或从网络上接收到的字节流反向转换为对象的过程。概念虽如此&#xff0c;但不同的开发语言…

【JavaEE 初阶(七)】网络原理 TCP与UDP协议

❣博主主页: 33的博客❣ ▶️文章专栏分类:JavaEE◀️ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;关注我带你了解更多网络知识 目录 1.前言2.应用层2.1xml2.2json 3.传输层3.1UDP协议3.2TCP协议3.2.1确认响应3.2.2超时重…

【c++】map和set的封装

1.红黑树源码 我们使用上节课的红黑树源码来封装map和set. 因为map存的是&#xff08;key,value&#xff09;,set存的是&#xff08;key&#xff09;,为了我们set和map使用同一个类模板&#xff08;红黑树&#xff09;&#xff0c;所以我们先要修改红黑树结点中存的数据类型&a…

苹果永久版安装PD虚拟机:Parallels Desktop 19 一键激活版

Parallels Desktop 19是一款功能强大的虚拟机软件&#xff0c;专为Mac用户设计&#xff0c;允许用户在同一台Mac电脑上同时运行Windows、Linux等多个操作系统&#xff0c;而无需额外的硬件设备。 下载地址&#xff1a;https://www.macz.com/mac/9581.html?idOTI2NjQ5Jl8mMjcuM…

Java环境搭建(二)Notepad++和IDEA的下载

Notepad&#xff08;不推荐使用&#xff09; 高级记事本 下载地址 Notepad (juxinwk1.cn) 下载安装后一直下一步就可以了 注&#xff1a;改一下路径还有建立快捷方式&#xff08;自己选择&#xff09; IDEA 集成环境 下载地址 IntelliJ IDEA – the Leading Java and Kotl…

展馆展厅设计施工流程

1、需求分析和确定&#xff1a; 与客户沟通&#xff0c;了解客户需求&#xff0c;对展馆展厅的用途、面积、功能、展品特点等进行分析&#xff0c;并确定设计方案。 2、方案设计 根据需求确定设计方案&#xff0c;包括平面布局、展品陈列、展示方式、照明等。设计师需要提供设计…

防静电劳保鞋:工业安全中的隐形守护者

在工业生产环境中&#xff0c;静电问题常常被忽视&#xff0c;然而它却是许多安全事故的潜在隐患。静电不仅可能损坏敏感的电子设备&#xff0c;更在易燃易爆环境中构成严重威胁。因此&#xff0c;防静电措施在工业安全中显得尤为重要。在众多防静电措施中&#xff0c;防静电劳…

618有哪些好物值得推荐?收下这份618必买好物清单

随着618购物节的脚步越来越近&#xff0c;你是不是已经开始摩拳擦掌&#xff0c;准备大肆采购一番了&#xff1f;在这个购物狂欢节里&#xff0c;要说哪些宝贝最值得你入手&#xff0c;那一定少不了数码家电类&#xff01;今天就给大家整理了一些我往期自用过还不错的数码家电好…