【DWR】扫一扫登陆

网上关于扫一扫登陆的地方越来越多,但是关于这个扫一扫的实现的文章却甚少,我在做这个工程之前,弄了许久都没有资料。其实这个可以用DWR来实现,DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站。它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA函数,就像它就在浏览器里一样,拥有运行在WEB上但是不需要浏览器插件的好处。

当然,扫一扫也不是乱扫就能够登陆的,关键是你的手机有一定的用户信息,将其获取出来,送到PC端。本文是基于微信公众平台的扫一扫,只要用户利用微信里面的扫一扫功能,就能获取微信用户资料然后登陆。

首先,如何配置好DWR,已经在《【DWR】Helloworld》(点击打开链接)一文中说明,这里不再赘述如何准备好dwr.jar,放到工程里面的lib文件夹,主要是说明这个微信扫一扫登陆是如何实现的。

一、基本目标

1、首先有一个这样的页面waitforscan.jsp,里面就一个等待用户扫描的二维码,上面输出的信息只是为了调试:

2、用微信的扫一扫功能对准这个二维码一扫:

3、就会弹出授权页面,用户一点确定,手机与电脑同时跳转到登陆成功页面,登陆成功页面输出微信的所有信息。:P为了笔者的个人安全,这里就不展示那个登陆页面了~

二、基本思想

1、关键是利用Dwr与Servlet对Httpsession与ScriptSession的操作。Httpsession是打开浏览器之后的过程,用户打开浏览器到关闭浏览器的一个过程对应一个Httpsession,这样我们就能够知道到底是哪个用户的哪个浏览器需要跳转,把用户的微信信息写入哪个浏览器;ScriptSession就是当前页的ID,这样就可以知道手机扫描二维码成功之后,能够告知waitforscan.jsp需要跳转。如果用户刷新此页,则Httpsession不改变,ScriptSession改变。

2、本工程的目录结构如下,记得在Servlet与Dwr需要的包,与Oauth认证需要的json解析包,具体可以看我《【Servlet】最简单的Servlet JavaWeb程序》(点击打开链接)、《【DWR】Helloworld》(点击打开链接)与《【Servlet】基于Jsp的微信Oauth2认证》(点击打开链接):

3、数据流程图如下:

4、数据流图如下:

三、制作过程

1、Web.xml

