前提条件:
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
分享到:
相关推荐
主要为大家详细介绍了PHP微信扫描公众号二维码实现登陆功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
1、使用jweixin-1.4.0.js实现微信公众号Html5页面调用手机照相机识别二维码 2、核心代码已经给到txt文件中,可以根据需要自行扩充。 3、二维码可以由自己的API生成,应用到很多领域。
8、扫描参数二维码接收参数和用户openid PS:代码仅供参考,需要在服务号上配置和获取 token,AppID,AppSecret,access_token以及设置网页OAuth2.0鉴权的网页地址。 全程几乎无验证,最好不要直接使用,建议完善验证...
结合了express+request+config+wechat等模块,实现了获取微信二维码url地址和ticket,事件推送服务
C#代码微信开发 带参数二维码, 可用于不同渠道的推广宣传二维码制作。
1.使用TBS Studio进行微信公众号真机调试扫描二维码报错无法安装线上TBS内核,原因是微信内置浏览器 x5内核以弃用升级到最新的xweb内核; 2.本方法是在最新版微信基础上真机公众号调试,手机电脑同屏利用浏览器的...
刚开始接触微信的时候一头雾水,领导想要一个扫码获取微信用户信息的功能,接下来通过本文给大家分享微信公众号实现扫码获取微信用户信息(网页授权),需要的朋友可以参考下
扫码登录是微信官方提供的安全验证方法之一,它通过手机扫描二维码将登录信息与设备绑定,有效防止了密码泄露的风险。该登录器的实现原理可能包括调用微信官方的API接口,结合用户的微信客户端,实现扫码验证过程。 ...
【抽奖步骤】第1步:用户,通过链接或者扫描二维码签到第2步:管理员,查看签到列表第3步:管理员,电脑上打开“头像抽奖”抽奖【可以操作内容】第1步:准备好自己的APPID和APPSECRET(公众号的)第2步:打开WxAPI....
适用于:本文适用于有一定微信开发基础的用户 引言: 花了300大洋申请了微信公众平台后,发现不能使用微信公众号登录网站(非微信打开)获得微信帐号。仔细研究后才发现还要再花300大洋申请微信...2.用户通过微信扫描
小程序可以通过扫描二维码 二维码或是搜一搜,就能立即使用。 可以进行关联,并相互跳转。通过公众号查看并进入所绑定的小程序一个公众号可以绑五个小程序。 小程序”可添加到桌面变成APP安卓用户可以将...
微信公众号智能绑定实例,具体参考文章:... 如果后期微信公众号登录只能通过扫描二维码登录则智能绑定功能完全失效,目前企业号使用的就是扫描二维码+密码登录方式。
微信公众号扫描带参数二维码实现自动分组,实现不同渠道进入用户数量统计,为地推用户进行绩效统计。
扫描测试号二维码后会生成微信号,哪个账号需要接收推送信息就需要哪个账号扫码 这里需要记住的是对应账号的微信号,也就是user id,后面需要用 ## 新增测试模板 这里点击`新增测试模板` 模板标题: 自定义,...
3、受权限限制(全是个人未认证订阅号),暂未开发底部自定义菜单、关注者接口、二维码扫描事件等其他高级功能。 操作步骤: 1、直接上传并通过域名 目录访问,使用相对路径,支持任意目录直传即用。 PHP微信...
几天在做项目时遇到微信扫描二维码的然后进入公众号网页巴拉巴拉的,然后就很顺利的遇到了在安卓端扫码的时候,顺利的一塌糊涂,然后到了苹果端的时候,就只能出现一个保存图片,然后就写一下记录一下这问题的解决...
受权限限制(全是个人未认证订阅号),暂未开发底部自定义菜单、关注者接口、二维码扫描事件等其他高级功能。 # 操作步骤 # #1. 直接上传并通过域名+目录访问,使用相对路径,支持任意目录直传即用。
3、受权限限制(全是个人未认证订阅号),暂未开发底部自定义菜单、关注者接口、二维码扫描事件等其他高级功能。 使用方法:直接上传并通过域名 目录访问,使用相对路径,支持任意目录直传即用。