Contents

首先

现在很多站点都支持第三方登录功能, 如何实现第三方登录,做以下记录:
首先有一个 GitHub 账号

登录 Github

  • 点击 setting

  • 点击开发者设置

  • 新建一个授权应用

  • 填写信息

获取 Client ID 和 Client Secret

后端程序

  1. 先写一个简单的登录页面
 1<!DOCTYPE html>
 2<html lang="en" xmlns:th="http://www.thymeleaf.org">
 3<head>
 4    <meta charset="UTF-8">
 5    <title>登录</title>
 6</head>
 7<body>
 8<form method="get" action="/oauth/login">
 9    <input type="submit" th:name="type" th:value="github">
10    <input type="submit" th:name="type" th:value="gitee"/>
11</form>
12</body>
13</html>
  1. controller 页面跳转
1    @GetMapping(value = "/login")
2    public String login() {
3        return "login";
4    }

A 点击登录

会重定向到 github 的登录授权页面;地址如下:

https://github.com/login/oauth/authorize?client_id=xxxxxxxxxxxxxxxxxx&scope=user,public_repo

授权结束

地址跳转到回掉地址,并携带一个 code 参数

http://localhost:8080/login?code=xxxxxxxxxxxxxxxxxxxx

B 获取用户的 access_token 用户标识

需要传入 client_id,client_secret 以及 上一步回调得到的 code 参数

https://github.com/login/oauth/access_token?client_id=xxxxxxxxxxxxxxxxxxx&client_secret=xxxxxxxxxxxxxxxxx&code=xxxxxxxxxxxxxxxxxxx

C 最后一步使用 access_token 获取用户信息

https://api.github.com/user?access_token=xxxxxxxxxxxxxxxxx

完整代码

基本的 Oauth

 1public interface BaseOauth {
 2
 3    /**
 4     * 授权地址
 5     *
 6     * @return 授权地址
 7     */
 8    public String authorize();
 9
10    /**
11     * 获取accessToken
12     *
13     * @param code 请求编码
14     * @return accessToken
15     */
16    public String accessToken(String code);
17
18    /**
19     * 获取用户信息
20     *
21     * @param accessToken token
22     * @return user
23     */
24    public String userInfo(String accessToken);
25}
26

GiteeOauth 实现

 1@Component
 2public class GiteeOauth implements BaseOauth {
 3
 4    private static final String GITEE_CLIENT_ID = "1cf84a0dc5cbe7719afe1c16b71dc2475f2612c05bee7557922022d0b5c8";
 5    private static final String GITEE_CLIENT_SECRET = "13bac3e8d348264b3c9d3a1738b4879b34eb2e850489e69f411d34d474";
 6
 7    private static final String REDIRECT_URI = "http://127.0.0.1:8012/gitee/callback";
 8
 9    @Override
10    public String authorize() {
11        return "https://gitee.com/oauth/authorize?client_id=" + GITEE_CLIENT_ID + "&response_type=code&redirect_uri=" + REDIRECT_URI;
12    }
13
14    @Override
15    public String accessToken(String code) {
16        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;
17    }
18
19    @Override
20    public String userInfo(String accessToken) {
21        return "https://gitee.com/api/v5/user?access_token=" + accessToken;
22    }
23}
24

GithubOauth 实现

 1@Component
 2public class GithubOauth implements BaseOauth {
 3
 4    private static final String GITHUB_CLIENT_ID = "3d00a49f8121305975c";
 5    private static final String GITHUB_CLIENT_SECRET = "4edd0d1css04100dd57c34cde45c1e21e0521b64b89";
 6
 7    /**
 8     * 登陆授权类型
 9     */
10    @Override
11    public String authorize() {
12        return "https://github.com/login/oauth/authorize?client_id=" + GITHUB_CLIENT_ID + "&scope=user,public_repo";
13    }
14
15    @Override
16    public String accessToken(String code) {
17        return "https://github.com/login/oauth/access_token?client_id=" + GITHUB_CLIENT_ID + "&client_secret=" + GITHUB_CLIENT_SECRET + "&code=" + code;
18    }
19
20    @Override
21    public String userInfo(String accessToken) {
22        return "https://api.github.com/user?access_token=" + accessToken + "&scope=public_repo%2Cuser&token_type=bearer";
23    }
24}

BaseOauthService

1public interface BaseOauthService {
2    String authorizeUri();
3
4    String getAccessToken(String code);
5
6    JSONObject getUserInfo(String accessToken);
7
8}

