图解登录流程
用户访问社区;点击登录;去github调用authorize(授权)地址;GitHub返回预先写好的redirect-uri地址并携带code;社区接到uri请求后解析出code,携带code去调用github的access_token接口;如果code正确会返回access_token;携带access_token去调用GitHub的user 接口;github返回user信息;存入数据,更新登陆状态;登陆成功。
实现过程
- 给登录按钮绑定一个ui地址,以及必填参数(client_id、redirect_uri、scope、state):
<a href="https://github.com/login/oauth/authorize?client_id=cd661c08676ed80603&redirect_uri=http://localhost:8887/callback&scope=user&state=1">登录</a>
这时点击登录跳转到authorize地址,登录GitHub后,GitHub返回预先写好的redirect-uri地址并携带一个code。
- 解析出code,携带code和下列四个参数去调用github的access_token接口 。
- 创建AccessTokenDTO,放入上面五个参数。
@Data
//创建AccessTokenDTO,放入上面五个参数。
public class AccessTokenDTO {
private String client_id;
private String client_secret;
private String code;
private String redirect_uri;
private String state;
}
- 使用okhttp POST方法携带五个参数去调用github的access_token接口 ,首先引入okhttp和fastjson的maven的包。
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
- okhttp POST方法带着使用fastJson将五个参数转换成的Json数据去请求github的access_token地址,得到access_token。得到的access_token是下面这种形式的字符串。
- 将access_token从字符串中截取出来,再使用okhttp GET去请求github的user地址+access_token(“https://api.github.com/user?access_token=”+accessToken),得到user信息,创建GithubUser 存储返回的user信息(我们只需要以下四个信息),使用fastJson的Json.parseObject(String,GithubUser.class),将String解析成GithubUser类对象。
@Data
public class GithubUser {
private String name;
private Long id;
private String bio;
private String avatar_url;
}
@Component
public class GithubProvider {
//okhttp POST方法带着使用fastJson将五个参数转换成的Json数据去请求github的access_token地址。
//返回access_token字符串,截取拿到access_token。
public String getAccessToken(AccessTokenDTO accessTokenDTO){
MediaType mediaType = MediaType.get("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
//将accessTokenDTO转换成Json类型
RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(accessTokenDTO));
Request request = new Request.Builder()
.url("https://github.com/login/oauth/access_token")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
String string = response.body().string();
String token = string.split("&")[0].split("=")[1];
return token;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
//再使用okhttp GET去请求github的user地址+access_token,得到user信息,
//使用fastJson的Json.parseObject(String,GithubUser.class),将String解析成类对象。
public GithubUser getUser(String accessToken){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.github.com/user?access_token="+accessToken)
.build();
try {
Response response = client.newCall(request).execute();
String string = response.body().string();
//fastJson的JSON.parseObject方法可以自动将String解析成类(GithubUser)对象。
//GithubUser里的值都可以获得
GithubUser githubUser = JSON.parseObject(string, GithubUser.class);
return githubUser;
} catch (IOException e) {
}
return null;
}
}
- 在AuthorizeController中调用GithubProvider 的getAccessToken方法获得access_token,传入access_token到getUser方法,得到GithubUser的user信息:
@Controller
public class AuthorizeController {
@Autowired
private GithubProvider githubProvider;
@GetMapping("/callback")
public String callback(@RequestParam(name ="code") String code,
@RequestParam(name="state") String state){
AccessTokenDTO accessTokenDTO = new AccessTokenDTO();
accessTokenDTO.setCode(code);
accessTokenDTO.setRedirect_uri("你的Redirect_uri");
accessTokenDTO.setState(state);
accessTokenDTO.setClient_id("你的Client_id");
accessTokenDTO.setClient_secret("你的Client_secret");
String accessToken = githubProvider.getAccessToken(accessTokenDTO);
GithubUser user = githubProvider.getUser(accessToken);
return "index";
}
}