指明/scanhandle对应wx.loginqrcode.Scanhandle这个Java,同时启动Dwr,具体还可以参考我之前的《【Servlet】最简单的Servlet JavaWeb程序》(点击打开链接)与《【DWR】Helloworld》(点击打开链接

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>

	<!-- 我需要用到dwr技术 -->
	<servlet>
		<servlet-name>dwr-invoker</servlet-name>
		<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
		<init-param>
			<param-name>debug</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>pollAndCometEnabled</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>crossDomainSessionSecurity</param-name>
			<param-value>false</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dwr-invoker</servlet-name>
		<url-pattern>/dwr/*</url-pattern>
	</servlet-mapping>

	<!-- 微信扫二维码登陆部分-->
	<servlet>
		<servlet-name>scanhandle</servlet-name>
		<servlet-class>wx.loginqrcode.Scanhandle</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>scanhandle</servlet-name>
		<url-pattern>/scanhandle</url-pattern>
	</servlet-mapping>

</web-app>

2、Dwr.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
    "http://getahead.ltd.uk/dwr/dwr20.dtd">
<dwr>
    <allow>
        <create creator="new" javascript="dwrfuc" scope="application">
            <param name="class" value="wx.loginqrcode.Dwr"/>
        </create>
  </allow>
</dwr>  

指明Dwr的处理于wx.loginqrcode.Dwr这个java中,同时以后调用dwr里面的参数则用到dwr.XX()这个方法,这里在《【DWR】Helloworld》(点击打开链接)已经说明了。

3、Dwr.java

这个java是整个工程的核心,请比对后面的jsp页面与java进行查看

package wx.loginqrcode;

import java.util.*;
import javax.servlet.http.*;

import org.directwebremoting.*;
import org.directwebremoting.proxy.dwr.*;

public class Dwr  {
		//创造两个MAP数据结构,一个是存放标识+ScriptSession,另一个是标识+HttpSession,HttpSession要被其他java操作,所以是public
		private static Map<String, ScriptSession> scrSessionMap = new HashMap<String, ScriptSession>();
		public static Map<String, HttpSession> httpSessionMap = new HashMap<String, HttpSession>();
		//这个标识就是httpSessionId
		public void getwebindex(String httpSessionId) {
			//Dwr通过以下的两种方式取得ScriptSession与HttpSession
			ScriptSession sessions = WebContextFactory.get().getScriptSession();
			HttpSession httpSession = WebContextFactory.get().getHttpServletRequest().getSession();
			httpSessionMap.put(httpSessionId, httpSession);
			scrSessionMap.put(httpSessionId, sessions);
			//再把HttpSession打回给waitforscan.jsp,这个HttpSession与waitforscan.jsp里面利用jsp生成的HttpSession相同
			Util utilAll = new Util(sessions);
			utilAll.addFunctionCall("recid", httpSessionId);
		}

		public static void send(String to, String msg) {
			//这里是对于Scanhandle.java传过来消息进行处理,其实无论传递过来什么,都可以告诉waitforscan.jsp要跳转,这个msg是没有意义的
			ScriptSession sessions = scrSessionMap.get(to);
			Util utilAll = new Util(sessions);
			utilAll.addFunctionCall("ifscanmsgrec", msg);
		}

}

4、waitforscan.jsp

这一页用到了Jquery与Jquery_qrcode_master插件生成二维码,所以大家对比于上面的工程目录看到我的有js文件夹,关于如何用到Jquery与Jquery_qrcode_master插件生成二维码,可以参考《【jQuery】使用jquery-qrcode插件把网址转化成二维码,手机扫一扫即可访问》(点击打开链接)这里不赘述,很简单的,注意有兼容性的判断,二维码必须在上下左右留些空位,否则,用户扫描很困难,即使你的二维码成功,手机也是很难识别的。这页,甚至一下的页面应该对照着Dwr.java查看,因为Dwr.java是这个工程的核心

<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!-- 首先要引入3个在src文件夹里面的js文件 -->
<script type="text/javascript" src="js/jquery-1.11.1.js"></script>
<script type="text/javascript" src="js/jquery.qrcode.js"></script>
<script type="text/javascript" src="js/qrcode.js"></script>
<!-- 我需要用到dwr技术 -->
<script type='text/javascript' src='../dwr/engine.js'></script>
<script type='text/javascript' src='../dwr/util.js'></script>
<!-- 注意这里,因为刚才在dwr.xml写了javascript="dwrfuc"一句,所以这里必须引入dwrfun.js,上面则是指定动作 -->
<script type='text/javascript' src='../dwr/interface/dwrfuc.js'></script>
<title>欢迎扫码登陆</title>
</head>
<body>
	欢迎扫码登陆:你此次会话的HttpSessionID为:<span id="debug"></span>
	<!-- 新建一个id为qrcodeTable图层给这个二维码使用 -->
	<div id="qrcodeTable" style="margin-left:50px;margin-top:50px"></div>
</body>
</html>
<!-- 再于脚本处加入如下代码即可 -->
<script>
	//利用jsp生成一个HttpSessionID并且发送到dwr的getwebindex注册
	var httpSessionId = "<%=request.getSession().getId()%>";

	window.onload = function() {
		dwr.engine.setActiveReverseAjax(true);
		dwrfuc.getwebindex(httpSessionId);
	}	

	function recid(dwrmsg){
		document.getElementById("debug").innerHTML = httpSessionId;
		//用Jquery_qrcode_master插件生成二维码对于谷歌浏览器必须用到canvas这种方式,否则生成的二维码会出错,无法扫描
		//因此有了如下的二维码判断
		var isChrome = navigator.userAgent.toLowerCase().match(/chrome/) != null;
		if (!isChrome) {
			jQuery('#qrcodeTable').qrcode({
				render	: "table",
				text	: "http://119.29.10.179/wechattest/scanhandle?httpSessionId="+httpSessionId
			});
		}
		else{
			jQuery('#qrcodeTable').qrcode({
					render	: "canvas",
					text	: "http://119.29.10.179/wechattest/scanhandle?httpSessionId="+httpSessionId
				});
		}
	}

	//如果被扫描了,收到dwrmsg放过来的信息,马上跳转到welcome.jsp
	function ifscanmsgrec(dwrmsg){
		window.location.href = "welcome.jsp";
	}
</script>

5、ScanHandle.java

这里部分用到了Oauth认证,请参考《【Servlet】对基于Jsp的微信Oauth2认证的改进》(点击打开链接

package wx.loginqrcode;

//首先由于oauth.java在其他的包里面,所以我们要引入这个包
import wx.oauth.*;

//io异常需要
import java.io.*;

//servlet需要
import javax.servlet.*;
import javax.servlet.http.*;

public class Scanhandle extends HttpServlet {
	//没有下面这句eclipse会出警告
	private static final long serialVersionUID = 1L;
	//微信Oauth认证用到了get方法
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		//首先清空一下Session,以免多用户扫描时候Session冲突,然后请求httpSessionId这个参数
		request.getSession().invalidate();
		String httpSessionId = request.getParameter("httpSessionId");
		/**
		 * @param code 这是微信提供的东西code
		 * @param jsonstring 用户信息json字符串
		 */
		String code = request.getParameter("code");
		String jsonstring = null;
		//如果没有code,就向微信提供的网址请求
		//state里面还可以带上你需要拿到用户信息之后进一步处理的参数
		if (code == null) {
			/**
			 * @param appid 微信提供给你的appid
			 * @param redirect_uri 你自己的服务器地址/工程名/本页的Servelt名字
			 * @param state 把我们的httpSessionID带到state中,待Oauth认证成功之后可以取回
			 */
			response.sendRedirect("https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=http://192.168.0.1/wechattest/scanhandle&response_type=code&scope=snsapi_userinfo&state="+ httpSessionId +"#wechat_redirect");
		} else {
			//如果扫描成功之后,需要用state参数更新httpSessionId,否则由于Java开头有String httpSessionId = request.getParameter("httpSessionId");这句,会导致httpSessionId为空
			httpSessionId = request.getParameter("state");
			//向Oauth.java拿到了用户信息之后,存到手机Session
			jsonstring = new Oauth().getUserinfo(code);
			request.getSession().setAttribute("jsonstring", jsonstring);
			//通过httpSessionId取得对应的pc_httpSession,把记录用户信息的json字符串压入这个httpSession,这样pc就能收到用户微信信息
			HttpSession pc_httpSession = Dwr.httpSessionMap.get(httpSessionId);
			pc_httpSession.setAttribute("jsonstring", jsonstring);
			//然后发信息给waitforscan.jsp告诉其跳转,这里什么信息是不重要的,因为waitforscan.jsp根本没有对这个消息进行处理
			Dwr.send(httpSessionId, jsonstring);
			//如果手机自己跳转
			request.getRequestDispatcher("loginqrcode/welcome.jsp").forward(
					request, response);
		}
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

	}
}

