玩命加载中🤣🤣🤣

th-login


第三方登录:

vue-java前后端交互流程demo (本篇以gitee 为例)

时序图

sequenceDiagram
	actor c as 客户端
	participant f as 前端服务器
	participant b as 后端服务器
	participant g as gitee
	rect rgb(213, 235, 225)
        f ->> +g: 打开新窗口, 请求https://gitee.com/oauth/authorize
        note over f, g: 携带client_id以及redirect_url (此处是不安全的)
        g ->> g: 校验client_id
        g ->> -b: 重定向至后端服务器
        note over g,b: 携带code (此处是不安全的)
    end
    rect rgb(192, 214, 149)
        b ->> +g: 请求https://gitee.com/oauth/token
        note over b, g: 携带grant_type,client_id,client_secret,code,redirect_uri
        g -->> -b: 返回access_token
    end
        rect rgb(240, 194, 162)
        b ->> +g: 请求https://gitee.com/api/v5/user
        note over b, g: 携带access_token
        g -->> -b: 返回用户信息
    end
    rect rgb(235, 238, 232)
        b ->> f: 生成token, 并将token信息发送给老窗口, 然后关闭新窗口
        f ->> f: 监听到token
        f ->> c: 将token写入到客户端浏览器
	end

gitee

代码示例

  1. 前端打开新窗口, 并请求 gitee
giteeHandleClick(thirdpart) {
    const client_id = 'client_idxxxxx' // giteeid
    const redirect_uri = encodeURIComponent('http://uri/tp/gitee_cb') // gitee跳转地址
    const url = `https://gitee.com/oauth/authorize?client_id=${client_id}&redirect_uri=${redirect_uri}&response_type=code`
    window.open(url, thirdpart, 540, 540) // url,用户信息
}
  1. 后端接收gitee 所传code -> 获取access_token -> 获取用户信息 -> 生成用户token 并返回给前端
public void gitee(String code, HttpServletResponse resp) throws IOException {
    //获取访问令牌
    String accessToken = this.getAccessToken(code);
    //获取用户信息
    Map<String, Object> body = this.getUserInfo(accessToken);

    Object username = body.get("name");
    Object avatar = body.get("avatar_url");
    //用户信息存储本地, 生成JWT令牌给前端
    String token = userService.loginFromOAuth(username.toString(), avatar.toString(), "");
    //让页面去发送信息给前端调用者
    String script = String.format("<script>\n" +
                                  "window.opener.postMessage('%s','%s')\n" +
                                  "window.close()\n" +
                                  "</script>",
                                  //给调用者发送信息,(详细内容,来源)指明消息来源, 否则会跨域
                                  //window.opener.postMessage(message,origin)
                                  //window.close() 关闭小窗口
                                  token,
                                  frontendURL);
    resp.getWriter().print(script);
}

private String getAccessToken(String code) throws IOException {
    String json = new ObjectMapper().writeValueAsString(MapBuilder.create()
                                    .put("grant_type", "authorization_code")
                                    .put("client_id", clientId)
                                    .put("client_secret", clientSecret)
                                    .put("code", code)
                                    .put("redirect_uri", redirectURI).build()
                                                       );
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    HttpEntity<String> httpEntity = new HttpEntity<>(json, headers);
    ResponseEntity<String> response = restTemplate.postForEntity("https://gitee.com/oauth/token", httpEntity, String.class);
    Map body = new ObjectMapper().readValue(response.getBody(), Map.class);
    return body.getOrDefault("access_token", "").toString();
}

private Map<String, Object> getUserInfo(String accessToken) throws IOException {
    ResponseEntity<String> response = restTemplate.getForEntity(URI.create("https://gitee.com/api/v5/user?access_token=" + accessToken), String.class);
    Map body = new ObjectMapper().readValue(response.getBody(), Map.class);
    return body;
}
  1. 前端监听到token信息, 写入用户Cookie
window.addEventListener('message', msg => {
  // 可以对消息来源做判断
  if (msg.origin.toString().indexOf('8080') !== -1) {
    setToken(msg.data)
    window.location.href = '/' // 浏览器跳转
  }
})

文章作者: 👑Dee👑
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC 4.0 许可协议。转载请注明来源 👑Dee👑 !
  目录