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

作者: [Aoho’s Blog]

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

1. 背景

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

最近在做权限相关服务的开发,在系统微服务化后,原有的单体应用是基于session的安全权限方式,不能满足现有的微服务架构的认证与鉴权需求。微服务架构下,一个应用会被拆分成若干个微应用,每个微应用都需要对访问进行鉴权,每个微应用都需要明确当前访问用户以及其权限。尤其当访问来源不只是浏览器,还包括其他服务的调用时,单体应用架构下的鉴权方式就不是特别合适了。在微服务架构下,要考虑外部应用接入的场景、用户–服务的鉴权、服务–服务的鉴权等多种鉴权场景。
比如用户A访问User Service,A如果未登录,则首先需要登录,请求获取授权token。获取token之后,A将携带着token去请求访问某个文件,这样就需要对A的身份进行校验,并且A可以访问该文件。

最近在做权限相关服务的开发,在系统微服务化后,原有的单体应用是基于session的安全权限方式,不能满足现有的微服务架构的认证与鉴权需求。微服务架构下,一个应用会被拆分成若干个微应用,每个微应用都需要对访问进行鉴权,每个微应用都需要明确当前访问用户以及其权限。尤其当访问来源不只是浏览器,还包括其他服务的调用时,单体应用架构下的鉴权方式就不是特别合适了。在微服务架构下,要考虑外部应用接入的场景、用户–服务的鉴权、服务–服务的鉴权等多种鉴权场景。
比如用户A访问User Service,A如果未登录,则首先需要登录,请求获取授权token。获取token之后,A将携带着token去请求访问某个文件,这样就需要对A的身份进行校验,并且A可以访问该文件。
为了适应架构的变化、需求的变化,auth权限模块被单独出来作为一个基础的微服务系统,为其他业务service提供服务。

2. 系统架构的变更

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

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

