认证鉴权与API权限控制在微服务架构中的设计与实现(一)

2023-11-04

引言: 本文系《认证鉴权与API权限控制在微服务架构中的设计与实现》系列的第一篇,本系列预计四篇文章讲解微服务下的认证鉴权与API权限控制的实现。

1. 背景

最近在做权限相关服务的开发,在系统微服务化后,原有的单体应用是基于Session的安全权限方式,不能满足现有的微服务架构的认证与鉴权需求。微服务架构下,一个应用会被拆分成若干个微应用,每个微应用都需要对访问进行鉴权,每个微应用都需要明确当前访问用户以及其权限。尤其当访问来源不只是浏览器,还包括其他服务的调用时,单体应用架构下的鉴权方式就不是特别合适了。在微服务架构下,要考虑外部应用接入的场景、用户–服务的鉴权、服务–服务的鉴权等多种鉴权场景。

比如用户A访问User Service,A如果未登录,则首先需要登录,请求获取授权token。获取token之后,A将携带着token去请求访问某个文件,这样就需要对A的身份进行校验,并且A可以访问该文件。

为了适应架构的变化、需求的变化,auth权限模块被单独出来作为一个基础的微服务系统,为其他业务service提供服务。

2. 系统架构的变更

单体应用架构到分布式架构,简化的权限部分变化如下面两图所示。

(1)单体应用简化版架构图:

(2)分布式应用简化版架构图:

分布式架构,特别是微服务架构的优点是可以清晰的划分出业务逻辑来,让每个微服务承担职责单一的功能,毕竟越简单的东西越稳定。

但是,微服务也带来了很多的问题。比如完成一个业务操作,需要跨很多个微服务的调用,那么如何用权限系统去控制用户对不同微服务的调用,对我们来说是个挑战。当业务微服务的调用接入权限系统后,不能拖累它们的吞吐量,当权限系统出现问题后,不能阻塞它们的业务调用进度,当然更不能改变业务逻辑。新的业务微服务快速接入权限系统相对容易把控,那么对于公司已有的微服务,如何能不改动它们的架构方式的前提下,快速接入,对我们来说,也是一大挑战。

3. 技术方案

这主要包括两方面需求:其一是认证与鉴权,对于请求的用户身份的授权以及合法性鉴权;其二是API级别的操作权限控制,这个在第一点之后,当鉴定完用户身份合法之后,对于该用户的某个具体请求是否具有该操作执行权限进行校验。

3.1 认证与鉴权

对于第一个需求,笔者调查了一些实现方案:

  1. 分布式Session方案
    分布式会话方案原理主要是将关于用户认证的信息存储在共享存储中,且通常由用户会话作为 key 来实现的简单分布式哈希映射。当用户访问微服务时,用户数据可以从共享存储中获取。在某些场景下,这种方案很不错,用户登录状态是不透明的。同时也是一个高可用且可扩展的解决方案。这种方案的缺点在于共享存储需要一定保护机制,因此需要通过安全链接来访问,这时解决方案的实现就通常具有相当高的复杂性了。

  2. 基于OAuth2 Token方案
    随着 Restful API、微服务的兴起,基于Token的认证现在已经越来越普遍。Token和Session ID 不同,并非只是一个 key。Token 一般会包含用户的相关信息,通过验证 Token 就可以完成身份校验。用户输入登录信息,发送到身份认证服务进行认证。AuthorizationServer验证登录信息是否正确,返回用户基础信息、权限范围、有效时间等信息,客户端存储接口。用户将 Token 放在 HTTP 请求头中,发起相关 API 调用。被调用的微服务,验证Token。ResourceServer返回相关资源和数据。

这边选用了第二种方案,基于OAuth2 Token认证的好处如下:

  • 服务端无状态:Token 机制在服务端不需要存储 session 信息,因为 Token 自身包含了所有用户的相关信息。
  • 性能较好,因为在验证 Token 时不用再去访问数据库或者远程服务进行权限校验,自然可以提升不少性能。
  • 现在很多应用都是同时面向移动端和web端,OAuth2 Token机制可以支持移动设备。
  • OAuth2与Spring Security结合使用,有提供很多开箱即用的功能,大多特性都可以通过配置灵活的变更。
  • 最后一点,也很重要,Spring Security OAuth2的文档写得较为详细。

oauth2根据使用场景不同,分成了4种模式:

  • 授权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)

对于上述oauth2四种模式不熟的同学,可以自行百度oauth2,阮一峰的文章有解释。常使用的是password模式和client模式。

3.2 操作权限控制

