前后端分离下的第三方登录
大致流程(授权码模式)
以码云为例
获取用户请求的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) } }) }
如何在码云上申请第三方应用登录
- 点击头像,进入设置
- 在侧边栏中选择第三方应用