单体应用架构到分布式架构,简化的权限部分变化如下面两图所示。
(1)单体应用简化版架构图:
[singl](http://upload-images.jianshu.io/upload_images/2830896-47ef8e53ee297799.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

单体架构

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

分布式架构

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

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

3. 技术方案

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

3.1 认证与鉴权

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

  1. 分布式Session方案

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

  2. 基于OAuth2 Token方案

    基于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很容易入手,上手快控制粒度可糙可细。自由度高,Shiro既能配合Spring使用也可以单独使用。

  2. Spring Security

    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系统的最终使用组件如下:

OAuth2.0 JWT Token
Spring Security
Spring boot

4.2 步骤

主要步骤为:

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

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

4.3 endpoint

提供的endpoint:

/oauth/token?grant_type=password #请求授权token/oauth/token?grant_type=refresh_token #刷新token/oauth/check_token #校验token/logout #注销token及权限相关信息

4.4 maven依赖

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

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>2.2.0</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId><version>1.2.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId><version>1.2.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jersey</artifactId><version>1.5.3.RELEASE</version></dependency>

4.5 AuthorizationServer配置文件

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

@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//配置客户端认证clients.withClientDetails(clientDetailsService(dataSource));}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { //配置token的数据源、自定义的tokenServices等信息endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore(dataSource)).tokenServices(authorizationServerTokenServices()).accessTokenConverter(accessTokenConverter()).exceptionTranslator(webResponseExceptionTranslator);}

4.6 ResourceServer配置

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

@Overridepublic void configure(HttpSecurity http) throws Exception {http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().requestMatchers().antMatchers("/**").and().authorizeRequests().antMatchers("/**").permitAll().anyRequest().authenticated().and().logout().logoutUrl("/logout").clearAuthentication(true).logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()).addLogoutHandler(customLogoutHandler());

4.7 执行endpoint

  1. 首先执行获取授权的endpoint。
method: post 
url: http://localhost:12000/oauth/token?grant_type=password
header:
{Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=,Content-Type: application/x-www-form-urlencoded
}
body:
{username: keets,password: ***
}

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

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

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

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

2.鉴权的endpoint

method: post 
url: http://localhost:12000/oauth/check_token
header:
{Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=,Content-Type: application/x-www-form-urlencoded
}
body:
{token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsImV4cCI6MTUwODQ0Nzc1NiwidXNlcl9uYW1lIjoia2VldHMiLCJqdGkiOiJiYWQ3MmIxOS1kOWYzLTQ5MDItYWZmYS0wNDMwZTdkYjc5ZWQiLCJjbGllbnRfaWQiOiJmcm9udGVuZCIsInNjb3BlIjpbImFsbCJdfQ.5ZNVN8TLavgpWy8KZQKArcbj7ItJLLaY1zBRaAgMjdo
}

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

{"X-KEETS-UserId": "d6448c24-3c4c-4b80-8372-c2d61868f8c6","user_name": "keets","scope": ["all"],"active": true,"exp": 1508447756,"X-KEETS-ClientId": "frontend","jti": "bad72b19-d9f3-4902-affa-0430e7db79ed","client_id": "frontend"
}

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

3.刷新token

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

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

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

4.注销token

method: get
url: http://localhost:9000/logout
header:
{Authorization: bearereyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MDgzMzkwNTQsIlgtU0lNVS1Vc2VySWQiOiIwOGFhMTYxYi1lYjI3LTQ2NjAtYjA1MC1lMDc5YTJiODBhODMiLCJ1c2VyX25hbWUiOiJrZWV0cyIsImp0aSI6IjJhNTQ4NjY2LTRjNzEtNGEzNi1hZmY0LTMwZTI1Mjc0ZjQxZSIsImNsaWVudF9pZCI6ImZyb250ZW5kIiwic2NvcGUiOlsibWVua29yIl19.rA-U2iXnjH0AdPaGuvSEJH3bTth6AT3oQrGsKIams30
}

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

5. 总结

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


参考

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

我的官网
我的博客

我的官网http://guan2ye.com
我的CSDN地址http://blog.csdn.net/chenjianandiyi
我的简书地址http://www.jianshu.com/u/9b5d1921ce34
我的githubhttps://github.com/javanan
我的码云地址https://gitee.com/jamen/
阿里云优惠券https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=vf2b5zld&utm_source=vf2b5zld

阿里云教程系列网站http://aliyun.guan2ye.com

1.png

我的开源项目spring boot 搭建的一个企业级快速开发脚手架

1.jpg

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

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

相关文章

mac下完全卸载程序的方法

在国外网上看到的&#xff0c;觉得很好&#xff0c;不仅可以长卸载的知识&#xff0c;还对mac系统有更深的认识。比如偏好设置文件&#xff0c;我以前设置一个程序坏了&#xff0c;打不开了&#xff0c;怎么重装都打不开&#xff0c;后来才知道系统还保留着原来的偏好设置文件。…

机器学习集群_机器学习中的多合一集群技术在无监督学习中应该了解

机器学习集群Clustering algorithms are a powerful technique for machine learning on unsupervised data. The most common algorithms in machine learning are hierarchical clustering and K-Means clustering. These two algorithms are incredibly powerful when appli…

自考本科计算机要学什么,计算机自考本科需要考哪些科目

高科技发展时代&#xff0c;怎离得开计算机技术&#xff1f;小学生都要学编程了&#xff0c;未来趋势一目了然&#xff0c;所以如今在考虑提升学历的社会成人&#xff0c;多半也青睐于计算机专业&#xff0c;那么计算机自考本科需要考哪些科目&#xff1f;难不难&#xff1f;自…

非对称加密

2019独角兽企业重金招聘Python工程师标准>>> 概念 非对称加密算法需要两个密钥&#xff1a;公钥&#xff08;publickey&#xff09;和私钥&#xff08;privatekey&#xff09;。公钥与私钥是一对&#xff0c;如果用公钥对数据进行加密&#xff0c;只有用对应的私…

政府公开数据可视化_公开演讲如何帮助您设计更好的数据可视化

政府公开数据可视化What do good speeches and good data visualisation have in common? More than you may think.好的演讲和好的数据可视化有什么共同点&#xff1f; 超出您的想象。 Aristotle — the founding father of all things public speaking — believed that th…

C++字符串完全指引之一 —— Win32 字符编码 (转载)

C字符串完全指引之一 —— Win32 字符编码原著&#xff1a;Michael Dunn翻译&#xff1a;Chengjie Sun 原文出处&#xff1a;CodeProject&#xff1a;The Complete Guide to C Strings, Part I 引言  毫无疑问&#xff0c;我们都看到过像 TCHAR, std::string, BSTR 等各种各样…

网络计算机无法访问 请检查,局域网电脑无法访问,请检查来宾访问帐号是否开通...

局域网电脑无法访问&#xff0c;有时候并不是由于网络故障引起的&#xff0c;而是因为自身电脑的一些设置问题&#xff0c;例如之前谈过的网络参数设置不对造成局域网电脑无法访问。今天分析另一个电脑设置的因素&#xff0c;它也会导致局域网电脑无法访问&#xff0c;那就是宾…

雷军的金山云D轮获3亿美元!投后估值达19亿美金

12月12日&#xff0c;雷军旗下金山云宣布D轮完成3亿美元融资&#xff0c;金额为云行业单轮融资最高。至此金山云投后估值达到19亿美元&#xff0c;成为国内估值最高的独立云服务商。金山集团相关公告显示&#xff0c;金山云在本轮融资中总计发行3.535亿股D系列优先股。骊悦投资…

转:利用深度学习方法进行情感分析以及在海航舆情云平台的实践

http://geek.csdn.net/news/detail/139152 本文主要为大家介绍深度学习算法在自然语言处理任务中的应用——包括算法的原理是什么&#xff0c;相比于其他算法它具有什么优势&#xff0c;以及如何使用深度学习算法进行情感分析。 原理解析 在讲算法之前&#xff0c;我们需要先剖…

消费者行为分析_消费者行为分析-是否点击广告?

消费者行为分析什么是消费者行为&#xff1f; (What is Consumer Behavior?) consumer behavior is the study of individuals, groups, or organizations and all the activities associated with the purchase, use, and disposal of goods and services, and how the consu…

魅族mx5游戏模式小熊猫_您不知道的5大熊猫技巧

魅族mx5游戏模式小熊猫重点 (Top highlight)I’ve been using pandas for years and each time I feel I am typing too much, I google it and I usually find a new pandas trick! I learned about these functions recently and I deem them essential because of ease of u…

非常详细的Django使用Token(转)

基于Token的身份验证 在实现登录功能的时候,正常的B/S应用都会使用cookiesession的方式来做身份验证,后台直接向cookie中写数据,但是由于移动端的存在,移动端是没有cookie机制的,所以使用token可以实现移动端和客户端的token通信。 验证流程 整个基于Token的验证流程如下: 客户…

数据科学中的数据可视化

数据可视化简介 (Introduction to Data Visualization) Data visualization is the process of creating interactive visuals to understand trends, variations, and derive meaningful insights from the data. Data visualization is used mainly for data checking and cl…

手把手教你webpack3(6)css-loader详细使用说明

CSS-LOADER配置详解 前注&#xff1a; 文档全文请查看 根目录的文档说明。 如果可以&#xff0c;请给本项目加【Star】和【Fork】持续关注。 有疑义请点击这里&#xff0c;发【Issues】。 1、概述 对于一般的css文件&#xff0c;我们需要动用三个loader&#xff08;是不是觉得好…

多重线性回归 多元线性回归_了解多元线性回归

多重线性回归 多元线性回归Video Link影片连结 We have taken a look at Simple Linear Regression in Episode 4.1 where we had one variable x to predict y, but what if now we have multiple variables, not just x, but x1,x2, x3 … to predict y — how would we app…

tp703n怎么做无线打印服务器,TP-Link TL-WR703N无线路由器无线AP模式怎么设置

TP-Link TL-WR703N无线路由器配置简单&#xff0c;不过对于没有网络基础的用户来说&#xff0c;完成路由器的安装和无线AP模式的设置&#xff0c;仍然有一定的困难&#xff0c;本文学习啦小编主要介绍TP-Link TL-WR703N无线路由器无线AP模式的设置方法!TP-Link TL-WR703N无线路…

pandas之groupby分组与pivot_table透视

一、groupby 类似excel的数据透视表&#xff0c;一般是按照行进行分组&#xff0c;使用方法如下。 df.groupby(byNone, axis0, levelNone, as_indexTrue, sortTrue, group_keysTrue,squeezeFalse, observedFalse, **kwargs) 分组得到的直接结果是一个DataFrameGroupBy对象。 df…

js能否打印服务器端文档,js打印远程服务器文件

js打印远程服务器文件 内容精选换一换对于密码鉴权方式创建的Windows 2012弹性云服务器&#xff0c;使用初始密码以MSTSC方式登录时&#xff0c;登录失败&#xff0c;系统显示“第一次登录之前&#xff0c;你必须更改密码。请更新密码&#xff0c;或者与系统管理员或技术支持联…

如何使用Python处理丢失的数据

The complete notebook and required datasets can be found in the git repo here完整的笔记本和所需的数据集可以在git repo中找到 Real-world data often has missing values.实际数据通常缺少值 。 Data can have missing values for a number of reasons such as observ…

为什么印度盛产码农_印度农产品价格的时间序列分析

为什么印度盛产码农Agriculture is at the center of Indian economy and any major change in the sector leads to a multiplier effect on the entire economy. With around 17% contribution to the Gross Domestic Product (GDP), it provides employment to more than 50…