对于第二个需求,笔者主要看了Spring Security和Shiro。

  1. Shiro
    Shiro是一个强大而灵活的开源安全框架,能够非常清晰的处理认证、授权、管理会话以及密码加密。Shiro很容易入手,上手快控制粒度可糙可细。自由度高,Shiro既能配合Spring使用也可以单独使用。

  2. Spring Security
    Spring社区生态很强大。除了不能脱离Spring,Spring Security具有Shiro所有的功能。而且Spring Security对Oauth、OpenID也有支持,Shiro则需要自己手动实现。Spring Security的权限细粒度更高。但是Spring Security太过复杂。

看了下网上的评论,貌似一边倒向Shiro。大部分人提出的Spring Security问题就是比较复杂难懂,文档太长。不管是Shiro还是Spring Security,其实现都是基于过滤器,对于自定义实现过滤器,我想对于很多开发者并不是很难,但是这需要团队花费时间与封装可用的jar包出来,对于后期维护和升级,以及功能的扩展。很多中小型公司并不一定具有这样的时间和人力投入这件事。笔者综合评估了下复杂性与所要实现的权限需求,以及上一个需求调研的结果,既然Spring Security功能足够强大且稳定,最终选择了Spring Security

4. 系统架构

4.1 组件

Auth系统的最终使用组件如下:

4.2 步骤

主要步骤为:

  • 配置资源服务器和认证服务器
  • 配置Spring Security

上述步骤比较笼统,对于前面小节提到的需求,属于Auth系统的主要内容,笔者后面会另写文章对应讲解。

4.3 endpoint

提供的endpoint:

4.4 maven依赖

主要的jar包,pom.xml文件如下:

4.5 AuthorizationServer配置文件

AuthorizationServer配置主要是覆写如下的三个方法,分别针对endpoints、clients、security配置。

 
  1. @Override
  2. public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
  3. security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
  4. }
  5. @Override
  6. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
  7. //配置客户端认证
  8. clients.withClientDetails(clientDetailsService(dataSource));
  9. }
  10. @Override
  11. public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
  12. //配置token的数据源、自定义的tokenServices等信息
  13. endpoints.authenticationManager(authenticationManager)
  14. .tokenStore(tokenStore(dataSource))
  15. .tokenServices(authorizationServerTokenServices())
  16. .accessTokenConverter(accessTokenConverter())
  17. .exceptionTranslator(webResponseExceptionTranslator);
  18. }

4.6 ResourceServer配置

