Contents
首先
现在很多站点都支持第三方登录功能, 如何实现第三方登录,做以下记录:
首先有一个 GitHub 账号
登录 Github
-
点击 setting
-
点击开发者设置
- 新建一个授权应用
- 填写信息
获取 Client ID 和 Client Secret
后端程序
- 先写一个简单的登录页面
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>
- 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 参数
C 最后一步使用 access_token 获取用户信息
完整代码
基本的 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/