github 和gitee 第三方登录 实现过程

首先

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

登录Github

  • 点击 setting

github 和gitee 第三方登录 实现过程_第1张图片

  • 点击开发者设置
    github 和gitee 第三方登录 实现过程_第2张图片
  • 新建一个授权应用
    github 和gitee 第三方登录 实现过程_第3张图片
  • 填写信息

github 和gitee 第三方登录 实现过程_第4张图片

获取Client ID和Client Secret

github 和gitee 第三方登录 实现过程_第5张图片

后端程序

  1. 先写一个简单的登录页面
<!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>
  1. controller 页面跳转
    @GetMapping(value = "/login")
    public String login() {
        return "login";
    }

github 和gitee 第三方登录 实现过程_第6张图片

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

完整代码

github 和gitee 第三方登录 实现过程_第7张图片

基本的Oauth

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);
}

GiteeOauth实现

@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;
    }
}

GithubOauth实现

@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";
    }
}

BaseOauthService

public interface BaseOauthService {
    String authorizeUri();

    String getAccessToken(String code);

    JSONObject getUserInfo(String accessToken);

}

GiteeOauthService

@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;
    }
}

GithubOauthService

@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

@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";
    }
}

UserInfo

@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>

github 和gitee 第三方登录 实现过程_第8张图片
github 和gitee 第三方登录 实现过程_第9张图片
参考文档:

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

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

你可能感兴趣的:(java)