OAuth 2.0

授权模式

授权码

三方应用先申请一个授权码,然后通过该授权码获得令牌。

假设 A 网站要使用B网站的用户信息。

A 网站要先申请 client_idclient_secret

第一步,A提供一个连接,用户点击后跳转到B网站,授权用户给数据给A网站使用。

第一步 用户点击B网站登录跳转到B网站

A->B 链接

一个位于 A 网站上的链接 例如 B网站登录

https://b.com/oauth/authorize?
  response_type=code&
  client_id=CLIENT_ID&
  redirect_uri=CALLBACK_URL&
  scope=read

假设 CALLBACK_URL = https://a.com/callback

第二步 用户在B网站登录跳转到A网站

用户跳转到B网站,进行登录操作,登陆后会跳转到上一步的CALLBACK_URL, 并携带一个code

https://a.com/callback?code=AUTHORIZATION_CODE

第三步 A网站后端根据 code 获得 token

A网站的callback接收到code参数,后端向B请求令牌

https://b.com/oauth/token?
 client_id=CLIENT_ID&
 client_secret=CLIENT_SECRET&
 grant_type=authorization_code&
 code=AUTHORIZATION_CODE&
 redirect_uri=CALLBACK_URL

其中,client_idclient_secret用来确认A的身份,grant_type

authorization_code表示授权码模式,code是传过来的授权码,

redirect_uri是令牌颁发后的回调地址。

第四步 B网站收到请求,颁发令牌

向第三步的回调地址发送一段json数据

{    
  "access_token":"ACCESS_TOKEN",
  "token_type":"bearer",
  "expires_in":2592000,
  "refresh_token":"REFRESH_TOKEN",
  "scope":"read",
  "uid":100101,
  "info":{...}
}

此时 A网站便可以通过令牌 调用 B网站的接口了

Github OAuth2 实战

注册应用 获得 client_id 和 sercet

https://github.com/settings/applications/new

配置 回调地址

假设为 http://localhost/oauth/redirect

服务器实现

@RestController
public class OuathController {

    @Autowired
    RestTemplate restTemplate;

    @Value("${github.client.ID}")
    String clientID;
    @Value("${github.client.secret}")
    String clientSecret;


    @RequestMapping("/oauth/redirect")
    public String redirect(@RequestParam("code") String code) {
        System.out.println("code: " + code);
        // 通过 code 获得 access_token
        String postUrl = "https://github.com/login/oauth/access_token";
        //headers
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.setContentType(MediaType.APPLICATION_JSON);
        requestHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        //body
        Map<String, String> requestBody = new HashMap();
        requestBody.put("client_id", clientID);
        requestBody.put("client_secret", clientSecret);
        requestBody.put("code", code);
        HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, requestHeaders);
        Map<String, Object> s = restTemplate.postForObject(postUrl, requestEntity, Map.class);
        String token = (String) s.get("access_token");
        System.out.println("access token:" + token);

        requestBody.clear();
        requestHeaders.setBearerAuth(token);
        requestEntity = new HttpEntity<>(requestBody, requestHeaders);
        String userUrl = "https://api.github.com/user";
        ResponseEntity<String> exchange = restTemplate.exchange(userUrl, HttpMethod.GET, requestEntity, String.class);
        return exchange.getBody();
    }

}

用户操作

用户通过 <a href="https://github.com/login/oauth/authorize?client_id=11d48799b5cbf9a06fb0&redirect_uri=http://localhost:8080/oauth/redirect">github</a>

跳转到 github登录,授权后,用户会跳转到http://localhost:8080/oauth/redirect?code=a69488907d4ed78ce1c1

后台可以根据code访问github获得acess_token,根据acess_token便可获得用户的各种信息了

Last Updated:
Contributors: himcs, mcs