前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >1 Springboot SpringCloud集成OAuth2入门详细教程

1 Springboot SpringCloud集成OAuth2入门详细教程

作者头像
天涯泪小武
发布2019-01-17 11:28:01
1.7K0
发布2019-01-17 11:28:01
举报
文章被收录于专栏:SpringCloud专栏

关于OAuth2的解释,有一篇比较出名的文章——理解OAuth 2.0 - 阮一峰的网络日志(http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html),可以了解一下OAuth2的基础知识。

简单理解一下OAuth2,你要登录一个XX网站下片,但是下片需要注册登录成为这个网站的会员,你不想注册,还好网站提供了qq登录,你选择qq登录。那么问题来了,你选择qq登录时,会跳转到qq的登录页面,输入qq账号密码,注意,这时登录qq与这个XX网站是没关系的,这是qq做的登录页,登录时qq会问你是否允许该XXX网站获取你的个人信息如头像、昵称等,你勾选同意,登录成功后就又回到了XX网站的某个页面了。这是一个什么流程呢,其实是一个XX网站试图获取你个人信息、然后问你是否同意的一个流程。你同意了,qq才会允许第三方网站获取你的个人信息。

类似的场景还有很多,譬如你授权云打印平台去打印你云盘里的照片,这些统统归属于你(用户)授权第三方平台(Client,客户端)获取服务方(资源服务器)的资源。在这些场景下,你不需要在第三方平台输入你的账号密码,你所做的验证都是在服务方的认证服务器做的。认证通过后,认证服务器会返回一个token给第三方,第三方就可以拿着token去访问已经被授权访问的资源了,第三方不需要知道你的账号密码。当然,第三方能访问的资源的范围会在认证时显示出来给你看,你可以勾选哪些同意、哪些不同意,这样能避免第三方获取你太多的信息。

百度OAuth2认证流程实战

我们先来看看第三方平台是怎么工作的,我们自己充当一个第三方平台,用户不想在我的网站注册,我让他用百度账号登录,授权百度的个人信息给我。

这是百度的OAuth文档,http://developer.baidu.com/wiki/index.php?title=docs/oauth,要使用百度的OAuth认证,我们需要在百度开发者平台去创建一个应用

这里有API Key和Secret。

下图是OAuth的整个流程。

现在我们来执行OAuth的第一步,客户端要求用户给予授权。也就是用户到我们网站后,点击选择使用百度账号登录后,我们要做如下的事。

我们需要打开如下网址:http://openapi.baidu.com/oauth/2.0/authorize?client_id=VaAykBZSIK33tD1yRK3XoPtx&redirect_uri=http://qq.com&response_type=code&scope=basic&display=popup

这个网址就是百度设定的授权页面,里面的参数解释一下:

client_id就是你在百度开发者平台创建应用后得到的client_id,必填。

response_type为code,代表授权模式,授权模式有4种,最常用的就是授权码模式,我们也只看授权码模式,别的不管,所以这里固定值为code,必填。

scope代表授权范围,可以客户端自己设定不同的值代表不同的范围,譬如abc代表只允许访问用户名头像、def允许访问相册,是个可选项。

百度的文档里讲了授权权限列表

这里我们使用scope=basic

display这个参数不是OAuth里的参数,是百度自己加的,属于第三方平台自己新加的参数,看介绍,百度的目的是让回调的网页更美观。

redirect_uri代表回调的地址,也就是说当我们访问上面的请求授权地址时,如果授权通过了,那么就会自动打开redirect_uri这个网址,并且把授权码code添加到该网址的后缀。

我们作为一个第三方平台,上一步请求百度授权的目的就是为了得到这个授权码code。然后好拿着这个code,去进行下一步操作,去获取token。

上面我写的redirect_uri是http://qq.com,只是为了演示,如果是真的自己平台,需要填自己的网址。

然后在安全设置里,把授权回调页,填写进行,保存。注意,这里填的回调页需要和上面的redirect_uri网址的一样才行。

一样OK,我们就可以去申请授权了,直接访问http://openapi.baidu.com/oauth/2.0/authorize?client_id=VaAykBZSIK33tD1yRK3XoPtx&redirect_uri=http://qq.com&response_type=code&scope=basic&display=popup

可以看到出来了这样一个界面,注意看右边的“允许test应用进行以下操作”,这个就是上面配置的scope决定的。像这样的界面很多,微信啊qq啊都有这样的授权页,你可以选择勾选你想让访问的信息范围。

这里我们输入自己的百度账号密码,点登录即可。这里你的百度账号密码第三方平台是拿不到的,这是百度的登录页。

登录成功后界面:

可以看到,百度回调打开了我们填写的redirect_url,并且把code覆在后面。如果这是你自己的域名服务器,你就可以使用code参数接收到值,并且进行下一步获取token的操作了。

下面我们来获取token。

访问https://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code=66bee35200ddf4dfb3bd3caca1969e4b&client_id=VaAykBZSIK33tD1yRK3XoPtx&client_secret=FgL5vYi1Fs11IprXB8LprHIv4fslTqsC&redirect_uri=http://qq.com

这里面的grant_type是固定的,别的几个都和上面一样,多了个secret,从你的百度开发者平台能看到。code就是上一步获取到的code,注意code是有时限的,获取到code后过一段时间就失效了,需要重新获取code。

返回值如下:

这个是百度的文档:

可以看到百度返回了token,session_key、session_secret、refresh_token等字段,貌似和OAuth官方描述的不一样,可能百度自己有自己的考虑吧。下图是阮一峰文章里讲的正常的返回值。

