对接第三方登录

一:对接QQ前准备工作:

    1,有已备案的域名;

    2,https://connect.qq.com/登录QQ互联;

    3,创建应用;

              进入应用管理页面创建应用,根据实际需要是创建网站应用还是移动应用,我这里是网站应用:

             

                 

                    

                              

    4,提交完之后会自动提交审核,基本上就是审核你的资料和备案的资料是否一致,所有资料必须和备案资料一模一样,否则            审核不会通过;

二,接口讲解

     Step1:放置QQ登录按钮

            网站需要下载“QQ登录”按钮图片,并按照UI规范将按钮放置在页面合适的位置。

            

  

    Step2:获取Authorization Code

            1. 打开浏览器,访问如下地址(请将client_id,redirect_uri,scope等参数值替换为你自己的):

             https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=[YOUR_APPID]&redirect_uri=                                       [YOUR_REDIRECT_URI]&scope=[THE_SCOPE]

            2. 如果用户已经有登录态,会弹出提示一个确认页。如果还没有登录,会弹出登录页,如下图所示:

            

   Step3:通过Authorization Code获取Access Token

           1.发送请求到如下地址(请将参数值替换为你自己的):

                https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id=[YOUR_APP_ID]&client_secret=                        [YOUR_APP_Key]&code=[The_AUTHORIZATION_CODE]&redirect_uri=[YOUR_REDIRECT_URI]

            2.返值值:

                           access_token=token&expires_in=7776000&refresh_token=A38F7F82618085969038776EA883A990

            3.第三方网站可存储access token信息,以便后续调用OpenAPI访问和修改用户信息时使用。

   Step4:使用Access Token来获取用户的OpenID

           1. 发送请求到如下地址。(请将access_token等参数值替换)

                 https://graph.qq.com/oauth2.0/me?access_token=token

           2.返回值:callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} )

   Step5:使用Access Token以及OpenID来访问和修改用户数据  

           1.发送请求到get_user_info的URL(请将access_token,appid等参数值替换为你自己的):                                                              https://graph.qq.com/user/get_user_info?access_token=token&appid=APP_ID&openid=OPENID

           2.返回值:    

userInfo:{
    "ret": 0,
    "msg": "",
    "is_lost":0,
    "nickname": "不哭死神",
    "gender": "男",
    "province": "香港",
    "city": "九龙城区",
    "year": "2014",
    "constellation": "",
    "figureurl": "http:\/\/qzapp.qlogo.cn\/qzapp\/101728010\/EE5A14DF9DA6707634C34062FB2C586D\/30",
    "figureurl_1": "http:\/\/qzapp.qlogo.cn\/qzapp\/101728010\/EE5A14DF9DA6707634C34062FB2C586D\/50",
    "figureurl_2": "http:\/\/qzapp.qlogo.cn\/qzapp\/101728010\/EE5A14DF9DA6707634C34062FB2C586D\/100",
    "figureurl_qq_1": "http://thirdqq.qlogo.cn/g?b=oidb&k=edBLoLB3PJhcj27OtGFWRw&s=40&t=1557037098",
    "figureurl_qq_2": "http://thirdqq.qlogo.cn/g?b=oidb&k=edBLoLB3PJhcj27OtGFWRw&s=100&t=1557037098",
    "figureurl_qq": "http://thirdqq.qlogo.cn/g?b=oidb&k=edBLoLB3PJhcj27OtGFWRw&s=140&t=1557037098",
    "figureurl_type": "1",
    "is_yellow_vip": "0",
    "vip": "0",
    "yellow_vip_level": "0",
    "level": "0",
    "is_yellow_year_vip": "0"
}

 三:代码实现:

               1,第三方对接接口定义:         

/**
 * 第三方登录顶级接口
 * 
 * @author reyco
 * @date 2019年7月23日
 *
 */
public interface LoginService {
	/**
	 * 登录 ---返回重定向地址
	 * @return
	 */
	String login()throws Exception;
	/**
	 * 回调地址
	 * @param code         登录成功后返回的code
	 * @param request      参数request
	 * @return
	 * @throws Exception
	 */
	String callback(String code,HttpServletRequest request) throws Exception;
}

          2,qq实现:

@Component("qq")
public class QQLoginServiceImpl implements LoginService{
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private RestTemplate restTemplate;
	
	@Override
	public String login() {
		// 回调地址
		String backUrl = PropertiesUtil.getValue("qq.callback");
		// appid
		String qqID = PropertiesUtil.getValue("qq.id");
		String state = UUID.randomUUID().toString().replaceAll("-", "");
		String url = "https://graph.qq.com/oauth2.0/authorize?client_id=" + qqID + "&response_type=code" + "&scope=all"
				+ "&redirect_uri=" + URLEncoder.encode(backUrl) + "&state="+state;
		return url;
	}

