├── pom.xml
├── readme.md
└── src
└── main
├── java
└── org
│ └── yangjie
│ ├── Application.java
│ ├── config
│ └── WebMvcConfig.java
│ ├── controller
│ ├── QQController.java
│ └── WeiboController.java
│ ├── service
│ ├── QQService.java
│ └── WeiboService.java
│ └── util
│ ├── HttpUtil.java
│ └── JsonUtil.java
├── resources
└── application.yml
└── webapp
├── index.html
└── my.html
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | org.java.util
6 | java_oauth
7 | 0.0.1-SNAPSHOT
8 | war
9 |
10 | java_oauth
11 | http://maven.apache.org
12 |
13 |
14 | cc.moko.weixin.Application
15 | UTF-8
16 |
17 |
18 |
19 | org.springframework.boot
20 | spring-boot-starter-parent
21 | 1.4.2.RELEASE
22 |
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-web
28 |
29 |
30 | com.squareup.okhttp3
31 | okhttp
32 | 3.2.0
33 |
34 |
35 |
36 |
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-maven-plugin
41 |
42 |
43 | org.apache.maven.plugins
44 | maven-compiler-plugin
45 |
46 | 1.8
47 | 1.8
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | #### java 实现第三方登录
2 |
3 | * QQ
4 |
5 | * 微博
--------------------------------------------------------------------------------
/src/main/java/org/yangjie/Application.java:
--------------------------------------------------------------------------------
1 | package org.yangjie;
2 |
3 |
4 | import org.apache.log4j.Logger;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 |
8 | /**
9 | * 程序入口, 启动器
10 | * @author YangJie [2015年11月4日 下午1:28:33]
11 | */
12 | @SpringBootApplication
13 | public class Application {
14 |
15 | private static Logger logger = Logger.getLogger(Application.class);
16 |
17 | public static void main(String[] args) {
18 | SpringApplication.run(Application.class, args);
19 | logger.info("server is running...");
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/yangjie/config/WebMvcConfig.java:
--------------------------------------------------------------------------------
1 | package org.yangjie.config;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
6 |
7 | /**
8 | * web mvc 配置类
9 | * @author YangJie [2015年11月4日 下午1:30:08]
10 | */
11 | @Configuration
12 | public class WebMvcConfig extends WebMvcConfigurerAdapter {
13 |
14 | @Override // 默认首页
15 | public void addViewControllers(ViewControllerRegistry registry) {
16 | registry.addViewController("/").setViewName("/login.html");
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/org/yangjie/controller/QQController.java:
--------------------------------------------------------------------------------
1 | package org.yangjie.controller;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.web.bind.annotation.RequestMapping;
6 | import org.springframework.web.bind.annotation.RequestMethod;
7 | import org.yangjie.service.QQService;
8 |
9 | /**
10 | * QQ登录
11 | * @author YangJie [2017年2月23日 下午3:54:16]
12 | */
13 | @Controller
14 | @RequestMapping("qq")
15 | public class QQController{
16 |
17 | @Autowired
18 | private QQService qqService;
19 |
20 |
21 | /**
22 | * 登录发起
23 | * @author YangJie [2017年2月22日 下午6:28:49]
24 | * @return
25 | */
26 | @RequestMapping(value="/auth", method=RequestMethod.GET)
27 | public String auth() {
28 | String url = new StringBuilder(QQService.AUTH_URL)
29 | .append("?client_id=").append(QQService.APPID)
30 | .append("&redirect_uri=").append(QQService.CALLBACK_URL)
31 | .append("&response_type=code&state=moko").toString();
32 | return "redirect:" + url;
33 | }
34 |
35 | /**
36 | * 登录授权回调
37 | * @author YangJie [2017年2月22日 下午6:28:49]
38 | * @param code
39 | * @param state
40 | * @return
41 | */
42 | @RequestMapping(value="/callback", method=RequestMethod.GET)
43 | public String callback(String code, String state) {
44 | String token = qqService.getToken(code);
45 | String openid = qqService.getOpenid(token);
46 | // 执行登录过程, 然后调整到个人首页
47 | return "redirect:/my.html?"+openid;
48 | }
49 |
50 | }
--------------------------------------------------------------------------------
/src/main/java/org/yangjie/controller/WeiboController.java:
--------------------------------------------------------------------------------
1 | package org.yangjie.controller;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.web.bind.annotation.RequestMapping;
6 | import org.springframework.web.bind.annotation.RequestMethod;
7 | import org.yangjie.service.WeiboService;
8 |
9 | /**
10 | * 微博登录
11 | * @author YangJie [2017年2月23日 下午3:54:01]
12 | */
13 | @Controller
14 | @RequestMapping("weibo")
15 | public class WeiboController{
16 |
17 | @Autowired
18 | private WeiboService weiboService;
19 |
20 |
21 | /**
22 | * 登录发起
23 | * @author YangJie [2017年2月22日 下午6:28:49]
24 | * @return
25 | */
26 | @RequestMapping(value="/auth", method=RequestMethod.GET)
27 | public String auth() {
28 | String url = new StringBuilder(WeiboService.AUTH_URL)
29 | .append("?client_id=").append(WeiboService.APPID)
30 | .append("&redirect_uri=").append(WeiboService.CALLBACK_URL)
31 | .append("&state=moko").toString();
32 | return "redirect:" + url;
33 | }
34 |
35 | /**
36 | * 登录授权回调
37 | * @author YangJie [2017年2月22日 下午6:28:49]
38 | * @param code
39 | * @param state
40 | * @return
41 | */
42 | @RequestMapping(value="/callback", method=RequestMethod.GET)
43 | public String callback(String code, String state) {
44 | String uid = weiboService.getUid(code);
45 | // 执行登录过程, 然后调整到个人首页
46 | return "redirect:/my.html?"+uid;
47 | }
48 |
49 | }
--------------------------------------------------------------------------------
/src/main/java/org/yangjie/service/QQService.java:
--------------------------------------------------------------------------------
1 | package org.yangjie.service;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | import org.springframework.stereotype.Service;
7 | import org.yangjie.util.HttpUtil;
8 | import org.yangjie.util.JsonUtil;
9 |
10 | /**
11 | * QQ登录
12 | * @author YangJie [2017年2月23日 下午2:47:29]
13 | */
14 | @Service
15 | public class QQService{
16 |
17 | public static String APPID = "";
18 | public static String SECRET = "";
19 | public static String CALLBACK_URL = "http:///qq/callback";
20 |
21 | // 发起授权地址
22 | public static String AUTH_URL = "https://graph.qq.com/oauth2.0/authorize";
23 | // 获取token地址
24 | public static String TOKEN_URL = "https://graph.qq.com/oauth2.0/token";
25 | // 获取授权信息地址
26 | public static String ME_URL = "https://graph.qq.com/oauth2.0/me";
27 | // 获取用户信息地址
28 | public static String INFO_URL = "https://graph.qq.com/user/get_user_info";
29 |
30 |
31 | /**
32 | * 获取token
33 | * @author YangJie [2017年2月22日 下午6:28:49]
34 | * @param code
35 | * @return
36 | */
37 | public String getToken(String code) {
38 | String url = new StringBuilder(TOKEN_URL)
39 | .append("?client_id=").append(APPID)
40 | .append("&client_secret=").append(SECRET)
41 | .append("&grant_type=").append("authorization_code")
42 | .append("&redirect_uri=").append(CALLBACK_URL)
43 | .append("&code=").append(code).toString();
44 | String result = HttpUtil.get(url);
45 | // access_token=x&expires_in=x&refresh_token=x
46 | return result.split("&")[0].split("=")[1];
47 | }
48 |
49 | /**
50 | * 获取openid
51 | * @author YangJie [2017年2月22日 下午6:28:49]
52 | * @param token
53 | * @return
54 | */
55 | public String getOpenid(String token) {
56 | String url = new StringBuilder(ME_URL)
57 | .append("?access_token=").append(token).toString();
58 | // 如果申请过多应用联合, 可以通过添加参数&unionid=1获取
59 | String result = HttpUtil.get(url);
60 | // callback( {"client_id":"x","openid":"x"} );
61 | return result.split("\"")[7];
62 | }
63 |
64 |
65 | /**
66 | * 获取用户信息
67 | * @author YangJie [2017年2月22日 下午6:28:49]
68 | * @param openid
69 | * @param token
70 | * @return http://wiki.connect.qq.com/get_user_info
71 | */
72 | public Map getInfo(String openid, String token) {
73 | String url = new StringBuilder(INFO_URL)
74 | .append("?oauth_consumer_key=").append(APPID)
75 | .append("&openid=").append(openid)
76 | .append("&access_token=").append(token).toString();
77 | String result = HttpUtil.get(url);
78 | return JsonUtil.toObject(result, HashMap.class, Map.class, String.class, String.class);
79 | }
80 |
81 | }
--------------------------------------------------------------------------------
/src/main/java/org/yangjie/service/WeiboService.java:
--------------------------------------------------------------------------------
1 | package org.yangjie.service;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | import org.springframework.stereotype.Service;
7 | import org.yangjie.util.HttpUtil;
8 | import org.yangjie.util.JsonUtil;
9 |
10 | /**
11 | * 微博登录
12 | * @author YangJie [2017年2月23日 下午2:47:29]
13 | */
14 | @Service
15 | public class WeiboService{
16 |
17 | public static String APPID = "";
18 | public static String SECRET = "";
19 | public static String CALLBACK_URL = "http:///weibo/callback";
20 |
21 | // 发起授权地址
22 | public static String AUTH_URL = "https://api.weibo.com/oauth2/authorize";
23 | // 获取token地址
24 | public static String TOKEN_URL = "https://api.weibo.com/oauth2/access_token";
25 | // 获取用户信息地址
26 | public static String INFO_URL = "https://api.weibo.com/2/users/show.json";
27 |
28 |
29 | /**
30 | * 获取uid
31 | * @author YangJie [2017年2月22日 下午6:28:49]
32 | * @param code
33 | * @return
34 | */
35 | public String getUid(String code) {
36 | Map formMap = new HashMap();
37 | formMap.put("client_id", APPID);
38 | formMap.put("client_secret", SECRET);
39 | formMap.put("grant_type", "authorization_code");
40 | formMap.put("redirect_uri", CALLBACK_URL);
41 | formMap.put("code", code);
42 | String result = HttpUtil.post(TOKEN_URL, formMap);
43 | // {"access_token": "ACCESS_TOKEN","expires_in": 1234,"remind_in":"798114","uid":"12341234"}
44 | Map resultMap = JsonUtil.toObject(result, HashMap.class, Map.class, String.class, String.class);
45 | return resultMap.get("uid");
46 | }
47 |
48 | /**
49 | * 获取用户信息
50 | * @author YangJie [2017年2月22日 下午6:28:49]
51 | * @param uid
52 | * @param token
53 | * @return http://open.weibo.com/wiki/2/users/show
54 | */
55 | public Map getInfo(String uid, String token) {
56 | String url = new StringBuilder(INFO_URL)
57 | .append("?access_token=").append(token)
58 | .append("&uid=").append(uid).toString();
59 | String result = HttpUtil.get(url);
60 | return JsonUtil.toObject(result, HashMap.class, Map.class, String.class, String.class);
61 | }
62 |
63 | }
--------------------------------------------------------------------------------
/src/main/java/org/yangjie/util/HttpUtil.java:
--------------------------------------------------------------------------------
1 | package org.yangjie.util;
2 |
3 | import java.io.IOException;
4 | import java.util.Map;
5 |
6 | import okhttp3.FormBody;
7 | import okhttp3.MediaType;
8 | import okhttp3.OkHttpClient;
9 | import okhttp3.Request;
10 | import okhttp3.RequestBody;
11 |
12 | /**
13 | * HTTP工具类
14 | * @author YangJie [2016年5月24日 下午6:15:41]
15 | */
16 | public class HttpUtil {
17 |
18 | private static final OkHttpClient client = new OkHttpClient();
19 |
20 | private static final MediaType jsonMediaType = MediaType.parse("application/json; charset=utf-8");
21 | private static final MediaType xmlMediaType = MediaType.parse("application/xml; charset=utf-8");
22 |
23 |
24 |
25 | /**
26 | * execute
27 | * @param request
28 | * @return
29 | */
30 | public static String execute(Request request){
31 | try {
32 | return client.newCall(request).execute().body().string();
33 | } catch (IOException e) {
34 | e.printStackTrace();
35 | }
36 | return null;
37 | }
38 |
39 | /**
40 | * get
41 | * @param url
42 | * @return
43 | * @throws Exception
44 | */
45 | public static String get(String url) {
46 | return execute(new Request.Builder().url(url).get().build());
47 | }
48 |
49 | /**
50 | * post
51 | * @param url
52 | * @param body
53 | * @return
54 | */
55 | public static String post(String url, RequestBody body){
56 | return execute(new Request.Builder().url(url).post(body).build());
57 | }
58 |
59 | /**
60 | * post
61 | * @param url
62 | * @param formMap
63 | * @return
64 | */
65 | public static String post(String url, Map formMap){
66 | FormBody.Builder form = new FormBody.Builder();
67 | if (formMap!=null && !formMap.isEmpty()) {
68 | for(String key : formMap.keySet()){
69 | form.add(key, formMap.get(key));
70 | }
71 | return post(url, form.build());
72 | }
73 | return null;
74 | }
75 |
76 | /**
77 | * post
78 | * @param url
79 | * @param body
80 | * @param mediaType
81 | * @return
82 | */
83 | public static String post(String url, String body, MediaType mediaType) {
84 | return post(url, RequestBody.create(mediaType, body));
85 | }
86 |
87 | /**
88 | * post (json)
89 | * @param url
90 | * @return
91 | */
92 | public static String postJson(String url, String body) {
93 | return post(url, body, jsonMediaType);
94 | }
95 |
96 | /**
97 | * post (xml)
98 | * @param url
99 | * @param body
100 | * @return
101 | */
102 | public static String postXml(String url, String body) {
103 | return post(url, body, xmlMediaType);
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/org/yangjie/util/JsonUtil.java:
--------------------------------------------------------------------------------
1 | package org.yangjie.util;
2 |
3 | import com.fasterxml.jackson.core.JsonProcessingException;
4 | import com.fasterxml.jackson.databind.DeserializationFeature;
5 | import com.fasterxml.jackson.databind.ObjectMapper;
6 |
7 | public class JsonUtil {
8 |
9 | public static ObjectMapper objectMapper = new ObjectMapper()
10 | .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 忽略未知属性
11 |
12 | /**
13 | * 将对象转换成json字符串
14 | * @param object
15 | * @return
16 | * @throws Exception
17 | */
18 | public static String toJson(Object object) {
19 | try {
20 | return objectMapper.writeValueAsString(object);
21 | } catch (JsonProcessingException e) {
22 | e.printStackTrace();
23 | }
24 | return null;
25 | }
26 |
27 | /**
28 | * 将json字符串转换成对象
29 | * @param json
30 | * @param valueType
31 | * @return
32 | * @throws Exception
33 | */
34 | public static T toObject(String json, Class valueType) {
35 | try {
36 | return objectMapper.readValue(json, valueType);
37 | } catch (Exception e) {
38 | e.printStackTrace();
39 | }
40 | return null;
41 | }
42 |
43 | /**
44 | * json转对象(处理复杂类型对象)
45 | * List : json, ArrayList.class, List.class, Bean.class
46 | * Map : json, HashMap.class, Map.class, Bean1.class, Bean2.class
47 | * @param json
48 | * @param parametrized 要转换的真实类型
49 | * @param parametersFor 要转换类型的类或接口
50 | * @param parameterClasses 类型中的泛型类型
51 | * @return
52 | * @throws Exception
53 | */
54 | public static T toObject(String json, Class> parametrized, Class> parametersFor, Class>... parameterClasses) {
55 | try {
56 | return objectMapper.readValue(json, objectMapper.getTypeFactory().constructParametrizedType(parametrized, parametersFor, parameterClasses));
57 | } catch (Exception e) {
58 | e.printStackTrace();
59 | }
60 | return null;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 80
--------------------------------------------------------------------------------
/src/main/webapp/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 第三方登录
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/main/webapp/my.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | index
6 |
7 |
8 |
9 | index
10 |
11 |
12 |
--------------------------------------------------------------------------------