java oss认证流程 java oauth认证_java oss认证流程


原创作者:万里

前言

最近公司项目需要使用OAuth 2.0对接客户的用户系统,而我以前只是知道有OAuth2.0这个协议,但是没有接触过,所以乘这个机会把OAuth 2.0相关知识梳理一遍,顺便使用Java语言开发一个Demo实现对接Gitlab.这里感谢同事钟亮和吴鹏对我工作上帮助和支持。

在接触一项新东西之前肯定要对他进行一个了解. 网上关于OAuth2.0的资料非常的多,这里只做简要叙述.首先要找到什么是OAuth 2.0。开放授权(OAuth 2.0)是一个授权协议,它允许软件应用代表(而不是充当)资源拥有者去访问资源拥有者的资源。应用向资源拥有者请求授权, 然后取得令牌(token), 并用他来访问资源。这一切都不需要去充当资源拥有者的身份, 因为令牌明确表示了被授予的访问权限。现如今越来越多的应用使用OAuth 2.0来授权,比如常见的使用QQ登录。

OAuth 2.0授权类型有以下几种:

1. Authorization Code (授权码模式)

2. Implicit (简化模式)

3. Password (密码模式)

4. Client Credentials (客户端模式)

5. Device Code (设备代码)

6. Refresh Token (刷新令牌)

OAuth是一个复杂的安全协议, 他需要不同的组件互相通信。但从根本上来说,OAuth事务中的两个重要步骤是颁发令牌和使用令牌。令牌表示授予客户端的访问权限, 他在OAuth2.0的各个部分都起到了核心作用。尽管每个步骤的细节会因多种因素而异, 但是一个规范的OAuth事务包含以下事件:

1. 资源拥有者向客户端表示他希望客户端代表他执行一些任务

2. 客户端在授权服务器上向资源拥有者请求授权

3. 资源拥有者许可客户端的授权请求

4. 客户端接收到来的授权服务器令牌

5. 客户端向受保护资源出示令牌

授权码模式(Authorization Code)

授权码模式(Authorization Code)是功能最完善,流程最严密的授权模式。他的特点就是通过客户端的后台服务器,与“服务提供商”的认证服务器进行互动。其他的模式基本上都是对授权码模式的简化和定制。翻看OAuth2.0的RFC(Request for Comments 请求意见稿)时看到他的流程如下。要看懂他就要知道其中的一些专有名词:

1. Resource Owner: 资源拥有者,这里指客户的用户

2. User-Agent: 用户代理, 一般指的是浏览器

3. Client: 客户端, 这里指的是我们需要做对接的系统,比如下面的demo程序

4. Authorization Server: 授权服务, 这里指提供授权服务的系统,比如gitlab

+----------+ | Resource | | Owner | | | +----------+ ^ | (B) +----|-----+ Client Identifier +---------------+ | -+----(A)-- & Redirection URI ---->| | | User- | | Authorization | | Agent -+----(B)-- User authenticates --->| Server | | | | | | -+----(C)-- Authorization Code ------(D)-- Authorization Code ---------' | | Client | & Redirection URI | | | | | |

下面我将以实战的方式来进一步阐述他的流程,开发之前的一些准备工作是要有一个Gitlab账号,在这里(https://gitlab.com/profile/applications)注册一个需要开发这个程序的相关信息,Name是在Gitlab中用于标识客户端的名字,Redirect URI是客户端的一个回调地址。注册成功后我们会获得Client ID(or Application), Secret。


❖ 1. 用户使用浏览器代理用户的所有行为,Client需要授权时浏览器去授权服务器获取验证码,响应代码如下:


private static final String CLIENT_ID = "37c111426318a880b3eba318c77b455835364485e8e51292fc017ace9a31fb291";  private static final String GITLAB_REDIRECT_URL = "https://gitlab.com/oauth/authorize?client_id=%s&redirect_uri=%s&response_type=code&state=YOUR_UNIQUE_STATE_HASH"; private static final String REDIRECT_URL = "http://127.0.0.1/gitlab/callback"; @GetMapping("login") public void login(HttpServletResponse response) throws IOException { response.sendRedirect(String.format(GITLAB_REDIRECT_URL, CLIENT_ID, REDIRECT_URL)); }


我使用的是Web客户端,因此采用HTTP重定向的方式将用户代理重定向到授权服务器的授权端点,客户端的HTTP响应如下


HTTP/1.1 302Location: https://gitlab.com/oauth/authorize?client_id=37c111426318a880b3eba318c77b455835364485e8e51292fc017ace9a31fb291&redirect_uri=http://127.0.0.1/gitlab/callback&response_type=code&state=YOUR_UNIQUE_STATE_HASHContent-Length: 0Date: Mon, 26 Aug 2019 08:45:54 GMT


❖ 2. 浏览器根据Location请求授权服务器,当授权成功后用户代理将在次重定向回到客户端的redirect_uri http://127.0.0.1/gitlab/callback, 客户端获取到code再去请求授权服务器获取AccessToken, 代码如下:


//完整路径 /gitlab/callback@GetMapping("callback") public String callback(@RequestParam String code, HttpServletRequest request, HttpServletResponse response) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON_UTF8); Map map = new HashMap<>(8); map.put("client_id