	@Override
	public String callback(String code,HttpServletRequest request) throws Exception {
		HttpSession session = request.getSession();
		// 获取token信息
		Map<String, String> map = getAccessToken(code);
		String accessToken = map.get("access_token");
		// 获取appid
		JSONObject openidObj = getAppid(accessToken);
		String appid = openidObj.getString("client_id");
		String openid = openidObj.getString("openid");
		// 获取用户信息
		JSONObject userInfo = getUserInfo(accessToken,appid,openid);
		// 获取登录ip
		String ip = CusAccessObjectUtil.getIpAddress(request); // 获取登录城市
		String cityName = IPDataUtils.getCityName(ip); // 获取登录用户
		String loginPhone = userInfo.getString("nickname");
		User u = new User(3,5,ip, cityName, loginPhone);
		session.setAttribute("user", u);
		return "重定向地址";
	}
	/**
	 * 获取token信息
	 * @param code
	 * @return
	 * @throws Exception
	 */
	private Map<String,String> getAccessToken(String code) throws Exception {
		Map<String,String> map = new HashMap<>();
		String qqID = PropertiesUtil.getValue("qq.id");
		String qqKey = PropertiesUtil.getValue("qq.key");
		String backURL = PropertiesUtil.getValue("qq.callback");
		String get_token_url = "https://graph.qq.com/oauth2.0/token?" + "grant_type=authorization_code" + "&client_id="
				+ qqID + "&client_secret=" + qqKey + "&redirect_uri=" + backURL + "&code=" + code;
		String response = restTemplate.getForObject(get_token_url,String.class);
		logger.info("token:"+response);
		String[] responses =  response.split("&");
		map.put("access_token", getValue(responses,0));
		map.put("expires_in", getValue(responses,1));
		map.put("refresh_token", getValue(responses,2));
		return map;
	}
	private  String getValue(String[] response,Integer index) {
		String values = response[index];
		String[] value = values.split("=");
		return value[1];
	}
	/**
	 * 获取appid
	 * @return
	 * @throws JSONException 
	 */
	private JSONObject getAppid(String token) throws JSONException {
		String get_openid_url = "https://graph.qq.com/oauth2.0/me?access_token="+token;
		String response = restTemplate.getForObject(get_openid_url,String.class);
		logger.info("openId"+response);
		String data = response.substring(response.indexOf("{"), response.indexOf("}")+1);
		JSONObject jsonObject = new JSONObject(data);
		return jsonObject;
	}
	/**
	 * 获取用户信息
	 * @param token
	 * @return
	 * @throws Exception
	 */
	private JSONObject getUserInfo(String token,String appid,String openid) throws Exception {
		String get_userInfo_url = "https://graph.qq.com/user/get_user_info?access_token="+token+"&appid="+appid+"&openid="+openid;
		String response = restTemplate.getForObject(get_userInfo_url,String.class);
		logger.info("userInfo:"+response);
		JSONObject jsonObject = new JSONObject(response);
		return jsonObject;
	}
}

           3.微博实现           

@Component("weibo")
public class WBLoginServiceImpl implements LoginService{
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private RestTemplate restTemplate;
	
	@Override
	public String login() {
		// 回调地址
		String backUrl = PropertiesUtil.getValue("weibo.callback");
		// appid
		String wbId = PropertiesUtil.getValue("weibo.id");
		String state = UUID.randomUUID().toString().replaceAll("-", "");
		String url = "https://api.weibo.com/oauth2/authorize?"
				+ "client_id="+wbId
				+ "&response_type=code"
				+ "&scope=all"
				+ "&display=pc"
				+ "&redirect_uri="+ URLEncoder.encode(backUrl) 
				+ "&state="+state;
		return url;
	}

	@Override
	public String callback(String code,HttpServletRequest request) throws Exception {
		HttpSession session = request.getSession();
		JSONObject accessToken = getAccessToken(code);
		String token = accessToken.getString("access_token");
		JSONObject userInfo = getUserInfo(token);
		// 获取登录ip
		String ip = CusAccessObjectUtil.getIpAddress(request); // 获取登录城市
		String cityName = IPDataUtils.getCityName(ip); // 获取登录用户
		String uid = userInfo.getString("uid");
		User u = new User(3,5,ip, cityName, uid);
		session.setAttribute("user", u);
		return "重定向地址";
	}
	/**
	 * 获取token信息
	 * @param code
	 * @return
	 * @throws Exception
	 */
	private JSONObject getAccessToken(String code) throws Exception {
		String grant_type = "authorization_code";
		String wbId = PropertiesUtil.getValue("weibo.id");
		String wbKey = PropertiesUtil.getValue("weibo.key");
		String backURL = PropertiesUtil.getValue("weibo.callback");
		String get_token_url = PropertiesUtil.getValue("weibo.get_token_url");
		LinkedMultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
		requestEntity.add("grant_type", grant_type);
		requestEntity.add("client_id", wbId);
		requestEntity.add("client_secret", wbKey);
		requestEntity.add("redirect_uri", backURL);
		requestEntity.add("code", code);
		ResponseEntity<String> postForEntity = restTemplate.postForEntity(get_token_url, requestEntity, String.class);
		String body = postForEntity.getBody();
		JSONObject wbTokenObject = new JSONObject(body);
		logger.info("weibo."+wbTokenObject.toString());
		return wbTokenObject;
	}
	/**
	 * 获取用户信息
	 * @param token
	 * @return
	 * @throws Exception
	 */
	private JSONObject getUserInfo(String token) throws Exception {
		String get_userInfo_url = PropertiesUtil.getValue("weibo.get_token_info");
		LinkedMultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
		requestEntity.add("access_token", token);
		ResponseEntity<String> responseEntity = restTemplate.postForEntity(get_userInfo_url, requestEntity, String.class);
		String body = responseEntity.getBody();
		JSONObject wbUserInfoObject = new JSONObject(body);
		logger.info("weibo."+wbUserInfoObject.toString());
		return wbUserInfoObject;
	}
}

          4.百度实现

