欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

微信扫描公众号二维码实现登陆

程序员文章站 2022-07-14 08:55:03
...
前提条件:
1.微信公众平台为服务号,
2.服务号实现了账号绑定功能,即将open_id 与业务系统中的用户名有对应关系


具体实现原理:
1.用户访问业务系统登陆页时,调用二维码接口,获得二维码的ticketid,同时将sessionid,ticketid和二维码的seceneid保存
2.返回登陆页时,根据ticketid获得微信二维码
3.页面通过ajax发送请求,判断是否已经扫描成功。
4.公众平台服务监测到扫描事件,更新seceneid中扫描二维码的业务系统用户名
4.当ajax监测到扫描成功,并返回有业务系统用户名,即可做模拟登陆!

具体代码:
根据sceneID获取,获取ticketId,
sceneId可以为sessionID,或者自定义的其他任何值,但必须保证不重复
注意:这里请求的type可以为临时二维码或永久二维码,具体区别可以参看微信公众平台的开发者文档。
public static String getSceneTicket(String type,String sceneId){
		WxScene scene = new WxScene();
		scene.setAction_name(type);
		scene.setSceneId(Integer.parseInt(sceneId));
		scene.setExpire_seconds(1800);
		String jsonScene = JSONObject.fromObject(scene).toString();
		String url = WeixinContents.qr_scene_ticket_url.replaceAll("ACCESS_TOKEN", getAccessToken(WeixinContents.appid,WeixinContents.appsecret).getToken());
		System.out.println(jsonScene);
		JSONObject jsonObject = httpRequest(url, "POST", jsonScene);
		int result = 0;
		String ticket = "";
		if (null != jsonObject) {
			if (jsonObject.containsKey("errcode")) {
				result = jsonObject.getInt("errcode");
			}else{
				ticket = jsonObject.getString("ticket");
			}
		}
		return ticket;
	}


2.扫描二维码登陆的几个action
@ActionKey("/")
	@ClearInterceptor(ClearLayer.ALL)
	public void index() {
		LoginUser u = (LoginUser)getSessionAttr("LoginUser");
		setAttr("root", this.getRequest().getContextPath());
		if(null==u){
			setAttr("ticketId",wxTicket());
			render("/WEB-INF/login.html");
		}else{
			redirect("/index");
		}
	}
	private String wxTicket() {
		int sceneId = Db.queryInt("select SEQ_WX_SCENE.Nextval from dual");
		String ticketId = WeixinHttpUtils.getSceneTicket("QR_SCENE", sceneId+"");
		setSessionAttr("ticketId",ticketId);
		setSessionAttr("sessionId",this.getRequest().getSession().getId());
		String sql = "insert into wx_scence_logon(id,sessionid,ticketid,SCENCE_ID) values(sys_guid(),?,?,?)";
		Db.update(sql,this.getRequest().getSession().getId(),ticketId,sceneId);
		return ticketId;
	}
	@ActionKey("/cxTicket")
	@ClearInterceptor(ClearLayer.ALL)
	public void cxTicket(){
		String ticketId = getPara("ticketId");
		String sessionid = getPara("sessionId");
		int i=0;
		while(i<10){
			Record r = Db.findFirst("select id from wx_scence_logon l,wx_user u where u.open_id = l.open_id and l.ticketid = ? and l.sessionId = ?",ticketId,sessionid);
			if(r!=null&&StringUtils.isNotEmpty(r.getStr("id"))){
					setAttr("success","1");
					setAttr("logonId",r.getStr("id"));
					break;
			}else{
				setAttr("success","0");
				try {
					Thread.sleep(5000);
					i++;
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		render(new JsonRender().forIE());
	}
	@ActionKey("/ticketLogon")
	@ClearInterceptor(ClearLayer.ALL)
	public void ticketLogon(){
		String id = getPara("ticketId");
		Record r = Db.findFirst("select user_id as username from wx_scence_logon l,wx_user u where u.open_id = l.open_id and l.id = ?",id);
		if(r!=null&&StringUtils.isNotEmpty(r.getStr("username"))){
			String username = r.getStr("username");
			LoginUser user = LoginUser.dao.findFirst("select user_id,xm,department_id,departmentname,userpw from gy_user u where u.username = ? and u.userlockstate = '1' ",username);
			String permSql = "select distinct p.* from hr_user_role t,hr_role r,hr_role_perm m,hr_perms p where t.role_id = r.id and m.role_id = r.id and m.perm_id = p.id and user_id = ?";
			List<Record> perms = Db.find(permSql,new Object[]{user.getStr("user_id")});
			if(perms!=null&&perms.size()>0){
				this.getSession().removeAttribute("USER_PERMS");
				setSessionAttr("USER_PERMS",perms);
				getRequest().getSession().setAttribute("LoginUser",user);
			}
		}
		this.redirect("/main");
	}


3.
登陆页面
二维码显示
<img src="https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=${ticketId!}" width="250px"/>

定时查询扫描状态
function wxCxTikcet(){
	$.getJSON("${root!}/cxTicket",{ticketId:"${ticketId}",sessionId:"${sessionId}"},function(data){
		//alert(data.success=="1");
		if(data.success=='1'){
			_logon(data.logonId);
			//window.location.href="${root!}/ticketLogon/"+data.logonId;
		}
	});
}
var t_int = window.setInterval("wxCxTikcet()",5000);

4.公众平台代码

}else if(eventType.equalsIgnoreCase(MessageUtil.EVENT_TYPE_SCAN)){
							String scene_id = eventKey;
							if(Integer.parseInt(eventKey)==0){
								respContent = "扫描参数出错!请刷新重试!";
							}else{
								respContent = getSceneContent(scene_id,fromUserName);
							}
					}

private static String getSceneContent(String sceneId,String fromUserName){
		String sql ="select * from WX_SCENCE_LOGON  where scence_id = ?";
		Record r = Db.findFirst(sql,sceneId);
		if(r!=null){
			String updateSql = "update wx_scence_logon set open_id = ? where id = ?";
			Db.update(updateSql,fromUserName,r.getStr("id"));
			return "您已成功登陆***系统!";
		}
}




说明,框架使用jfinal 1.5