所需jar包
<!--spring-websocket-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.3.20.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.3.20.RELEASE</version>
</dependency>
<!-- google 的二维码写人jar-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.2.0</version>
</dependency>
package com.bsd.hy.module.webSocketServet; import java.io.Serializable; public class Msg4Ws<T> implements Serializable { private static final long serialVersionUID = 1L; private int code;//消息编号 private String msg;//消息描述 private T data;//消息实体 public Msg4Ws(int code) { this.code = code; } public Msg4Ws(int code, T data) { this.code = code; this.data = data; } public Msg4Ws(int code, String msg, T data) { this.code = code; this.msg = msg; this.data = data; } public Msg4Ws(int code, String msg) { this.code = code; this.msg = msg; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
package com.bsd.hy.module.webSocketServet; import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; import java.io.IOException; import java.util.*; @Service public class MyHandler extends TextWebSocketHandler { private Logger logger = LoggerFactory.getLogger(MyHandler.class); // 保存所有的用户session private static final Map<String, WebSocketSession> users; static { users = new HashMap<>(); } /** * 连接 就绪时 * @param session * @throws Exception */ @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { logger.debug("[{} : {}] has be connected...", session.getUri(), session.getId()); users.put(session.getId(), session); System.out.println(session); logger.info("返回id"); Msg4Ws<String> msg4Ws=new Msg4Ws<String>(10000, "ws的sessionId", session.getId()); // 转为json String message = new ObjectMapper().writeValueAsString(msg4Ws); TextMessage returnMessage = new TextMessage(message); session.sendMessage(returnMessage); } /** * 处理信息 * @param session * @param message * @throws IOException */ @Override public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException { String msgStr = message.getPayload(); logger.info("收到消息:" + message); logger.info("收到消息内容:" + msgStr); String resultMsg = msgStr + " received at server"; logger.info("返回信息:" + resultMsg); TextMessage returnMessage = new TextMessage(resultMsg); session.sendMessage(returnMessage); } /** * 处理传输时异常 * @param session * @param exception * @throws Exception */ @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { super.handleTransportError(session, exception); } /** * 关闭 连接时 * @param session * @param status * @throws Exception */ @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { logger.debug("[{} : {}]", session.getUri(), session.getId()); users.remove(session.getId()); } @Override public boolean supportsPartialMessages() { return super.supportsPartialMessages(); } /** * 发送信息给指定用户 * @param userid * @param message * @throws IOException */ public void sendMessageToUser(String userid, TextMessage message) throws IOException { WebSocketSession session = users.get(userid); if (session == null) { throw new RuntimeException("对应sessionid(" + userid + ")的session不存在"); } session.sendMessage(message); } /** * 向所有用户推送消息 * @param message * @throws IOException */ public void sendMessageToAllUsers(TextMessage message) throws IOException { for (WebSocketSession user : users.values()) { user.sendMessage(message); } } }
package com.bsd.hy.module.webSocketServet; import java.util.Map; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; public class MyWebSocketConfig extends HttpSessionHandshakeInterceptor{ @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { System.out.println("Before Handshake"); return super.beforeHandshake(request, response, wsHandler, attributes); } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { System.out.println("After Handshake"); super.afterHandshake(request, response, wsHandler, ex); } }
package com.bsd.hy.module.wechat; import com.bsd.hy.module.user.model.HyUser; import com.bsd.hy.module.user.service.UserService; import com.bsd.hy.module.webSocketServet.Msg4Ws; import com.bsd.hy.module.webSocketServet.MyHandler; import com.bsd.hy.util.http.HttpsUtil; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.zxing.BarcodeFormat; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.socket.TextMessage; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.util.concurrent.locks.ReentrantLock; import static com.bsd.hy.module.wechat.WechatString.APP_ID; import static com.bsd.hy.module.wechat.WechatString.APP_SECRET; /** * 调用微信授权登录的接口 * step1 拼接授权url,url 如下: * state=key1 (长度为5) 创建厂家 state=key2 (长度为6) 创建经销商 state=c 普通用户授权登录 * https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxe3a25a1e6b280c17&redirect_uri=http://23s60z8662.iask.in/wechat/step2&response_type=code&scope=snsapi_userinfo&state=dealer#wechat_redirect * https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxe3a25a1e6b280c17&redirect_uri=http://23s60z8662.iask.in/wechat/step2&response_type=code&scope=snsapi_userinfo&state=factory#wechat_redirect * https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxe3a25a1e6b280c17&redirect_uri=http://23s60z8662.iask.in/wechat/step2&response_type=code&scope=snsapi_userinfo&state=dealerfactory#wechat_redirect * step2 用户点击授权链接后的回调处理 * step3 拉取用户信息 */ @Controller @RequestMapping("/wechat") public class WechatAuthController { private static final ReentrantLock LOCK = new ReentrantLock(); private static final Logger LOGGER = LoggerFactory.getLogger(WechatAuthController.class); @Autowired private UserService userService; @Autowired private MyHandler myHandler; private HttpSession session; /** * Method of obtaining a QR code */ @RequestMapping("/step1") private void getobtainingQRcode(String type, HttpServletResponse response) throws Exception { String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + APP_ID + "&redirect_uri=http://23s60z8662.iask.in/wechat/step2&" + "response_type=code&scope=snsapi_userinfo&state=" + type + "#wechat_redirect"; ServletOutputStream stream = null; try { int width = 350; int height = 350; stream = response.getOutputStream(); QRCodeWriter writer = new QRCodeWriter(); BitMatrix m = writer.encode(url, BarcodeFormat.QR_CODE, height, width); MatrixToImageWriter.writeToStream(m, "png", stream); } catch (Exception e) { e.printStackTrace(); } finally { if (stream != null) { try { stream.flush(); stream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } /** * step2 用户点击授权链接后的回调处理 */ @RequestMapping("/step2") public String callback(String code, String state,HttpServletRequest request) { // 获取access_token的链接 String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + APP_ID + "&secret=" + APP_SECRET + "&code=" + code + "&grant_type=authorization_code"; try { session=request.getSession(); LOCK.lock(); String result = HttpsUtil.get(url); if (result == null) return "forward:/404.jsp"; // 获取数据失败 JSONObject json = new JSONObject(result); String openId = json.getString("openid"); String accessToken = json.getString("access_token"); String[] strs = state.split("_"); session.setAttribute("openId", openId); session.setAttribute("accessToken", accessToken); session.setAttribute("state", state); if (strs[0].toString().equals("dealer")) { session.setAttribute("type", 1); } else if (strs[0].toString().equals("factory")) { session.setAttribute("type", 2); } else { session.setAttribute("type", 0); } return "forward:/view/user/index.jsp"; } catch (Exception ex) { LOGGER.error("/微信授权错误/"); session.setAttribute("message", "授权失败,请重试"); return "forward:/404.jsp"; } finally { LOCK.unlock(); } } /** * step3 拉取用户信息 * { * "openid":" OPENID", * "nickname": NICKNAME, * "sex":"1", * "province":"PROVINCE" * "city":"CITY", * "country":"COUNTRY", * "headimgurl": "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46", * "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ], * "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" * } * 以上信息皆可以拉取 * <p> * 获取用户信息后,保存到数据库,在shiro加密过程中,openid 为shiro的username, * 以openid 为salt,进行 11 次加密,得到加密后的password */ @RequestMapping("/step3") public String getUserInfo(HttpServletRequest request) throws Exception { session = request.getSession(); String accessToken = session.getAttribute("accessToken").toString(); String openId = session.getAttribute("openId").toString(); int type = (int) session.getAttribute("type"); String state = session.getAttribute("state").toString(); ; String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN"; String result = HttpsUtil.get(url); if (result == null) return null; JSONObject json = new JSONObject(result); HyUser hyUser = new HyUser(); hyUser.setOpenId(openId); hyUser.setNickname(json.getString("nickname")); hyUser.setSex(json.getInt("sex")); hyUser.setProvince(json.getString("province")); hyUser.setCity(json.getString("city")); hyUser.setCountry(json.getString("country")); hyUser.setHeadimgurl(json.getString("headimgurl")); hyUser.setType(type); HyUser user = userService.getUserByOpenId(openId); if (user == null) { hyUser.setType(type); int user_id = userService.insertUser(hyUser); } else if (user.getType() == type) { hyUser.setType(type); int user_id = userService.update(hyUser); } else { hyUser.setType(3); int user_id = userService.update(hyUser); } String[] strs = state.split("_"); if (type == 1) { //PC端的用户请求 Msg4Ws<Boolean> msg4Ws = new Msg4Ws<Boolean>(10001, "/wechat/adddealer", true); /*json转换*/ String message = new ObjectMapper().writeValueAsString(msg4Ws); myHandler.sendMessageToUser(strs[2], new TextMessage(message)); return "forward:/view/user/add_dealer.jsp"; } else if (type == 2) { //PC端的用户请求 Msg4Ws<Boolean> msg4Ws = new Msg4Ws<Boolean>(10001, "/wechat/addfactory", true); /*json转换*/ String message = new ObjectMapper().writeValueAsString(msg4Ws); myHandler.sendMessageToUser(strs[2], new TextMessage(message)); return "forward:/view/user/add_factory.jsp"; } else { return "/404.jsp"; } } @RequestMapping("/adddealer") public String adddealer(){ return "/view/user/add_dealer.jsp"; } @RequestMapping("/addfactory") public String tttt(){ return "/view/user/add_factory.jsp"; } }
前端代码
dealer.jsp
<%@ page contentType="text/html; charset=utf-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <% String base_path = request.getContextPath(); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <link type="text/css" rel="stylesheet" href="<%=base_path%>/base/plugins/layui/css/layui.css" /> <style type="text/css"> .ad_img{ width: 256px; margin: auto; } h3{ text-align: center; } </style> </head> <body> <div class="layui-form-item" style="text-align:center; padding-top:10%"> <div class="ad_img" id="erweima" > <h1>经销商授权码</h1> <img id="qrcode" src="" alt=""> </div> </div> <script type="text/javascript" src="<%=base_path%>/js/jquery-3.3.1.min.js" charset="utf-8"></script> <script type="text/javascript" src="<%=base_path%>/layer/layer.js"></script> <script type="text/javascript" src="<%=base_path%>/base/plugins/layui/layui.js" charset="utf-8"></script> <script type="text/javascript" src="<%=base_path%>/js/global.js" charset="utf-8"></script> <script type="text/javascript"> function randomString(len) { len = len || 32; var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz'; var maxPos = $chars.length; var pwd = ''; for (i = 0; i < len; i++) { pwd += $chars.charAt(Math.floor(Math.random() * maxPos)); } return pwd; } var str = randomString(32); /*首次进入js自动加载二维码*/ $(function(){ $("#qrcode").attr("src","<%=base_path%>/wechat/step1?type=dealer_"+str); }); window.setInterval(function() { $("#qrcode").attr("src","<%=base_path%>/wechat/step1?type=dealer_"+str); }, 300000); var ws = null; if (WebSocket) { ws = new WebSocket("ws://localhost/websocket"); // 建立通道 } else { alert("浏览器不支持websocket"); } ws.addEventListener('open', function(ev) { console.log('websocket已经连接'); ws.send('Hello'); }); ws.onmessage = function(evt) { console.log("Received Message: " + evt.data); //{"code":10001,"msg":"登录成功","data":true} var json = evt.data; var hasCode = json.match("code"); if (hasCode == null) { return; } var dataObj = eval("(" + json + ")"); var code = dataObj.code; console.log("code=" + code); if (code == 10000) { $("#qrcode").attr("src", "<%=base_path%>/wechat/step1?type=factory_"+str+"_"+ dataObj.data); } else if (code == 10001) { ws.close(); window.location.href=dataObj.msg; } }; </script> </body> </html>
factory.jsp
<%@ page contentType="text/html; charset=utf-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <% String base_path = request.getContextPath(); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" type="text/css" href="<%=base_path%>/base/plugins/layui/css/layui.css" /> <style type="text/css"> .ad_img{ width: 256px; margin: auto; } h1{ text-align: center; } </style> </head> <body> <div class="layui-form-item" style="text-align:center; padding-top:10%"> <div class="ad_img" id="erweima" > <h1>经销商授权码</h1> <img id="qrcode" src="" alt=""> </div> </div> <script type="text/javascript" charset="utf-8" src="<%=base_path%>/js/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="<%=base_path%>/layer/layer.js"></script> <script type="text/javascript" charset="utf-8" src="<%=base_path%>/base/plugins/layui/layui.js"></script> <script type="text/javascript" charset="utf-8" src="<%=base_path%>/js/global.js"></script> <script> function randomString(len) { len = len || 32; var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz'; var maxPos = $chars.length; var pwd = ''; for (i = 0; i < len; i++) { pwd += $chars.charAt(Math.floor(Math.random() * maxPos)); } return pwd; } var str = randomString(32); var ws = null; if (WebSocket) { ws = new WebSocket("ws://localhost/websocket"); // 建立通道 } else { alert("浏览器不支持websocket"); } ws.addEventListener('open', function(ev) { console.log('websocket已经连接'); ws.send('Hello'); }); ws.onmessage = function(evt) { console.log("Received Message: " + evt.data); var json = evt.data; var hasCode = json.match("code"); if (hasCode == null) { return; } var dataObj = eval("(" + json + ")"); var code = dataObj.code; console.log("code=" + code); if (code == 10000) { $("#qrcode").attr("src", "<%=base_path%>/wechat/step1?type=factory_"+str+"_"+ dataObj.data); } else if (code == 10001) { ws.close(); window.location.href=dataObj.msg; } }; </script> </body> </html>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String base_path = request.getContextPath(); %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> <title></title> <link rel="stylesheet" href="https://cdn.bootcss.com/weui/1.1.3/style/weui.min.css"> <link rel="stylesheet" href="https://cdn.bootcss.com/jquery-weui/1.2.1/css/jquery-weui.min.css"> </head> <body> <div class="weui-msg"> <div class="weui-msg__icon-area"><i class="weui-icon-info weui-icon_msg"></i></div> <div class="weui-msg__text-area"> <h2 class="weui-msg__title">授权登录</h2> <p class="weui-msg__desc"> 获取你的公开信息(昵称、头像等) </p> </div> <div class="weui-msg__opr-area"> <p class="weui-btn-area"> <a href="javascript:dexe()" class="weui-btn weui-btn_primary">确认授权</a> </p> </div> </div> </body> <script src="https://cdn.bootcss.com/jquery/1.11.0/jquery.min.js"></script> <script src="https://cdn.bootcss.com/jquery-weui/1.2.1/js/jquery-weui.min.js"></script> <script src="https://cdn.bootcss.com/jquery-weui/1.2.1/js/swiper.min.js"></script> <script src="https://cdn.bootcss.com/jquery-weui/1.2.1/js/city-picker.min.js"></script> <script type="text/javascript" charset="utf-8" src="<%=base_path%>/js/jquery-3.3.1.min.js"></script> <script type="text/javascript"> function dexe() { $.ajax({ type: "get", data:{}, url: '<%=base_path%>/wechat/step3', success: function (page) { alert("授权成功"); }, error: function () { alert("授权失败"); } }); } </script> </html>