@Component("baidu")
public class BaiduLoginServiceImpl implements LoginService{
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private RestTemplate restTemplate;
	
	@Override
	public String login() {
		// 回调地址
		String backUrl = PropertiesUtil.getValue("baidu.callback");
		// appid
		String baiduId = PropertiesUtil.getValue("baidu.id");
		// 随机状态
		String state = UUID.randomUUID().toString().replaceAll("-", "");
		String url = "https://openapi.baidu.com/oauth/2.0/authorize?client_id="+ baiduId +"&response_type=code&display=pc"
				+ "&redirect_uri="+URLEncoder.encode(backUrl) + "&state="+state;
		return url;
	}

	@Override
	public String callback(String code,HttpServletRequest request) throws Exception {
		HttpSession session = request.getSession();
		JSONObject accessToken = getAccessToken(code);
		String token = accessToken.getString("access_token");
		JSONObject userInfo = getUserInfo(token);
		// 获取登录ip
		String ip = CusAccessObjectUtil.getIpAddress(request); // 获取登录城市
		String cityName = IPDataUtils.getCityName(ip); // 获取登录用户
		String username = userInfo.getString("username");
		User u = new User(3,5,ip, cityName, username);
		session.setAttribute("user", u);
		return "重定向地址";
	}
	/**
	 * 获取token信息
	 * @param code
	 * @return
	 * @throws Exception
	 */
	private JSONObject getAccessToken(String code) throws Exception {
		String grant_type = "authorization_code";
		String baiduId = PropertiesUtil.getValue("baidu.id");
		String baiduKey = PropertiesUtil.getValue("baidu.key");
		String backURL = PropertiesUtil.getValue("baidu.callback");
		String baiudu_get_token_url = PropertiesUtil.getValue("baidu.get_token_url");
		String get_token_url=baiudu_get_token_url+"?" + "grant_type=authorization_code" + "&client_id="
				+ baiduId + "&client_secret=" + baiduKey + "&redirect_uri=" + backURL + "&code=" + code;;
		 String response = restTemplate.getForObject(get_token_url,String.class);
		JSONObject baiduTokenObject = new JSONObject(response);
		logger.info("baidu"+baiduTokenObject.toString());
		return baiduTokenObject;
	}
	/**
	 * 获取用户信息
	 * @param token
	 * @return
	 * @throws Exception
	 */
	private JSONObject getUserInfo(String token) throws Exception {
		String get_userInfo_url = PropertiesUtil.getValue("baidu.get_token_info");
		LinkedMultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
		requestEntity.add("access_token", token);
		ResponseEntity<String> responseEntity = restTemplate.postForEntity(get_userInfo_url, requestEntity, String.class);
		String body = responseEntity.getBody();
		JSONObject baiduUserInfo = new JSONObject(body);
		logger.info("baidu_userInfo"+baiduUserInfo.toString());
		return baiduUserInfo;
	}
}

          5,登录策略:    

@Component("loginServiceContext")
public class LoginServiceContext {
	
	@Autowired
	private Map<String,LoginService> loginSerivceMap = new HashMap<String,LoginService>();
	
	/**
	 * 重定向地址
	 * @param type
	 * @return
	 * @throws Exception
	 */
	public String login(String type) throws Exception {
		return loginSerivceMap.get(type).login();
	}
	/**
	 * 回调地址
	 * @param type
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public String callback(String code,String type,HttpServletRequest request) throws Exception {
		return loginSerivceMap.get(type).callback(code,request);
	}
}

  6.LoginController.java

              

@RequestMapping("login")
@Controller
public class LoginController {
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired 
	private LoginServiceContext loginServiceContext;
	
	@RequestMapping("login")
	public String login(String type) throws Exception {
		String redirectUrl = loginServiceContext.login(type);
		logger.info(redirectUrl);
		return "redirect:"+redirectUrl;
		
	}
	@RequestMapping("callback")
	public String callback(HttpServletRequest request,HttpServletResponse response,String code,String type) throws Exception {
		HttpSession session = request.getSession();
		User user = (User)session.getAttribute("user");
		if (null != user) {
			return "redirect:你的重定向地址";
		}
		String callback = loginServiceContext.callback(code,type, request);
		return "redirect:"+callback;
	}
	
}

      7,html代码:

<div><a href="../login/login.do?type=qq"><img src="../imags/qq.png"/></a></div>
<div><a href="../login/login.do?type=baidu"><img src="../imags/baidu.png"/></a></div>
<div><a href="../login/login.do?type=weibo"><img src="../imags/wb.png"/></a></div>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java的艺术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值