资源服务器的配置,覆写了默认的配置。为了支持logout,这边自定义了一个CustomLogoutHandler并且将logoutSuccessHandler指定为返回http状态的HttpStatusReturningLogoutSuccessHandler

 
  1. 1 @Override
  2. 2 public void configure(HttpSecurity http) throws Exception {
  3. 3 http.csrf().disable()
  4. 4 .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  5. 5 .and()
  6. 6 .requestMatchers().antMatchers("/**")
  7. 7 .and().authorizeRequests()
  8. 8 .antMatchers("/**").permitAll()
  9. 9 .anyRequest().authenticated()
  10. 10 .and().logout()
  11. 11 .logoutUrl("/logout")
  12. 12 .clearAuthentication(true)
  13. 13 .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
  14. 14 .addLogoutHandler(customLogoutHandler());

4.7 执行endpoint

1. 首先执行获取授权的endpoint。

上述构造了一个post请求,具体请求写得很详细。username和password是客户端提供给服务器进行校验用户身份信息。header里面的Authorization是存放的clientId和clientSecret经过编码的字符串。
返回结果如下:

 
  1. {
  2. "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsImV4cCI6MTUwODQ0Nzc1NiwidXNlcl9uYW1lIjoia2VldHMiLCJqdGkiOiJiYWQ3MmIxOS1kOWYzLTQ5MDItYWZmYS0wNDMwZTdkYjc5ZWQiLCJjbGllbnRfaWQiOiJmcm9udGVuZCIsInNjb3BlIjpbImFsbCJdfQ.5ZNVN8TLavgpWy8KZQKArcbj7ItJLLaY1zBRaAgMjdo",
  3. "token_type": "bearer",
  4. "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsInVzZXJfbmFtZSI6ImtlZXRzIiwic2NvcGUiOlsiYWxsIl0sImF0aSI6ImJhZDcyYjE5LWQ5ZjMtNDkwMi1hZmZhLTA0MzBlN2RiNzllZCIsImV4cCI6MTUxMDk5NjU1NiwianRpIjoiYWE0MWY1MjctODE3YS00N2UyLWFhOTgtZjNlMDZmNmY0NTZlIiwiY2xpZW50X2lkIjoiZnJvbnRlbmQifQ.mICT1-lxOAqOU9M-Ud7wZBb4tTux6OQWouQJ2nn1DeE",
  5. "expires_in": 43195,
  6. "scope": "all",
  7. "X-KEETS-UserId": "d6448c24-3c4c-4b80-8372-c2d61868f8c6",
  8. "jti": "bad72b19-d9f3-4902-affa-0430e7db79ed",
  9. "X-KEETS-ClientId": "frontend"
  10. }

可以看到在用户名密码通过校验后,客户端收到了授权服务器的response,主要包括access token、refresh token。并且表明token的类型为bearer,过期时间expires_in。笔者在jwt token中加入了自定义的info为UserId和ClientId。

2. 鉴权的endpoint

 
  1. 1 method: post
  2. 2 url: http://localhost:12000/oauth/check_token
  3. 3 header:
  4. 4 {
  5. 5 Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=,
  6. 6 Content-Type: application/x-www-form-urlencoded
  7. 7 }
  8. 8 body:
  9. 9 {
  10. 10 token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsImV4cCI6MTUwODQ0Nzc1NiwidXNlcl9uYW1lIjoia2VldHMiLCJqdGkiOiJiYWQ3MmIxOS1kOWYzLTQ5MDItYWZmYS0wNDMwZTdkYjc5ZWQiLCJjbGllbnRfaWQiOiJmcm9udGVuZCIsInNjb3BlIjpbImFsbCJdfQ.5ZNVN8TLavgpWy8KZQKArcbj7ItJLLaY1zBRaAgMjdo
  11. 11 }

上面即为check_token请求的详细信息。需要注意的是,笔者将刚刚授权的token放在了body里面,这边可以有多种方法,此处不扩展。

 
  1. {
  2. "X-KEETS-UserId": "d6448c24-3c4c-4b80-8372-c2d61868f8c6",
  3. "user_name": "keets",
  4. "scope": [
  5. "all"
  6. ],
  7. "active": true,
  8. "exp": 1508447756,
  9. "X-KEETS-ClientId": "frontend",
  10. "jti": "bad72b19-d9f3-4902-affa-0430e7db79ed",
  11. "client_id": "frontend"
  12. }

校验token合法后,返回的response如上所示。在response中也是展示了相应的token中的基本信息。

3.刷新token

由于token的时效一般不会很长,而refresh token一般周期会很长,为了不影响用户的体验,可以使用refresh token去动态的刷新token。

 
  1. method: post
  2. url: http://localhost:12000/oauth/token?grant_type=refresh_token&refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsInVzZXJfbmFtZSI6ImtlZXRzIiwic2NvcGUiOlsiYWxsIl0sImF0aSI6ImJhZDcyYjE5LWQ5ZjMtNDkwMi1hZmZhLTA0MzBlN2RiNzllZCIsImV4cCI6MTUxMDk5NjU1NiwianRpIjoiYWE0MWY1MjctODE3YS00N2UyLWFhOTgtZjNlMDZmNmY0NTZlIiwiY2xpZW50X2lkIjoiZnJvbnRlbmQifQ.mICT1-lxOAqOU9M-Ud7wZBb4tTux6OQWouQJ2nn1DeE
  3. header:
  4. {
  5. Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=
  6. }

其response和/oauth/token得到正常的相应是一样的,此处不再列出。

4.注销token

 
  1. method: get
  2. url: http://localhost:9000/logout
  3. header:
  4. {
  5. Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=
  6. }

注销成功则会返回200,注销端点主要是将token和SecurityContextHolder进行清空。

5. 总结

本文是《认证鉴权与API权限控制在微服务架构中的设计与实现》系列文章的总述,从遇到的问题着手,介绍了项目的背景。通过调研现有的技术,并结合当前项目的实际,确定了技术选型。最后对于系统的最终的实现进行展示。后面将从实现的细节,讲解本系统的实现。敬请期待后续文章。


参考

  1. 理解OAuth 2.0
  2. 微服务API级权限的技术架构
  3. 微服务架构下的安全认证与鉴权

原文链接:认证鉴权与API权限控制在微服务架构中的设计与实现(一) | Aoho's Blog


♥ 作者:明志健致远
♠ 出处:明志健致远 - 博客园
♦ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
♣ 本博客大多为学习笔记或读书笔记,本文如对您有帮助,还请多推荐下此文,如有错误欢迎指正,相互学习,共同进步。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

认证鉴权与API权限控制在微服务架构中的设计与实现(一) 的相关文章

  • Java new Date() 打印

    刚刚学习 Java 我知道这可能听起来很愚蠢 但我不得不问 System out print new Date 我知道参数中的任何内容都会转换为字符串 最终值是 new Date 返回对 Date 对象的引用 那么它是如何打印这个的呢 Mo
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • 给定两个 SSH2 密钥,我如何检查它们是否属于 Java 中的同一密钥对?

    我正在尝试找到一种方法来验证两个 SSH2 密钥 一个私有密钥和一个公共密钥 是否属于同一密钥对 我用过JSch http www jcraft com jsch 用于加载和解析私钥 更新 可以显示如何从私钥 SSH2 RSA 重新生成公钥
  • 使用 Android 发送 HTTP Post 请求

    我一直在尝试从 SO 和其他网站上的大量示例中学习 但我无法弄清楚为什么我编写的示例不起作用 我正在构建一个小型概念验证应用程序 它可以识别语音并将其 文本 作为 POST 请求发送到 node js 服务器 我已确认语音识别有效 并且服务
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • 多个 Maven 配置文件激活多个 Spring 配置文件

    我想在 Maven 中构建一个环境 在其中我想根据哪些 Maven 配置文件处于活动状态来累积激活多个 spring 配置文件 目前我的 pom xml 的相关部分如下所示
  • 控制Android的前置LED灯

    我试图在用户按下某个按钮时在前面的 LED 上实现 1 秒红色闪烁 但我很难找到有关如何访问和使用前置 LED 的文档 教程甚至代码示例 我的意思是位于 自拍 相机和触摸屏附近的 LED 我已经看到了使用手电筒和相机类 已弃用 的示例 但我
  • 路径中 File.separator 和斜杠之间的区别

    使用有什么区别File separator和一个正常的 在 Java 路径字符串中 与双反斜杠相反 平台独立性似乎不是原因 因为两个版本都可以在 Windows 和 Unix 下运行 public class SlashTest Test
  • 禁止的软件包名称:java

    我尝试从数据库名称为 jaane 用户名 Hello 和密码 hello 获取数据 错误 java lang SecurityException Prohibited package name java at java lang Class
  • 为什么HashMap不能保证map的顺序随着时间的推移保持不变

    我在这里阅读有关 Hashmap 和 Hashtable 之间的区别 http javarevisited blogspot sg 2010 10 difference Between hashmap and html http javar
  • 加密 JBoss 配置中的敏感信息

    JBoss 中的标准数据源配置要求数据库用户的用户名和密码位于 xxx ds xml 文件中 如果我将数据源定义为 c3p0 mbean 我会遇到同样的问题 是否有标准方法来加密用户和密码 保存密钥的好地方是什么 这当然也与 tomcat
  • 如何在 javadoc 中使用“<”和“>”而不进行格式化?

    如果我写
  • Java列表的线程安全

    我有一个列表 它将在线程安全上下文或非线程安全上下文中使用 究竟会是哪一个 无法提前确定 在这种特殊情况下 每当列表进入非线程安全上下文时 我都会使用它来包装它 Collections synchronizedList 但如果不进入非线程安
  • 如何实现仅当可用内存较低时才将数据交换到磁盘的写缓存

    我想将应用程序生成的数据缓存在内存中 但如果内存变得稀缺 我想将数据交换到磁盘 理想情况下 我希望虚拟机通知它需要内存并将我的数据写入磁盘并以这种方式释放一些内存 但我没有看到任何方法以通知我的方式将自己挂接到虚拟机中before an O
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j

随机推荐

  • 用c语言打印九九乘法表

    分析 这是一个典型的使用循环嵌套的题目 把题目分成两部分 被乘数和乘数 被乘数的变化是从1变化到9 乘数的变化是根据被乘数而来 这样就决定了被乘数的变化做为外循环 乘数的变化作为内循环 1 1 1 2 1 2 2 2 4 3 1 3 3 2
  • 路径遍历(目录遍历)

    一 简介 路径遍历攻击也称为目录遍历 旨在 访问存储在web根文件夹之外的文件和目录 通过操纵带有 点 斜线 序列及其变化的文件或使用绝对路径来引用文件的变量 来访问存储在文件系统上的任意文件和目录 包括应用程序源代码 配置和关键系统文件
  • 中国移动光猫无线路由一体机如何再接另外一个无线路由器

    将无线路由器连接光猫 用一条网线一端接入光猫网口1或网口3或网口4 另一端接入无线路由器WAN接口 将无线路由器连接电脑 用一条网线一端接入无线路器LAN接口 另一端插入电脑 光猫的默认地址为192 168 1 1 所以无线路由器的LAN口
  • 日期加年,返回年份

    日期加年 返回字符串 param date str yyyy mm dd 必须是这个格式 param year 加的年 return string 年份 static function dateAddYear date str year i
  • 数据库连接异常:create connection error, url: jdbc:mysql://ip/数据库名, errorCode 0, state 08S01问题处理

    今天项目中新增了一部分接口 本地测试好之后打包部署到测试环境 数据库竟然连接失败 报错信息如下 create connection error url jdbc mysql ip 数据库名 errorCode 0 state 08S01 这
  • solidworks齿轮编辑_如何应用solidworks进行齿轮工程图绘制

    引言 齿轮是一种常用的传动零件 也是机械设计过程中经常需要设计的一种零件 由于齿轮的工程图绘制与一般零件有较大区别 在利用一般的三维软件设计出三维图形后并不能马上得到准确的二维图形 这种情况会大大降低工程技术人员的设计速度 增加设计成本 S
  • 安卓数据线ssh连树莓派(超简单)

    无需联网 无需无限网卡 树莓派 sudo vim etc network interfaces 添加或修改这句iface usb0 inet dhcp 然后手机数据线插上树莓派 开启usb网络共享 用better terminal或者ter
  • 记录一个std::future和std::async的demo

    Demo和代码简述 子线程函数 参数a传进去模拟遇到的带参数问题 函数的返回值可以是处理完的任意值 若有返回值则get 到的就是返回值 比如这个demo里get到的就是3 int TestNoClass int a int main int
  • LFSR

    c语言中实现LFSR define CRT SECURE NO WARNINGS include
  • 同步式SPWM两电平正弦脉宽调制逆变器(全波三角波)——正弦波为调制波(双重傅里叶分析)

    SPWM正弦脉宽调制介绍 SPWM是调制波为正弦波 载波为三角波或锯齿波的一种脉宽调制法 特点 原理简单 通用性强 控制和调节性能好 具有先出谐波 调节和稳定输出电压的多种作用 是一种比较好的波形改善法 分类 分为两阶式和三阶式两种 阶 指
  • S3C2440读写sd卡的一些总结

    整理硬盘的时候发现这个文档 以前写2440操作sd卡程序的时候总结的 1 我的2440 sdi对sd卡发送ACMD41时总是反馈crc fail 但是可以得到正确的response sd卡可以正常使用 2 sd卡可以没有mbr 在物理的 0
  • 推理规则的具体应用

    小伙伴们 大家好呀 相信步入大二的同学们肯定会学到离散数学 而推理规则是离散数学中最fundmental and important 的知识体系 今天我们来说说基本的推理规则 Firstly 推理 inference rules 是 前提
  • hibernate--lazy(懒加载)属性

    关联映射文件中
  • 线性表之单链表

    include stdafx h include
  • WebRTC学习(二)Windows10平台WebRTC编译(VS2017)

    1 Visual Studio 2017安装 WebRTC用到了很多C 最新特性 所以编译最新WebRTC代码VS要求为2017 gt 15 7 2 版本 2 安装SDK调试工具 由于最新WebRTC源码要求10 0 18362及以上Win
  • wordpress线上部署&更新主题

    目录 新增主题 主题介绍 部署到线上 更新主题 新增主题 随便复制一个主题到test文件夹 test主题文件cnpm I npm i 失败的可以使用淘宝镜像 cpm i 热更新 主题介绍 test目录下的style css Theme Na
  • 论文笔记:LightGCL: Simple Yet Effective Graph Contrastive Learning for Recommendation

    ICLR 2023 1 intro GNN在基于图的推荐系统中展现了良好的效果 这得益于其整合相邻结点信息以进行协同过滤的能力 在用户 物品交互图上进行多层的信息传递 以此挖掘高阶的连接信息 很大一部分基于 GNN 的协同过滤模型采用了监督
  • vue跨域处理(vue项目中baseUrl设置问题)

    一 方法一 在公用文件common js中设置baseUrl export var baseUrl process env NODE ENV production window g ApiUrl api 该方法的优点 在项目打包时 stat
  • jvm关闭

    关闭方式 正常关闭 最后一个普通线程 非守护线程 结束 调用了System exit 发送SIGINT信号 相当于不带参数的kill命令 或者键入Ctrl C 强制关闭 调用Runtime halt 发送SIGKILL信号 kill 9 命
  • 认证鉴权与API权限控制在微服务架构中的设计与实现(一)

    引言 本文系 认证鉴权与API权限控制在微服务架构中的设计与实现 系列的第一篇 本系列预计四篇文章讲解微服务下的认证鉴权与API权限控制的实现 1 背景 最近在做权限相关服务的开发 在系统微服务化后 原有的单体应用是基于Session的安全