单点登录是多域企业站点中普遍使用的一种登录方式。 本文力求通过对现实生活场景的辅助理解,彻底理清OAuth2.0实现单点登录的原理流程。 并总结了权限控制的实现方案及其在微服务器架构中的应用。
1单点登录1.1多登录传统的多登录系统在每个站点都有自己的帐户数据库和登录模块。 各站点的登录状态互不承认,各站点必须一个一个手动登录。 如下图所示,有以下两个术语的含义。
验证认证:用户的身份; 授权:验证用户的访问权限。 image.png 1.2单点登录,英语为Single Sign On,简称SSO。 多个站点(192.168.1.20X )共享一个认证许可服务器(192.168.1.110 )并共享用户数据库和认证许可模块。 用户通过任何一个网站登录,例如192.168.1.201,就可以免除登录并访问所有其他网站。 另外,各网站之间可以在该登录状态下直接进行交换。
image.png 2 OAuth2认证认可的原理流程2.1生命实例【重点】为了直观理解OAuth2.0的原理流程,假设这样的生命场景。
(1)文件站a )客户/客户:用“文件站ID/密码”表示,是掌握文件资源的机构。 另外,还有许多档案局B/C/…每个档案局保存的归档内容(资源/资源)都不一样,包括政治、经济、军事、文化等
)2)市民经常迟到的鼠标(资源所有者/Resource Owner ) :由“用户名/密码”标识,需要在各文件局查阅文件
)3)派出所)授权服务器/授权服务器) :可以是单个巨大的派出所,也可以是数据共享的派出所集群。 负责的信息,提供的对外接口功能如下。
档案信息:所有档案局的“档案局ID/密码”是证明档案局身份的公民信息:所有公民的“用户名/密码”是迟到鼠标为迟到鼠标的用户身份证明(认证/密码) 具有dtdqq和文件局权限的映射表可以检查每个公民是否对每个文件局具有操作权限(授权/授权)。 通常,设计中会添加一个官职(角色/Role )层次,指明每个公民属于哪个官职(角色),哪个官职(角色)对特定文件站具有操作权限。 2.1.1经常迟到的鼠标在第一次拜访经常迟到的鼠标之前没有访问过档案局,而是第一次来档案局。 对照下图序列号理解:
)总是迟到的鼠标来到“文件局a”的“文件地址”,可以要求实名注册后再询问,被“用户注册地址”指示处理(HTTP重定向)。
)经常迟到的鼠标来到“文件a”的“用户注册处”,无法证明有身份证(认证)和查阅文件a的权限)授权)。 迟到的鼠标携带文件局a的标记(client-id ),被重定向到“授权书发行处”;
)3)经常迟到的鼠标来到“派出所”的“授权书发放处”,出示档案局a的标识,希望发放授权书(授权)。 这里首先要求身份证明(认证),被重定向到“用户认证所”;
)4)经常迟到的鼠标来到“派出所”的“用户认证所”,收到了用户身份证(web登录表格)
)5)在经常迟到的鼠标上填写自己的用户名和密码,(提交/Submit )交给“用户认证所”。 在这里,从私人数据库中调查用户名和密码一致,确认此人是经常迟到的鼠标,发放身份证,完成认证。 迟到的鼠标拿着身份证和档案局a的显示,被重定向到“授权书发行处”;
(6)经常迟到的鼠标再次来到“授权书发放处”,出示身份证和档案局a标识。 这里从私人数据库中查询,经常迟到的鼠标的官职是市长级别),如果该官职拥有文件局a的查询权限,则发出“允许经常迟到的鼠标查询文件局a”的授权书)授权码/代码(/code )
)经常迟到的鼠标到达了“文件局”的“用户注册地”。 在那里,他个人取出了档案局a的标识(client-id )和密码,并附上了经常迟到的鼠标出示的许可证(code ),由经常迟到的鼠标向“档案局”的“腰牌发行地”申请
)经常迟到的鼠标会话(Session )已经与腰牌)相关联,可以直接从“文件位置”查询文件。
image.png 2.1.2旧的迟到鼠标首次访问档案局b旧的迟到鼠标已成功访问档案局a。 现在他要访问档案局b了。 对照下图序列号理解:
(1)/(2)同上;
)3)经常迟到的老鼠已经有了“身份证”,直接在“派出所”的“授权书发放处”成功发放了“接入档案局b”的授权书。
(4)/(5)/(6)豁免
(7)“档案b”的“用户注册处”注册完成;
(8)“档案局b”的“档案库地址”调查了文件。
Oauth2.0实现单点登录的原理流程,通俗易懂 2.1.3 老迟到的鼠标再次访问档案局A老迟到的鼠标已经成功访问了档案局A,现在他要访问档案局A。对照下图序号理解:
(1)直接成功查到了档案;
(2~8)都免了。
Oauth2.0实现单点登录的原理流程,通俗易懂 2.2 HTTP 重定向原理HTTP 协议中,浏览器的 REQUEST 发给服务器之后,服务器如果发现该业务不属于自己管辖,会把你支派到自身服务器或其他服务器(host)的某个接口(uri)。正如我们去政府部门办事,每到一个窗口,工作人员会说“你带上材料A,到本所的X窗口,或者其他Y所的Z窗口”进行下一个手续。
image.png 2.3 SSO 工作流程至此,就不难理解 OAuth 2.0 的认证/授权流程,此处不再赘述。请拿下图对照“2.1 生活实例”一节来理解。
image.png 2.4 OAuth2.0 进阶 https://tools.ietf.org/html/rfc6749https://tools.ietf.org/html/rfc6750https://blog.csdn.net/seccloud/article/details/8192707根据官方标准,OAuth 2.0 共用四种授权模式:
Authorization Code: 用在服务端应用之间,这种最复杂,也是本文采用的模式;Implicit: 用在移动app或者web app(这些app是在用户的设备上的,如在手机上调起微信来进行认证授权)Resource Owner Password Credentials(password): 应用直接都是受信任的(都是由一家公司开发的,本例子使用)Client Credentials: 用在应用API访问。 image.png 3 基于 SpringBoot 实现认证/授权 3.1 授权服务器(Authorization Server)(1) pom.xml
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId></dependency>(2) application.properties
server.port=8110 ## 监听端口(3) AuthorizationServerApplication.java
@EnableResourceServer // 启用资源服务器public class AuthorizationServerApplication { // ...}(4) 配置授权服务的参数
@Configuration@EnableAuthorizationServerpublic class Oauth2AuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter { @Override public void configure(final ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("webapp").secret("secret") //客户端 id/secret .authorizedGrantTypes("authorization code") //授权妈模式 .scopes("user_info") .autoApprove(true) //自动审批 .accessTokenValiditySeconds(3600); //有效期1hour }}@Configurationpublic class Oauth2WebSecurityConfigurer extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.requestMatchers() .antMatchers("/login", "/oauth/authorize/oauth/logout") .and().authorizeRequests().anyRequest().authenticated() .and().formLogin().permitAll(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("admin").password("admin123").roles("ADMIN"); }} 3.2 客户端(Client, 业务网站)(1) pom.xml
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId></dependency>(2) application.properties
server port=8080security.oauth2.client.client-id=webappsecurity.oauth2.client.client-secret=secretsecurity.oauth2.client.access-token-uri=http://localhost:8110/oauth/tokensecurity.oauth2.client.user-authorization-uri=http://localhost:8110/oauth/authorizesecurity.oauth2.resource.user-info-uri=http://localhost:8110/oauth/user(3) 配置 WEB 安全
@Configuration@EnableOAuth2Ssopublic class Oauth2WebsecurityConfigurer extends WebSecurityConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.antMatcher("/**").authorizeRequests() .antMatchers("/", "/login").permitAll() .anyRequest().authenticated(); }}@RestControllerpublic class Oauth2ClientController { @GetMapping("/") public ModelAndView index() { return new ModelAndView("index"); } @GetMapping("/welcome") public ModelAndView welcome() { return new ModelAndView("welcome"); }} 3.3 用户权限控制(基于角色) 授权服务器中,定义各用户拥有的角色: user=USER, admin=ADMIN/USER, root=ROOT/ADMIN/USER业务网站中(client),注解标明哪些角色可 @RestControllerpublic class Oauth2ClientController { @GetMapping("/welcome") public ModelAndView welcome() { return new ModelAndView("welcome"); } @GetMapping("/api/user") @PreAuthorize("hasAuthority('USER')") public Map<String, Object> apiUser() { } @GetMapping("/api/admin") @PreAuthorize("hasAuthority('ADMIN')") public Map<String, Object> apiAdmin() { } @GetMapping("/api/root") @PreAuthorize("hasAuthority('ROOT')") public Map<String, Object> apiRoot() { }} 4 综合运用 4.1 权限控制方案下图是基本的认证/授权控制方案,主要设计了认证授权服务器上相关数据表的基本定义。可对照本文“2.1 生活实例”一节来理解。
image.png 4.2 在微服务架构中的应用与常规服务架构不同,在微服务架构中,Authorization Server/Resource Server 是作为微服务存在的,用户的登录可以通过API网关一次性完成,无需与无法跳转至内网的 Authorization Server 来完成。
image.png好了,今天的文章就到这里了,希望通过这篇文章你能真正掌握Oauth2.0实现单点登录的原理。最后,我是一名写代码的架构师,做架构的程序员,期待你的关注。咱们有缘再见!