java扫码登录
来源:互联网 发布:素颜霜 知乎 编辑:程序博客网 时间:2024/04/30 00:55
这篇博文主要记录我实现扫码登录的步骤,及代码。其实之前从网上搜了很久扫码登录,copy版很多,所以回答也就那几种。
我把我自己的思路也说一下吧。如果有更好的意见或者我有不对的地方,请指出。
首先说一下我用的技术, maven构建项目,ssh ,redis, shiro, goeasy推送,ZXing二维码生成。
图有点粗糙。凑合看,我解释一下,首先我认为,session肯定是浏览器和服务器交互唯一的标识,所以我认为sessionid可以直接定位到是哪一个用户进行扫码登录,
OK,那么围绕这一点,当浏览器打开我们的网站时,我们就getsession,这样保证先给浏览器一个session对象。
接下来我将用代码展示的方式给大家展示一下流程
首先从网上扒了一个监听全局session的监听器。
public class MySessionContext { private static HashMap mymap = new HashMap(); public static synchronized void AddSession(HttpSession session) { if (session != null) { mymap.put(session.getId(), session); } } public static synchronized void DelSession(HttpSession session) { if (session != null) { mymap.remove(session.getId()); } } public static synchronized HttpSession getSession(String session_id) { if (session_id == null) return null; return (HttpSession) mymap.get(session_id); }}
public class MySessionListener { public void sessionCreated(HttpSessionEvent httpSessionEvent) { MySessionContext.AddSession(httpSessionEvent.getSession()); } public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { HttpSession session = httpSessionEvent.getSession(); MySessionContext.DelSession(session); }}
<listener><listener-class>cn.itcast.web.action.lisener.MySessionListener</listener-class></listener>
登录Action
@Action("loginAction_login")public String login() throws Exception {Map<String, Object> session = ActionContext.getContext().getSession();Subject subject = SecurityUtils.getSubject();//shiroif(session.get(SysConstant.CURRENT_USER_INFO)!=null){//如果有session用户信息,直接走验证,说明是手机扫码的User user = (User) session.get(SysConstant.CURRENT_USER_INFO);subject.login(new UsernamePasswordToken(user.getUserName(),user.getPassword()));} if(subject.isAuthenticated()){//验证成功直接返回成功。 return SUCCESS; }if(UtilFuns.isEmpty(username)){//为浏览器分配sessionHttpServletRequest request = ServletActionContext.getRequest(); sessID = request.getSession().getId(); super.push(sessID);request.getSession().setAttribute("ssid", sessID);return "login";}try {//登录成功赋值session String md5 = Encrypt.md5(password, username);subject.login(new UsernamePasswordToken(username, md5));session.put(SysConstant.CURRENT_USER_INFO, (User)subject.getPrincipal());} catch (Exception e) {e.printStackTrace();request.put("errorInfo", "对不起,登录失败,用户名或密码错误!!!");HttpServletRequest request = ServletActionContext.getRequest(); sessID = request.getSession().getId(); super.push(sessID);//压栈request.getSession().setAttribute("ssid", sessID);//为了获得图片二维码时有sessionreturn "login";}User user =(User)subject.getPrincipal();//4.将user对象保存到session域中session.put(SysConstant.CURRENT_USER_INFO, user);//5.跳页面return SUCCESS;}
这里实际上页面也悄悄工作了
<script>function changeCode(){$("#erweima").attr('src','${ctx}/mobile/MobileCode?t='+new Date().getTime());//选择二维码时直接去替换二维码图片}</script><script type="text/javascript" src="http://cdn.goeasy.io/goeasy.js"></script><script type="text/javascript"> var goEasy = new GoEasy({ appkey: 'BC-c9196bffff9b4fcabd70a200f95a51d2' }); goEasy.subscribe({ channel: '${sessID }',//这里绑定sessionid保证推送是指定用户 onMessage: function(message){ location.reload() } }); </script> </head>
public class QRCodeUtil extends BaseAction{ @Action(value="MobileCode")public void getcode(){//生成二维码HttpServletResponse response;String urls;Hashtable<EncodeHintType, String> hints;BitMatrix matrix;try {response = (HttpServletResponse)ActionContext.getContext().get(org.apache.struts2.StrutsStatics.HTTP_RESPONSE); Jedis jedis =new Jedis("192.168.123.101");HttpServletRequest request = ServletActionContext.getRequest();String sessID = (String) session.get("ssid");String id = request.getSession().getId();MySessionContext.AddSession(request.getSession()); String key = Encrypt.md5(UUID.randomUUID().toString(), "cao");jedis.set(key, sessID, "NX", "EX", 1800); urls = "http://192.168.123.96:8080/test/mobileAutoLog?parms="+key;//这是手机端扫码的结果hints = new Hashtable<EncodeHintType, String>(); hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); matrix = null; matrix = new MultiFormatWriter().encode(urls, BarcodeFormat.QR_CODE, 300, 300, hints); MatrixToImageWriter.writeToStream(matrix, "jpg", response.getOutputStream());} catch (Exception e1) {// TODO Auto-generated catch blocke1.printStackTrace();} }
然后假装扫码成功
。
。
。
。
。
。
我不得不插一段安卓代码了。。。
public void ineedLogin(View v){//扫码成功SharedPreferences sharedPreferences = getSharedPreferences("userinfo", 1);token = sharedPreferences.getString("username", ""); try {GetDataFromService();} catch (Exception e) {e.printStackTrace();}}private void GetDataFromService() throws Exception{RequestParams params = new RequestParams(result+"&username="+token);//去访问浏览器发过来的请求,并且拼接上用户的用户名。x.http().post(params, new Callback.CacheCallback<String>() {@Overridepublic boolean onCache(String result) {return false;}@Overridepublic void onSuccess(String result) {}@Overridepublic void onError(Throwable ex, boolean isOnCallback) {}@Overridepublic void onCancelled(CancelledException cex) {}@Overridepublic void onFinished() {}});
其实我这里选了一个比较low的。。我为了省事,安卓直接拼了username过去。。还用了个Xutils...搞得重写了很多方法。。别笑我。。哈哈哈哈
好了我们再来看扫码成功的action
Jedis jedis =new Jedis("192.168.123.101"); String jedisParms = jedis.get(parms); if(jedisParms!=null&&!jedisParms.equals("")){//去看redis是否有手机端传过来这个码, List<User> find = userService.find(new Specification<User>() {@Overridepublic Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {return cb.equal(root.get("userName").as(String.class),username);}}); User u1 = find.iterator().next();//拿到用户信息 HttpSession session = MySessionContext.getSession(jedisParms);//拿到session session.setAttribute(SysConstant.CURRENT_USER_INFO, u1); final String APP_KEY="BC-c9196bffff9b4fcabd70a200f95a51d2"; GoEasy goEasy =new GoEasy(APP_KEY); goEasy.publish(jedisParms,"heh" ); //直接推送前端 return NONE; }else{ System.out.println("验证失败"); }} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return "error";}
前端收到推送之后会刷新页面,并且session里面已经有值,那么会走登录验证的方法,session有值的方法。
我们再来看shiro,这里当时我有点懵,因为shiro实际上我用的不是很熟悉,就知道它运行的流程,当时不知道怎么才能让他验证通过,所以走了很多次shiro的登录方法,如果有别的好办法!也希望大家告诉我!!!
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {Map<String, Object> session = ActionContext.getContext().getSession();User object = (User) session.get(SysConstant.CURRENT_USER_INFO);if(object!=null){//手机final String username = object.getUserName();List<User> findUser = userService.find(new Specification<User>() {@Overridepublic Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {// TODO Auto-generated method stubreturn cb.equal(root.get("userName").as(String.class), username);}});return new SimpleAuthenticationInfo(findUser,findUser.get(0).getPassword(),this.getName());}else{//电脑 UsernamePasswordToken userNamePassword=(UsernamePasswordToken) arg0;final String username = userNamePassword.getUsername();List<User> findUser = userService.find(new Specification<User>() {@Overridepublic Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {// TODO Auto-generated method stubreturn cb.equal(root.get("userName").as(String.class), username);}});if(findUser!=null && findUser.size()!=0){return new SimpleAuthenticationInfo(findUser,findUser.get(0).getPassword(),this.getName());}}return null;}
因为之前没有加扫码登录时,我HashMd5是在这个密码比较器里加的,加了扫码之后,页面出过来明文我就直接加密了。所以密码比较器里面,直接比较就可以了
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {UsernamePasswordToken uToken =(UsernamePasswordToken) token;String en =new String(uToken.getPassword());return equals(en, info.getCredentials());}
到此java扫码登录完成!
如果各位有别的好思路,希望也分享给我。
阅读全文
2 0
- java扫码登录
- JAVA实现二维码扫码登录
- Java实现扫码二维码登录
- Java实现扫码二维码登录
- 扫码登录流程
- 扫码登录操作过程
- iOS 扫码登录
- android扫码登录
- 扫码登录
- APP扫码登录
- 扫码登录原理
- Android 实现扫码登录
- 关于扫码登录的一些问题
- 扫码登录的简易实现
- php/socket.io实现扫码登录
- 基于websocket的扫码登录
- 有关于PC的扫码登录
- 微信开放平台扫码登录
- 百炼-2815-城堡问题-C语言-递归算法
- pthread引发的内存泄漏
- 2017多校三 1004题 hdu 6059 Kanade's trio Trie树 计数
- 博通wifi驱动详解(三)
- 剑指offer--孩子们的游戏(圆圈中最后剩下的数)
- java扫码登录
- FAFU OJ 全排列
- 设计模式之中介者模式
- 机器学习中的正/负样本
- Shredding Company--(DFS)
- 1.7. 高斯过程(Gaussian Processes)
- 剑指offer 之 二叉搜索树与双向链表
- TODO 解析
- 博通wifi驱动详解(四)