已经取得了token了,我们就可以调用百度的一些api了,譬如可以通过GET方法发送如下请求包来调用获取当前登录用户的基本资料的开放API接口: GET https://openapi.baidu.com/rest/2.0/passport/users/getInfo?access_token=1.a6b7dbd428f731035f771b8d15063f61.86400.1292922000-2346678-124328

把token换成上一步取到的token,通过这个api就能获取到用户基本资料了。

OK,上面的几个步骤全部搞完,我们就已经完成了通过网页来搞定一次OAuth认证的全过程了。

SpringBoot OAuth2客户端实战

下面我们来使用SpringBoot完成一次同样的过程,来看看伟大的Spring为我们省略了哪几个步骤。此时我们就是个第三方平台,用户想要访问我们的内容,我们先让用户去登录他的百度账号给我们授权,就是这么个意思。

新建一个springboot项目,勾选web、Security,还要引入oauth2,最终的pom如下:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.tianyalei</groupId>
	<artifactId>test_oauth</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>test_oauth</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.8.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.security.oauth</groupId>
			<artifactId>spring-security-oauth2</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

在启动Application类上,加上@EnableOAuth2Sso注解

代码语言:javascript
复制
@SpringBootApplication
@EnableOAuth2Sso
public class TestOauthApplication {

	public static void main(String[] args) {
		SpringApplication.run(TestOauthApplication.class, args);
	}
}

来定义一个controller

代码语言:javascript
复制
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author wuweifeng wrote on 2017/10/18.
 */
@RestController
public class PublicController {
    @RequestMapping("/abc")
    public String index() {
        return "Hello abc";
    }

}

然后在resource下的static目录放一个index.html文件,里面就写一个句话Hello就行了。

看起来没什么,就是个普通的工程,毫无特色是吗?

启动它,访问localhost:8080试试,发现报错了,我们原以为能进入index.html,但是并没有,它报错了:

而且还自动给跳转到了localhost:8080/login这个网址去了,这是为什么呢?

我们使用Chrome的开发者工具来看一下

当访问localhost:8080时,302跳转了,跳转到了localhost:8080/login,这是spring OAuth2自动完成的,它拦截所有的请求,然后302到login,然后去做一件事,就是去OAuth的认证服务端去做认证,也就是带着clientId,redirect_uri等等参数,去访问server,去拿code,如果你还记得上面我们用浏览器请求百度code的步骤,你就明白。

那认证服务器地址在哪呢,它不知道,所以它报错了,异常里说了,需要个地址。

我们在application.yml里配置地址

代码语言:javascript
复制
security:
  oauth2:
    client:
      client-id: VaAykBZSIK33tD1yRK3XoPtx
      client-secret: FgL5vYi1Fs11IprXB8LprHIv4fslTqsC
      access-token-uri: http://openapi.baidu.com/oauth/2.0/token
      user-authorization-uri: http://openapi.baidu.com/oauth/2.0/authorize
    resource:
      userInfoUri: https://openapi.baidu.com/rest/2.0/passport/users/getInfo

client下的那几个参数都明白,我们文章上面都讲过,还有几个参数没列出来,看下图

可以看到tokenName也是可以自定义的,默认是"access_token",如果认证服务器不是这个,譬如Facebook的就叫"oauth_token",那么就配置tokenName。还有那两个scheme是干什么的呢?看下图DefaultClientAuthenticationHandler.java

它们是来决定发请求时是放在header里还是用form表单提交过去。

client的几个配置参数都懂了,还有个resource.userInfoUri,这个是干什么的呢,先不要管它,后面就知道了。

以上全部配置完毕,再启动项目,访问localhost:8080

看到百度给我们返回了这样一个界面,正常情况下应该是一个百度登录的界面。看箭头地方,redirect_uri=localhost:8080/login,这个地址我们并没有配置,是spring OAuth它自动给我们加上的,如果你还记得的话,我们上面在百度的回调地址配了个http://qq.com,下面我们把他修改为箭头的地址

再次访问localhost:8080.

好的,这下就是正常界面了,填写百度账号密码,看看效果。

可以看到,进入到了我们之前添加的index.html里了。再次访问localhost:8080/abc,也正常进入到了abc方法的返回,不需要再次百度鉴权。说明百度正常授权,并且已经返回了token,只不过这些都由spring自动给我们处理了。

再来回忆一下步骤,发起认证请求,输入百度账号密码成功后给我们返回code,我们拿着code再去请求百度token,百度返回token,我们拿着token去请求百度API接口。

现在看看spring的步骤,发起认证请求,输入百度账号密码,over。spring帮我们自动处理了code和token相关的事情。

下面我们来看看application.yml里resource.userInfoUri是干什么的,我们先把它注释掉。然后重启,访问localhost:8080

发现访问变的很漫长,最终出错了,这是为什么呢?

原来是spring在获得token后,必须要调用一下resource.userInfoUri里的接口,看看到底有没有返回值,也就是要验证一下token是不是正确的,这一步是它自动完成的。获得token——调用接口获取user details信息,如果成功了,才算正常,然后才会返回到你最开始调用的localhost:8080。

所以这个userInfoUri是必须的,我们可以在百度的文档里找到这个获取用户信息的API接口,填上去就OK了。

这一篇详细讲了OAuth客户端的工作流程,和集成springboot后的工作步骤,后面我们会自己搭建OAuth服务端。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017年10月19日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 百度OAuth2认证流程实战
  • SpringBoot OAuth2客户端实战
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档