6、welcome.jsp

登陆成功页面,非常简单,就是取用户信息,然后利用相应的json吧将其擦写,输出,

为了避免恶意用户直接通过输入浏览器地址访问这样,进行了抛出异常处理

至于微信服务器返回的用户微信信息json字符串,可以参考其开发者文档(点击打开链接

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ page import="com.alibaba.fastjson.*" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>欢迎登陆</title>
</head>
<body>
	<%
	String nickname = null;
	String headimgurl = null;
	try{
		String jsonstring = request.getSession().getAttribute("jsonstring").toString();
		JSONObject jobject = JSON.parseObject(jsonstring);
		nickname = jobject.getString("nickname");
		headimgurl = jobject.getString("headimgurl");
	}catch (Exception e) {
		out.print("请正常打开此页");
	}
	%>
	欢迎登陆<%=nickname %>,<img src="<%=headimgurl %>" />
</body>
</html>

至此,整个利用DWR做出来的扫一扫登陆页面就完工了,可以对其进行进一步的修改,比如绑定用户的微信信息与你网站的登陆信息,然后利用用户的微信信息在数据库取出你网站的登陆信息,这样就算微信不开放扫码登陆接口给你,你也可以利用微信的Oauth认证取得用户微信登陆信息的接口,自己做一个利用微信登陆你的网站的工程,登陆接口也好像没有这个接口,仅有合作企业才有,当然,你这样也为了微信做了广告。毕竟是基于对微信的开发。

时间: 2024-10-14 05:41:05

【DWR】扫一扫登陆的相关文章

php实现微信扫码自动登陆与注册功能

本文实例讲述了php实现微信扫码自动登陆与注册功能.分享给大家供大家参考,具体如下: 微信开发已经是现在程序员必须要掌握的一项基本的技术了,其实做过微信开发的都知道微信接口非常的强大做起来也非常的简单,这里我们一起来看一个微信自动登陆注册的例子. php 微信扫码 pc端自动登陆注册 用的接口scope 是snsapi_userinfo,微信登陆一个是网页授权登陆,另一个是微信联合登陆 网页授权登陆:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b647

日用品扫一扫微信红包活动

扫一扫微信红包活动 过去几年,支付宝在移动端一直被微信支付压着打,至少在线下支付上,腾讯已迎头赶上,在出行.零售.生活服务诸多领域的覆盖率不输支付宝钱包.总之,腾讯移动支付业务做起来了,而核心能力是社交. 就是由于腾讯这边放宽了,扫一扫微信红包活动越来越受大家欢迎,那么扫一扫微信红包活动.扫一扫微信红包活动系统开发.扫一艘微信红包活动可找小编:136-0243-3692. 一.扫一扫微信红包活动是怎么来操作的: 扫一扫微信红包活动直接跳转至红包活动领取页面,免微信授权登陆可以直观的展示企业品牌和

实现基于dotnetcore的扫一扫登录功能

第一次写博客,前几天看到.netcore的认证,就心血来潮想实现一下基于netcore的一个扫一扫的功能,实现思路构思大概是web端通过cookie认证进行授权,手机端通过jwt授权,web端登录界面通过signalr实现后端通讯,通过二维码展示手机端扫描进行登录.源码地址:点我 话不多说上主要代码, 在dotnetcore的startup文件中主要代码 public void ConfigureServices(IServiceCollection services) { services.C

很多人很想知道怎么扫一扫二维码就能打开网站,就能添加联系人,就能链接wifi,今天做个demo(续集)

有些功能部分手机不能使用,网站,通讯录,wifi基本上每个手机都可以使用.(浏览器自带的扫描就够了,QQ扫码和微信扫码部分手机不能直接连接wifi) 在看之前你可以扫一扫下面几个二维码先看看效果: 上篇网站介绍了一下常用格式(http://www.cnblogs.com/dunitian/p/4998714.html),其实扫二维码的本质就是解析出一段字符串,为什么有一些神奇的功能呢?那是字符串的格式满足一些系统内置的协议或者格式,所以系统就帮你干了类似于发短信,打电话,添加联系人,连接wifi

微信公众平台自定义菜单新增扫一扫、发图片、发位置 LBS运作更便捷

今天微信公众平台发布更新,自定义菜单新增扫一扫.发图片.发送位置等功能,这对于有意挖掘微信LBS服务的运营者来说更便捷了,订阅号不用返回微信界面就能扫图.发送图片.调用地理位置,用户体验更友好,自然也提高了黏度,对涨粉也好一些.详细能力如下: 公众号自定义菜单新增扫一扫.发图片.发位置功能 1. 扫码推送事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者,开发者可以下发消息. 2. 扫码推送事件,且弹出“消息接收

项目ITP(二) 二维码 拿起你的手机装一装,扫一扫 【每日一搏】

前言 系列文章:[传送门] 五一,期待的两天假期.我的生日,happy. [吐槽] 学校真恶心,半月前让我给他搞个东西,md,课题不加人.后来又来求,说钱(钱,咱不需要:我猜也不多).到现在,又来了,我晕.直接一句话,加我给做,时间问题,有可能只是半成品.不加不做. 正文 上文,我们讲了 二维码生成 解码 这次我们就用 android 来扫一下,实现android 扫二维码. 下载扫一扫 包结构-介绍 #com.zxing.xx 这是 zxing 库提供的 #BarCodeActivity 实战

名片扫一扫识别怎么样

出去见客户,交朋友,我们都会交换名片,一般情况下送出去多少名片,就会收到多少名片.我们都会拿一个整理名片的盒子,甚至专门用一个抽屉来整理我们收集起来的名片,有时候突然想起一位朋友,但想从名片堆里查找出ta,可能需要很久很久时间去找,甚至可以说是大海捞针,想必很多人都有这样的苦恼.还好我们有汇卡名片识别,可以进行名片扫一扫识别. ? 名片扫一扫识别,汇卡名片是文通研发的一款识别名片信息的软件.产品不以收集各位友人的信息为导向,这是一款基于OCR技术研发的应用. 名片扫一扫识别采用OCR技术,将名片

手机支付宝扫一扫 给郝萌主捐赠

很多其它游戏源代码,请点击我 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主的独立游戏工作,捐赠数额任意,重在心意^_^ + -------------------------------------------------------- End -------------------------------------------------------- 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主的独立游戏工作,捐赠数额任意,重在心意^_^ + -------------------

ASP.NET MVC做的微信WEBAPP中调用微信JSSDK扫一扫

今天做一个项目,是在微信上用的,微信WEB APP,里面用到了调用手机摄像头扫一扫二维码的功能,记得以前某个项目里写有的,但是找不到之前那个项目源码了,想复制粘贴也复制不了了,只好对着微信的那个开发文档重新再写过 ,顺便写个博客,以后碰到相同的问题直接复制博客里的代码就行了 以下是显示在微信上的页面: 以下是页面的代码,(用到了MUI): @{ Layout = "~/Views/Shared/_Layout.cshtml"; } <header class="mui-