前後端分離下的第三方登入

AD_milk發表於2021-07-16

大致流程(授權碼模式)

以碼云為例
前後端分離下的第三方登入

獲取使用者請求的API需要在請求中攜帶授權碼

而授權碼的獲取涉及OAuth2認證

  • 首先是使用者點選連結跳轉到碼雲的授權頁面
    跳轉連結需要將{client_id}{redirect_uri}替換為您在碼雲中註冊第三方應用時填寫的資訊

    response_type指定為授權碼模式(code)
    https://gitee.com/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code
    

    回撥地址最好上填成前端的,前端拿到code之後再發請求給spring應用

    使用者同意授權之後,碼雲會通過回撥地址將使用者授權碼code傳送給我們。
    也就是一個帶引數的get請求,可以使用searchParams從瀏覽器位址列中獲取它

    const urlParams = new URL(window.location.href)
    const code = urlParams.searchParams.get("code")
    

    回撥地址記得填寫成前端,如果回撥地址填了後端,由後端去主動通知web還是比較麻煩的。(當然你可以使用websocket)

  • 根據獲取到的授權碼(code)申請access_token
    這一步因為需要填充client_secret,所以我們可以讓前端傳送http請求給spring服務。讓spring帶上code以及secret去獲取access_token

      https://gitee.com/oauth/token?grant_type=authorization_code&code={code}&client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret}
    
  • 帶上上一步獲得的授權碼請求使用者基本資訊

      https://gitee.com/api/v5/user?access_token={your_token}
    

    根據您應用的規則去查詢資料庫,返回給前端相應的使用者資訊

部分程式碼

  •   @Controller
      @CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST})
      public class ThirdPartyLoginController {
        @Autowired
        private PrividerToken prividerToken;
        // 可以根據平臺的不同從配置中讀取
        String clientId = "123";
        String clientSecret = "123";
        String redirectUri = "http://callBack.com";
    
        @GetMapping("/thirdLoad")
        @ResponseBody
        public String callback(@RequestParam("code") String code
        ) throws IOException {
    
          prividerToken.setClientSecret(clientSecret);
          prividerToken.setClientId(clientId);
          prividerToken.setCode(code);
          String url = "https://gitee.com/oauth/token?grant_type=authorization_code"
                  + "&code=" + code
                  + "&client_id=" + prividerToken.getClientId()
                  + "&redirect_uri=" + prividerToken.getRedirectUri()
                  + "&client_secret=" + prividerToken.getClientSecret();
    
          MediaType mediaType
                  = MediaType.get("application/json; charset=utf-8");
    
          OkHttpClient client = new OkHttpClient();
          RequestBody body = RequestBody.create(JSON.toJSONString(prividerToken), mediaType);
          Request request = new Request.Builder()
                  .url(url)
                  .post(body)
                  .build();
    
          try (Response response = client.newCall(request).execute()) {
              String res = response.body().string();
              String split = res.split(":")[1];
              String accessToken = split.split("\"")[1];
              User userInfo = getUserInfo(accessToken);
              return String.valueOf(userInfo.getId());
          }
    
      }
    
      private User getUserInfo(@org.springframework.web.bind.annotation.RequestBody String accessToken) {
          OkHttpClient client = new OkHttpClient();
          String url = "https://gitee.com/api/v5/user?access_token=" + accessToken;
          Request request = new Request.Builder()
                  .url(url)
                  .build();
          User user = null;
          try (Response response = client.newCall(request).execute()) {
              String string = response.body().string();
              user = JSON.parseObject(string, User.class);
              System.out.println(user);
          } catch (IOException e) {
              e.printStackTrace();
          } finally {
              return user;
          }
      }
    }
    
  •       const urlParams = new URL(window.location.href)
          const code = urlParams.searchParams.get("code")
          if(code){
            $.ajax({
              url:'http://localhost:8080/thirdLogin?code='+code,
              method:'get',
              success:(res)=>{
                alert(res);
                console.log(res)
              }
            })
          }
    

如何在碼雲上申請第三方應用登入

  • 點選頭像,進入設定
  • 在側邊欄中選擇第三方應用
    前後端分離下的第三方登入

參考

相關文章