GiteeOauthService

 1@Service
 2public class GiteeServiceImpl implements BaseOauthService {
 3
 4    @Autowired
 5    GiteeOauth giteeOauth;
 6
 7    @Autowired
 8    RestTemplate restTemplate;
 9
10    @Override
11    public String authorizeUri() {
12        return giteeOauth.authorize();
13    }
14
15    @Override
16    public String getAccessToken(String code) {
17        String token = giteeOauth.accessToken(code);
18        ResponseEntity<Object> entity = restTemplate.postForEntity(token, httpEntity(), Object.class);
19        Object body = entity.getBody();
20        assert body != null;
21        String string = body.toString();
22        String[] split = string.split("=");
23        String accessToken = split[1].toString().split(",")[0];
24        return accessToken;
25    }
26
27    @Override
28    public JSONObject getUserInfo(String accessToken) {
29        String userInfo = giteeOauth.userInfo(accessToken);
30        ResponseEntity<JSONObject> forEntity = restTemplate.exchange(userInfo, HttpMethod.GET, httpEntity(), JSONObject.class);
31        JSONObject body = forEntity.getBody();
32        return body;
33    }
34
35    public static HttpEntity httpEntity() {
36        HttpHeaders headers = new HttpHeaders();
37        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");
38
39        HttpEntity<HttpHeaders> request = new HttpEntity<>(headers);
40        return request;
41    }
42}
43

GithubOauthService

 1@Service
 2public class GithubServiceImpl implements BaseOauthService {
 3    @Autowired
 4    GithubOauth githubOauth;
 5    @Autowired
 6    private RestTemplate restTemplate;
 7
 8    @Override
 9    public String authorizeUri() {
10        return githubOauth.authorize();
11    }
12
13    @Override
14    public String getAccessToken(String code) {
15        String token = githubOauth.accessToken(code);
16        ResponseEntity<Object> forEntity = restTemplate.exchange(token, HttpMethod.GET, httpEntity(), Object.class);
17        String[] split = Objects.requireNonNull(forEntity.getBody()).toString().split("=");
18        String accessToken = split[1].split(",")[0];
19        return accessToken;
20    }
21
22    @Override
23    public JSONObject getUserInfo(String accessToken) {
24        String userInfo = githubOauth.userInfo(accessToken);
25        ResponseEntity<JSONObject> entity = restTemplate.exchange(userInfo, HttpMethod.GET, httpEntity(), JSONObject.class);
26        JSONObject body = entity.getBody();
27        return body;
28    }
29}

Controller

 1@Controller
 2public class IndexController {
 3
 4    @Autowired
 5    private GiteeServiceImpl giteeService;
 6
 7    @Autowired
 8    GithubServiceImpl githubService;
 9
10
11    @GetMapping(value = "/")
12    public String index() {
13        return "index";
14    }
15
16    @GetMapping(value = "/login")
17    public String login() {
18        return "login";
19    }
20
21
22    @GetMapping(value = "/oauth/login")
23    public String login(@RequestParam("type") String type) {
24        if (type.toUpperCase().equals(LoginType.GITHUB.toString())) {
25            return "redirect:" + githubService.authorizeUri();
26        }
27        return "redirect:" + giteeService.authorizeUri();
28    }
29
30    @GetMapping(value = "/github/callback")
31    public String callback(HttpServletRequest request, Model model) {
32        String code = request.getParameter("code");
33        JSONObject userInfo = githubService.getUserInfo(githubService.getAccessToken(code));
34        UserInfo info = JSON.parseObject(userInfo.toString(), UserInfo.class);
35        model.addAttribute("github", info);
36        return "index";
37    }
38
39    @GetMapping(value = "/gitee/callback")
40    public String giteeCallBack(HttpServletRequest request, Model model) {
41        String code = request.getParameter("code");
42        JSONObject userInfo = giteeService.getUserInfo(giteeService.getAccessToken(code));
43        UserInfo info = JSON.parseObject(userInfo.toString(), UserInfo.class);
44        model.addAttribute("gitee", info);
45        return "index";
46    }
47}

UserInfo

 1@Data
 2public class UserInfo {
 3    private Integer id;
 4    private String avatarUrl;
 5    private String login;
 6    private String bio;
 7    private String createdAt;
 8    private String htmlUrl;
 9}
10
1public enum LoginType {
2    /**
3     * 登录类型
4     */
5    GITEE,
6    GITHUB;
7}
8

显示用户信息

 1<!DOCTYPE html>
 2<html lang="en" xmlns:th="http://www.thymeleaf.org">
 3<head>
 4    <meta charset="UTF-8">
 5    <title>首页</title>
 6    <style>
 7        .container {
 8            width: 500px;
 9            margin: 0 auto;
10        }
11    </style>
12</head>
13<body>
14<div class="container">
15    <h1> Gitee</h1>
16    <p th:text="${gitee}"></p>
17
18    <h1> GitHub</h1>
19    <p th:text="${github}"></p>
20</div>
21</html>

参考文档:

https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/

https://gitee.com/api/v5/oauth_doc#/list_1