基于Dubbox的微服实战5——实现分布式下的微信登录

目录

auth协议介绍
微信登录接入流程
编码实现步骤介绍
请求获取code
使用code获取授权票据access_token

使用access_token获取用户信息

auth协议介绍

OAUTH(Open Authorization,开放授权)协议为用户资源的授权提供了一个安全,开发而又简易的标准。与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的账号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权。并且这是安全的。


基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统


1.用户点击“微信登录”的图标,请求使用微信登录

2.第三方应用,请求微信开放平台,获取code,传参中就有回调url。

3.用户确认登录第三方应用,微信开放平台回调第三方应用的url,带上code

4.第三方应用拿到code,再带上appid,appsecrect等等参数,继续请求微信开放平台,获取access_token(授权票据)

5.微信开放平台会将access_token返回给第三方应用。

6.第三方应用拿到access_token,获取用户信息。

接入条件(微信开放平台)

注入开发者账号

拥有一个已审核通过的网站应用。


微信登录接入流程


编码实现步骤介绍

文档地址:

https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN

第一步:请求CODE

请求地址

https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

返回CODE

redirect_uri?code=CODE&state=STATE

第二步:通过code获取access_token

获取access_token

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
返回JSON
{ 
"access_token":"ACCESS_TOKEN", 
"expires_in":7200, 
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID", 
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

错误的

{"errcode":40029,"errmsg":"invalid code"}

第三步:通过access_token调用接口

获取用户个人信息

http://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID

返回JSON

第四步:实现网站自身业务

保存session

设置token



请求获取code


使用code获取授权票据access_token


使用access_token获取用户信息


测试和总结

后台代码:

package cn.bdqn.controller;

import cn.bdqn.common.Dto;
import cn.bdqn.common.DtoUtil;
import cn.bdqn.common.IdWorker;
import cn.bdqn.common.UrlUtils;
import cn.bdqn.pojo.QgUser;
import cn.bdqn.service.QgLoginService;
import com.alibaba.fastjson.JSON;
import org.apache.log4j.spi.ErrorCode;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

/**
 * 第三方登录控制器
 * @author hduser
 *
 */
@Controller
@RequestMapping(value = "/vendors")
public class VendorsController {

	@Resource
	private QgLoginService qgLoginService;

	/**
	 * 微信登录——第一步:获取code
	 * @param response
	 */
	@RequestMapping(value = "/wechat/login")
	public void wechatLogin(HttpServletResponse response){
		String qrconnect="https://open.weixin.qq.com/connect/qrconnect?appid=wx9168f76f000a0d4c&redirect_uri=http%3a%2f%2fj19h691179.iok.la%3a27105%2fvendors%2fwechat%2fcallback&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect";
		try {
			response.sendRedirect(qrconnect);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * 微信登录——第二步:通过code换取access_token
	 * @param code
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping(value = "/wechat/callback")
	public void wechatCallback(@RequestParam String code, HttpServletRequest request, HttpServletResponse response) throws IOException{
		String accessTokenUrl="https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx9168f76f000a0d4c&secret=8ba69d5639242c3bd3a69dffe84336c1&code="+
				code+"&grant_type=authorization_code";	
		response.setContentType("text/html;charset=utf-8");
		String json= UrlUtils.loadURL(accessTokenUrl);
		Map<String,Object> wechatToken=JSON.parseObject(json, Map.class);
		
		try {
			//验证本地库是否存在该用户
			QgUser user=qgLoginService.findByWxUserId(wechatToken.get("openid").toString());
			if(user==null){//如果不存在则添加用户
                user = new QgUser();
                user.setWxUserId(wechatToken.get("openid").toString());
                String id = IdWorker.getId();
                user.setId(id);
                qgLoginService.createQgUser(wechatToken.get("openid").toString(), id);
			}
			String token = qgLoginService.generateToken(user);
            qgLoginService.save(token, user);
			//返回前端处理
			StringBuilder loginPage=new StringBuilder();
			loginPage.append("http://j19h691179.iok.la:15614/index.html");
			loginPage.append("?user_type=1&token="+token);
			loginPage.append("&access_token="+wechatToken.get("access_token").toString());
			loginPage.append("&expires_in="+wechatToken.get("expires_in").toString());
			loginPage.append("&refresh_token="+wechatToken.get("refresh_token").toString());
			loginPage.append("&openid="+wechatToken.get("openid").toString());
			response.sendRedirect(loginPage.toString());
			
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		
	}
	/**
	 * 获取微信用户信息
	 * @param accessToken 微信会话凭据
	 * @param openid 微信用户唯一标识
	 * @return
	 */
	@RequestMapping(value = "/wechat/user/info", method = RequestMethod.GET,produces= "application/json")
	public @ResponseBody
    Dto wechatUserInfo(
			@RequestParam String accessToken,
			@RequestParam String openid){
		try {
			//加载用户信息
			String userInfoJson=UrlUtils.loadURL("https://api.weixin.qq.com/sns/userinfo?access_token="
					+accessToken
					+"&openid="+ openid
					);
			Map<String,Object> userInfo=JSON.parseObject(userInfoJson, Map.class);
			return DtoUtil.returnDataSuccess(userInfo);
		} catch (Exception e) {			
			e.printStackTrace();
			return DtoUtil.returnFail(e.getMessage(), "授权失败");
		}
	}
	/**
	 * 会话保持
	 * 1、保持和itrip的会话
	 * 2、保持和wechat的会话
	 * @return
	 */
//	@RequestMapping(value = "/wechat/token/refresh", method = RequestMethod.POST,produces= "application/json")
//	public @ResponseBody
//    Dto wechatRefreshToken(HttpServletRequest request, HttpServletResponse response){
//
//		String agent=request.getHeader("user-agent");
//		String token=request.getHeader("token");
//		String refreshToken=request.getHeader("refreshtoken");//此处header中的名称使用“_”不能获取
//
//		try {
//			//2、保持和wechat的会话
//			String refreshTokenUrl="https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=wx9168f76f000a0d4c&grant_type=refresh_token&refresh_token="+refreshToken.trim();
//
//			String json=UrlUtils.loadURL(refreshTokenUrl);
//			Map<String,Object> wechatToken=JSON.parseObject(json, Map.class);
//			if(null!=wechatToken.get("errcode")){
//				return DtoUtil.returnFail(wechatToken.get("errmsg").toString(), "置换token失败");
//			}
//
//			//返回ItripWechatTokenVO (整合了本地会话与微信会话)
//			ItripWechatTokenVO wechatTokenVO=new ItripWechatTokenVO(token,
//					Calendar.getInstance().getTimeInMillis()+TokenService.SESSION_TIMEOUT*1000,//2h有效期
//					Calendar.getInstance().getTimeInMillis());
//			wechatTokenVO.setAccessToken(wechatToken.get("access_token").toString());
//			wechatTokenVO.setExpiresIn(wechatToken.get("expires_in").toString());
//			wechatTokenVO.setRefreshToken(wechatToken.get("refresh_token").toString());
//			wechatTokenVO.setOpenid(wechatToken.get("openid").toString());
//			return DtoUtil.returnDataSuccess(wechatTokenVO);
//
//		} catch (Exception e) {
//			e.printStackTrace();
//			return DtoUtil.returnFail(e.getMessage(), ErrorCode.AUTH_REPLACEMENT_FAILED);
//		}
//
//	}
}


打开地址http://<ip>:<port>/vendors/wechat/login,就进入一个有二维码的页面,扫描二维码,就进入redirect_uri的页面,也就是http://<ip>:<port>/vendors/wechat/callback。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值