现在很多站点都支持第三方登录功能, 如何实现第三方登录,做以下记录:
首先有一个GitHub账号
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form method="get" action="/oauth/login">
<input type="submit" th:name="type" th:value="github">
<input type="submit" th:name="type" th:value="gitee"/>
</form>
</body>
</html>
@GetMapping(value = "/login")
public String login() {
return "login";
}
会重定向到github的登录授权页面;地址如下:
https://github.com/login/oauth/authorize?client_id=xxxxxxxxxxxxxxxxxx&scope=user,public_repo
地址跳转到回掉地址,并携带一个code 参数
http://localhost:8080/login?code=xxxxxxxxxxxxxxxxxxxx
需要传入client_id,client_secret 以及 上一步回调得到的code参数
https://github.com/login/oauth/access_token?client_id=xxxxxxxxxxxxxxxxxxx&client_secret=xxxxxxxxxxxxxxxxx&code=xxxxxxxxxxxxxxxxxxx
https://api.github.com/user?access_token=xxxxxxxxxxxxxxxxx
public interface BaseOauth {
/**
* 授权地址
*
* @return 授权地址
*/
public String authorize();
/**
* 获取accessToken
*
* @param code 请求编码
* @return accessToken
*/
public String accessToken(String code);
/**
* 获取用户信息
*
* @param accessToken token
* @return user
*/
public String userInfo(String accessToken);
}
@Component
public class GiteeOauth implements BaseOauth {
private static final String GITEE_CLIENT_ID = "1cf84a0dc5cbe7719afe1c16b71dc2475f2612c05bee7557922022d0b5c8";
private static final String GITEE_CLIENT_SECRET = "13bac3e8d348264b3c9d3a1738b4879b34eb2e850489e69f411d34d474";
private static final String REDIRECT_URI = "http://127.0.0.1:8012/gitee/callback";
@Override
public String authorize() {
return "https://gitee.com/oauth/authorize?client_id=" + GITEE_CLIENT_ID + "&response_type=code&redirect_uri=" + REDIRECT_URI;
}
@Override
public String accessToken(String code) {
return "https://gitee.com/oauth/token?grant_type=authorization_code&code=" + code + "&client_id=" + GITEE_CLIENT_ID + "&redirect_uri=" + REDIRECT_URI + "&client_secret=" + GITEE_CLIENT_SECRET;
}
@Override
public String userInfo(String accessToken) {
return "https://gitee.com/api/v5/user?access_token=" + accessToken;
}
}
@Component
public class GithubOauth implements BaseOauth {
private static final String GITHUB_CLIENT_ID = "3d00a49f8121305975c";
private static final String GITHUB_CLIENT_SECRET = "4edd0d1css04100dd57c34cde45c1e21e0521b64b89";
/**
* 登陆授权类型
*/
@Override
public String authorize() {
return "https://github.com/login/oauth/authorize?client_id=" + GITHUB_CLIENT_ID + "&scope=user,public_repo";
}
@Override
public String accessToken(String code) {
return "https://github.com/login/oauth/access_token?client_id=" + GITHUB_CLIENT_ID + "&client_secret=" + GITHUB_CLIENT_SECRET + "&code=" + code;
}
@Override
public String userInfo(String accessToken) {
return "https://api.github.com/user?access_token=" + accessToken + "&scope=public_repo%2Cuser&token_type=bearer";
}
}
public interface BaseOauthService {
String authorizeUri();
String getAccessToken(String code);
JSONObject getUserInfo(String accessToken);
}
@Service
public class GiteeServiceImpl implements BaseOauthService {
@Autowired
GiteeOauth giteeOauth;
@Autowired
RestTemplate restTemplate;
@Override
public String authorizeUri() {
return giteeOauth.authorize();
}
@Override
public String getAccessToken(String code) {
String token = giteeOauth.accessToken(code);
ResponseEntity<Object> entity = restTemplate.postForEntity(token, httpEntity(), Object.class);
Object body = entity.getBody();
assert body != null;
String string = body.toString();
String[] split = string.split("=");
String accessToken = split[1].toString().split(",")[0];
return accessToken;
}
@Override
public JSONObject getUserInfo(String accessToken) {
String userInfo = giteeOauth.userInfo(accessToken);
ResponseEntity<JSONObject> forEntity = restTemplate.exchange(userInfo, HttpMethod.GET, httpEntity(), JSONObject.class);
JSONObject body = forEntity.getBody();
return body;
}
public static HttpEntity httpEntity() {
HttpHeaders headers = new HttpHeaders();
headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
HttpEntity<HttpHeaders> request = new HttpEntity<>(headers);
return request;
}
}
@Service
public class GithubServiceImpl implements BaseOauthService {
@Autowired
GithubOauth githubOauth;
@Autowired
private RestTemplate restTemplate;
@Override
public String authorizeUri() {
return githubOauth.authorize();
}
@Override
public String getAccessToken(String code) {
String token = githubOauth.accessToken(code);
ResponseEntity<Object> forEntity = restTemplate.exchange(token, HttpMethod.GET, httpEntity(), Object.class);
String[] split = Objects.requireNonNull(forEntity.getBody()).toString().split("=");
String accessToken = split[1].split(",")[0];
return accessToken;
}
@Override
public JSONObject getUserInfo(String accessToken) {
String userInfo = githubOauth.userInfo(accessToken);
ResponseEntity<JSONObject> entity = restTemplate.exchange(userInfo, HttpMethod.GET, httpEntity(), JSONObject.class);
JSONObject body = entity.getBody();
return body;
}
}
@Controller
public class IndexController {
@Autowired
private GiteeServiceImpl giteeService;
@Autowired
GithubServiceImpl githubService;
@GetMapping(value = "/")
public String index() {
return "index";
}
@GetMapping(value = "/login")
public String login() {
return "login";
}
@GetMapping(value = "/oauth/login")
public String login(@RequestParam("type") String type) {
if (type.toUpperCase().equals(LoginType.GITHUB.toString())) {
return "redirect:" + githubService.authorizeUri();
}
return "redirect:" + giteeService.authorizeUri();
}
@GetMapping(value = "/github/callback")
public String callback(HttpServletRequest request, Model model) {
String code = request.getParameter("code");
JSONObject userInfo = githubService.getUserInfo(githubService.getAccessToken(code));
UserInfo info = JSON.parseObject(userInfo.toString(), UserInfo.class);
model.addAttribute("github", info);
return "index";
}
@GetMapping(value = "/gitee/callback")
public String giteeCallBack(HttpServletRequest request, Model model) {
String code = request.getParameter("code");
JSONObject userInfo = giteeService.getUserInfo(giteeService.getAccessToken(code));
UserInfo info = JSON.parseObject(userInfo.toString(), UserInfo.class);
model.addAttribute("gitee", info);
return "index";
}
}
@Data
public class UserInfo {
private Integer id;
private String avatarUrl;
private String login;
private String bio;
private String createdAt;
private String htmlUrl;
}
public enum LoginType {
/**
* 登录类型
*/
GITEE,
GITHUB;
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
<style>
.container {
width: 500px;
margin: 0 auto;
}
</style>
</head>
<body>
<div class="container">
<h1> Gitee</h1>
<p th:text="${gitee}"></p>
<h1> GitHub</h1>
<p th:text="${github}"></p>
</div>
</html>
https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/
https://gitee.com/api/v5/oauth_doc#/list_1