Chaptor1 OAuth 2.0 Foundati1ons

最近在通过《OAuth 2.0 Cookbook_Protect Your Web Applications using Spring Security-Packt Publishing(2017)》这本书学习Spring security,英文书看得很头疼,网上也没有对应的中文翻译,就当是半翻译半自学笔记,如果能帮到其他人,就更好了。

第一章的主要内容如下:

  1. 准备环境
  2. client端从facebook获取用户的联系人
  3. 在server端从facebook读取用户的联系人
  4. 通过oauth2.0 linkedin受保资源
  5. 通过oauth2.0 google受保资源,并传入用户session

在开始学习之前,先看这幅图
图片描述

这幅图清楚地展现了OAuth2.0的四个主要部分:

  1. Resource owner: 授权给第三方应用使用资源。
  2. Resource server:保存,保护用户资源,通常和authorization server共同实现为一个服务,例如图中的OAuth2.0 Provider。
  3. Authorization server
  4. Client :第三方应用表现为Client

准备环境

本书的例子使用Java ,spring boot,maven。请预先搭好相应环境

Reading the user's contacts from facebook on the client side

客户端从Facebook读取用户的联系人

1. 首先注册一个facebook账号,并进入开发者页面 https://developers.facebook.com/apps/ 
2. 点击Create a New App ,Create App ID ,然后会跳转进入如下页面

图片描述

3.选择创建一个“Facebook Login”的“Web”产品,输入网址地址,本文输入"http://clientimplicit.test"
4.继续,输入登录成功后的跳转URL,例如”http://localhost:8080/callback. “,保存修改

图片描述

5.在左边面板选择“设置”->“基本”,可以获取appid, app secret,至此,facebook的设置暂时完成。
图片描述

6.现在新建一个spring 项目,加入“web”和“Thymeleaf ”依赖,在templates文件夹下创建client.html 文件
7.将以下代码,写入client.html

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head><title>Facebook - client side integration</title></head>
    <body>
    Press the following button to start the implicit flow.
    <button id="authorize" type="button">Authorize</button>
    <div id="box"></div>
    </body>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script type="text/javascript" th:inline="javascript">
    /*<![CDATA[*/
    $(document).ready(function () {
    $("#authorize").click(makeRequest);
    });
    //点击按钮,往授权中心发请求
    function makeRequest() {
    var auth_endpoint =
    "https://www.facebook.com/v3.0/dialog/oauth",
    response_type = "token",
    client_id = "1741430609244678",
    redirect_uri = "https://localhost:8089/callback",
    scope = "public_profile user_friends";
    var request_endpoint = auth_endpoint + "?" +
    "response_type=" + response_type + "&" +
    "client_id=" + client_id + "&" +
    "redirect_uri=" + encodeURI(redirect_uri) + "&" +
    "scope=" + encodeURI(scope);
    window.location.href = request_endpoint;
    }
    /*]]>*/
    </script>
    </html>

8.此外,我们还要将一个URL映射到这个html文件,于是还要将以下代码加入Application.java文件

    @Controller
    @SpringBootApplication
    public class ClientImplicitFacebookApplication {
    public static void main(String[] args) {
    SpringApplication.run(ClientImplicitFacebookApplication.class, args);
    }
    @GetMapping("/")
    public String client() {
    return "client";
    }
}

9.启动项目,点击Authorize 按钮,在完成验证以后,可以在浏览器看到如下的重定向URL:

http://localhost:8080/callback#access_token=EAAbsiSHMZC60BANUwKBDCY
           eySZCjcBpvFuUO1gXsfTGwWjnZAFTAZBIJB62jdUroAcNuZAVWO24yeqo0iazWYytVg
           rQ1bgNWI8vm07Ws4ZCHXpGridHfZB6PQ1rzM4BzP29IljgTTuBLZBFQBEnEn2LJiOWJ
           jA8J6Y73BLcjIe2vVMZB9c2GnZBpiK4iZAWEtkTsMEZD&expires_in=7152

10.现在,我们可以提取access_token和expires_in来获取用户的朋友信息了.首先,我们要写一个页面接受重定向的callback请求。
11.在Application.java页面加入以下代码:

    @GetMapping("/callback")
    public String callback() { 
      return "callback_page"; 
    }

12.新建callback_page.html 文件,写入

    <!DOCTYPE html>
    <html>
    <head><title>Insert title here</title></head>
    <body>
    Friends who has also granted client-implicit
    <div id="friends">
    <ul></ul>
    </div>
    </body>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script type="text/javascript">
    /*<![CDATA[*/
    $(document).ready(function () {
    //从url提取信息
    var fragment = window.location.hash;
    var res = getResponse(fragment);
    window.location.hash = '_#';
    if (res.hasError()) {
    $("<div>Error trying to obtain user's authorization!</div>").insertBefore('#friends');
    return;
    }
    getFriends(res['access_token'], function (friends) {
    $(friends).each(function (index, friend) {
    $('#friends').find('ul').append('<li>' + friend.name + '</li>');
    });
    });
    });
    /*]]>*/
    //将信息分割成map
    function getResponse(fragment) {
    var attributes = fragment.slice(1).split('&');
    var response = {};
    $(attributes).each(function (idx, attr) {
    var keyValue = attr.split('=');
    response[keyValue[0]] = keyValue[1];
    });
    response.hasError = function () {
    return !response['access_token'];
    };
    return response;
    }
    //拿到accessToken后,去资源中心拿资源
    function getFriends(accessToken, callback) {
    var baseUrl = 'https://graph.facebook.com/v2.9/';
    var endpoint = 'me/friends';
    var url = baseUrl + endpoint;
    $.ajax({
    url: url,
    beforeSend: function (xhr) {
    xhr.setRequestHeader("Authorization", "Bearer " + accessToken);
    },
    success: function (result) {
    var friends = result.data;
    callback(friends);
    },
    error: function (jqXHR, textStatus, errorThrown) {
    console.log(textStatus);
    }
    });
    }
    </script>
    </html>

How it Works……

在 facebook的验证环节中,Resource server和Authorization server的角色区分地并不是太明显,就像图中的OAuth2.0 Provider。
在上述步骤中,我们看到了客户端注册的三个步骤:

1) 选择client type.
2) 注册重定向路径(redirection url)
3) 输入应用信息

客户端注册成功后,我们拿到了client_id和client_secret,在上一个例子中,我们没用到密钥,因为是通过浏览器发送的,所以有泄漏的风险。因而,我们选择使用access token,来获取资源。Facebook 2.9有2个途径来通过Facebook Graph API 验证登录:

1)使用facebook SDK
2) 通过一个login请求流
我们选择了第二种方法,这就是我们刚才发送的请求流:


 var request_endpoint = auth_endpoint + "?" +
      "response_type=" + response_type + "&" +
      "client_id=" + client_id + "&" +
      "redirect_uri=" + encodeURI(redirect_uri) + "&" +
      "scope=" + encodeURI(scope);
       window.location.href = request_endpoint;

重定向到Authorization Server后,用户来进行验证,授权这个客户端app是否可以使用他的资源,一旦用户验证通过了,就会立刻重定向回之前输入的redirection url。当拿到access_token后,我们接下来要做的,就是运用Facebook Graph API 来拿到我们想要的资源。


Lavender
196 声望59 粉丝

喜欢开发,就酱紫~