java 扫描登录

这篇博文主要记录我实现扫码登录的步骤,及代码。其实之前从网上搜了很久扫码登录,copy版很多,所以回答也就那几种。

我把我自己的思路也说一下吧。如果有更好的意见或者我有不对的地方,请指出。

首先说一下我用的技术, maven构建项目,ssh ,redis, shiro, goeasy推送,ZXing二维码生成。


图有点粗糙。凑合看,我解释一下,首先我认为,session肯定是浏览器和服务器交互唯一的标识,所以我认为sessionid可以直接定位到是哪一个用户进行扫码登录,

OK,那么围绕这一点,当浏览器打开我们的网站时,我们就getsession,这样保证先给浏览器一个session对象。

接下来我将用代码展示的方式给大家展示一下流程

首先从网上扒了一个监听全局session的监听器。

  1. public class MySessionContext {  
  2.      private static HashMap mymap = new HashMap();  
  3.   
  4.         public static synchronized void AddSession(HttpSession session) {  
  5.             if (session != null) {  
  6.                 mymap.put(session.getId(), session);  
  7.             }  
  8.         }  
  9.   
  10.         public static synchronized void DelSession(HttpSession session) {  
  11.             if (session != null) {  
  12.                 mymap.remove(session.getId());  
  13.             }  
  14.         }  
  15.   
  16.         public static synchronized HttpSession getSession(String session_id) {  
  17.             if (session_id == null)  
  18.             return null;  
  19.             return (HttpSession) mymap.get(session_id);  
  20.         }  
  21. }  
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);
        }
}

  1. public class MySessionListener {  
  2.        public void sessionCreated(HttpSessionEvent httpSessionEvent) {  
  3.             MySessionContext.AddSession(httpSessionEvent.getSession());  
  4.             }  
  5.   
  6.             public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {  
  7.                 HttpSession session = httpSessionEvent.getSession();  
  8.                 MySessionContext.DelSession(session);  
  9.             }  
  10. }  
public class MySessionListener {
       public void sessionCreated(HttpSessionEvent httpSessionEvent) {
            MySessionContext.AddSession(httpSessionEvent.getSession());
            }

            public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
                HttpSession session = httpSessionEvent.getSession();
                MySessionContext.DelSession(session);
            }
}


  1.  <listener>  
  2. <listener-class>cn.itcast.web.action.lisener.MySessionListener</listener-class>  
  3. </listener>  
 <listener>
<listener-class>cn.itcast.web.action.lisener.MySessionListener</listener-class>
</listener>


主要是因为不知道如何通过sessionid获得session对象。。知道的请留言告诉我,感激不尽!


登录Action

  1. @Action(“loginAction_login”)  
  2.     public String login() throws Exception {  
  3.         Map<String, Object> session = ActionContext.getContext().getSession();  
  4.         Subject subject = SecurityUtils.getSubject();//shiro  
  5.         if(session.get(SysConstant.CURRENT_USER_INFO)!=null){//如果有session用户信息,直接走验证,说明是手机扫码的  
  6.             User user = (User) session.get(SysConstant.CURRENT_USER_INFO);  
  7.             subject.login(new UsernamePasswordToken(user.getUserName(),user.getPassword()));  
  8.         }  
  9.           
  10.       
  11.       if(subject.isAuthenticated()){//验证成功直接返回成功。  
  12.           return SUCCESS;  
  13.       }  
  14.         if(UtilFuns.isEmpty(username)){//为浏览器分配session  
  15.             HttpServletRequest request = ServletActionContext.getRequest();  
  16.              sessID = request.getSession().getId();  
  17.             super.push(sessID);  
  18.             request.getSession().setAttribute(”ssid”, sessID);  
  19.             return “login”;  
  20.         }  
  21.           
  22.         try {//登录成功赋值session  
  23.             String md5 = Encrypt.md5(password, username);  
  24.             subject.login(new UsernamePasswordToken(username, md5));  
  25.             session.put(SysConstant.CURRENT_USER_INFO, (User)subject.getPrincipal());  
  26.         } catch (Exception e) {  
  27.             e.printStackTrace();  
  28.             request.put(”errorInfo”“对不起,登录失败,用户名或密码错误!!!”);  
  29.             HttpServletRequest request = ServletActionContext.getRequest();  
  30.              sessID = request.getSession().getId();  
  31.              super.push(sessID);//压栈  
  32.             request.getSession().setAttribute(”ssid”, sessID);//为了获得图片二维码时有session  
  33.             return “login”;  
  34.         }  
  35.         User user =(User)subject.getPrincipal();  
  36.           
  37.         //4.将user对象保存到session域中  
  38.         session.put(SysConstant.CURRENT_USER_INFO, user);  
  39.         //5.跳页面  
  40.         return SUCCESS;  
  41.     }  
  42.       
@Action("loginAction_login")
    public String login() throws Exception {
        Map<String, Object> session = ActionContext.getContext().getSession();
        Subject subject = SecurityUtils.getSubject();//shiro
        if(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)){//为浏览器分配session
            HttpServletRequest 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);//为了获得图片二维码时有session
            return "login";
        }
        User user =(User)subject.getPrincipal();

        //4.将user对象保存到session域中
        session.put(SysConstant.CURRENT_USER_INFO, user);
        //5.跳页面
        return SUCCESS;
    }
    

这里实际上页面也悄悄工作了

  1. <script>  
  2. function changeCode(){  
  3.     ("#erweima").attr('src','{ctx}/mobile/MobileCode?t=’+new Date().getTime());//选择二维码时直接去替换二维码图片  
  4. }  
  5. </script>  
  6. <script type=“text/javascript” src=“http://cdn.goeasy.io/goeasy.js”></script>  
  7. <script type=“text/javascript”>  
  8.         var goEasy = new GoEasy({  
  9.              appkey: ‘BC-c9196bffff9b4fcabd70a200f95a51d2’  
  10.         });  
  11.         goEasy.subscribe({  
  12.             channel: ’${sessID }’,//这里绑定sessionid保证推送是指定用户  
  13.             onMessage: function(message){  
  14.                   
  15.                  location.reload()  
  16.             }  
  17.         });  
  18.         </script>  
  19.         
  20. </head>  
<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>



  1. public class QRCodeUtil extends BaseAction{    
  2.       
  3.     @Action(value=“MobileCode”)  
  4.     public void getcode(){//生成二维码  
  5.         HttpServletResponse response;  
  6.         String urls;  
  7.         Hashtable<EncodeHintType, String> hints;  
  8.         BitMatrix matrix;  
  9.         try {  
  10.             response = (HttpServletResponse)  
  11.                     ActionContext.getContext().get(org.apache.struts2.StrutsStatics.HTTP_RESPONSE);  
  12.              Jedis jedis =new Jedis(“192.168.123.101”);  
  13.                 HttpServletRequest request = ServletActionContext.getRequest();  
  14.                 String sessID = (String) session.get(”ssid”);  
  15.                 String id = request.getSession().getId();  
  16.                 MySessionContext.AddSession(request.getSession());  
  17.              String key = Encrypt.md5(UUID.randomUUID().toString(), ”cao”);  
  18.             jedis.set(key, sessID, ”NX”“EX”1800);  
  19.                
  20.             urls = ”http://192.168.123.96:8080/test/mobileAutoLog?parms=”+key;//这是手机端扫码的结果  
  21.             hints = new Hashtable<EncodeHintType, String>();    
  22.     
  23.             hints.put(EncodeHintType.CHARACTER_SET, ”UTF-8”);    
  24.     
  25.             matrix = null;  
  26.                matrix = new MultiFormatWriter().encode(urls,    
  27.                         BarcodeFormat.QR_CODE, 300300, hints);    
  28.                MatrixToImageWriter.writeToStream(matrix, ”jpg”, response.getOutputStream());  
  29.         } catch (Exception e1) {  
  30.             // TODO Auto-generated catch block  
  31.             e1.printStackTrace();  
  32.         }    
  33.     
  34.           
  35.     
  36.     }    
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 block
            e1.printStackTrace();
        }  



    }  


然后假装扫码成功

我不得不插一段安卓代码了。。。

  1. public void ineedLogin(View v){//扫码成功  
  2.         SharedPreferences sharedPreferences = getSharedPreferences(”userinfo”1);  
  3.         token = sharedPreferences.getString(”username”“”);  
  4.           
  5.          
  6.         try {  
  7.             GetDataFromService();  
  8.         } catch (Exception e) {  
  9.             e.printStackTrace();  
  10.         }  
  11.     }  
  12.     private void GetDataFromService() throws   Exception{  
  13.         RequestParams params = new RequestParams(result+“&username=”+token);//去访问浏览器发过来的请求,并且拼接上用户的用户名。  
  14.         x.http().post(params, new Callback.CacheCallback<String>() {  
  15.   
  16.             @Override  
  17.             public boolean onCache(String result) {  
  18.                 return false;  
  19.             }  
  20.   
  21.             @Override  
  22.             public void onSuccess(String result) {  
  23.   
  24.             }  
  25.   
  26.             @Override  
  27.             public void onError(Throwable ex, boolean isOnCallback) {  
  28.   
  29.             }  
  30.   
  31.             @Override  
  32.             public void onCancelled(CancelledException cex) {  
  33.   
  34.             }  
  35.   
  36.             @Override  
  37.             public void onFinished() {  
  38.   
  39.             }  
  40.         });  
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>() {

            @Override
            public boolean onCache(String result) {
                return false;
            }

            @Override
            public void onSuccess(String result) {

            }

            @Override
            public void onError(Throwable ex, boolean isOnCallback) {

            }

            @Override
            public void onCancelled(CancelledException cex) {

            }

            @Override
            public void onFinished() {

            }
        });

其实我这里选了一个比较low的。。我为了省事,安卓直接拼了username过去。。还用了个Xutils…搞得重写了很多方法。。别笑我。。哈哈哈哈

好了我们再来看扫码成功的action

  1. Jedis jedis =new Jedis(“192.168.123.101”);  
  2.          String jedisParms = jedis.get(parms);  
  3.           
  4.          if(jedisParms!=null&&!jedisParms.equals(“”)){//去看redis是否有手机端传过来这个码,  
  5.              List<User> find = userService.find(new Specification<User>() {  
  6.                   
  7.                 @Override  
  8.                 public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {  
  9.                   
  10.                     return cb.equal(root.get(“userName”).as(String.class),username);  
  11.                 }  
  12.             });  
  13.              User u1 = find.iterator().next();//拿到用户信息  
  14.               
  15.              HttpSession session = MySessionContext.getSession(jedisParms);//拿到session  
  16.              session.setAttribute(SysConstant.CURRENT_USER_INFO, u1);  
  17.                
  18.               
  19.               
  20.     final String APP_KEY=“BC-c9196bffff9b4fcabd70a200f95a51d2”;  
  21.        
  22.         GoEasy goEasy =new GoEasy(APP_KEY);  
  23.        goEasy.publish(jedisParms,”heh” ); //直接推送前端  
  24.        
  25.             return NONE;  
  26.          }else{  
  27.              System.out.println(”验证失败”);  
  28.                
  29.          }  
  30.     } catch (Exception e) {  
  31.         // TODO Auto-generated catch block  
  32.         e.printStackTrace();  
  33.     }  
  34.     return “error”;  
  35. }  
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>() {

                @Override
                public 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 block
        e.printStackTrace();
    }
    return "error";
}

前端收到推送之后会刷新页面,并且session里面已经有值,那么会走登录验证的方法,session有值的方法。

我们再来看shiro,这里当时我有点懵,因为shiro实际上我用的不是很熟悉,就知道它运行的流程,当时不知道怎么才能让他验证通过,所以走了很多次shiro的登录方法,如果有别的好办法!也希望大家告诉我!!!

  1. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {  
  2.         Map<String, Object> session = ActionContext.getContext().getSession();  
  3.         User object = (User) session.get(SysConstant.CURRENT_USER_INFO);  
  4.         if(object!=null){//手机  
  5.             final String username = object.getUserName();  
  6.             List<User> findUser = userService.find(new Specification<User>() {  
  7.   
  8.                 @Override  
  9.                 public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {  
  10.                     // TODO Auto-generated method stub  
  11.                     return cb.equal(root.get(“userName”).as(String.class), username);  
  12.                 }  
  13.             });  
  14.             return new SimpleAuthenticationInfo(findUser,findUser.get(0).getPassword(),this.getName());  
  15.         }else{//电脑  
  16.            
  17.         UsernamePasswordToken  userNamePassword=(UsernamePasswordToken) arg0;  
  18.         final String username = userNamePassword.getUsername();  
  19.         List<User> findUser = userService.find(new Specification<User>() {  
  20.   
  21.             @Override  
  22.             public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {  
  23.                 // TODO Auto-generated method stub  
  24.                 return cb.equal(root.get(“userName”).as(String.class), username);  
  25.             }  
  26.         });  
  27.         if(findUser!=null && findUser.size()!=0){  
  28.               
  29.             return new SimpleAuthenticationInfo(findUser,findUser.get(0).getPassword(),this.getName());  
  30.         }  
  31.         }  
  32.         return null;  
  33.     }  
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>() {

                @Override
                public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    // TODO Auto-generated method stub
                    return 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>() {

            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                // TODO Auto-generated method stub
                return 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是在这个密码比较器里加的,加了扫码之后,页面出过来明文我就直接加密了。所以密码比较器里面,直接比较就可以了


  1. public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {  
  2.     UsernamePasswordToken uToken =(UsernamePasswordToken) token;  
  3.     String en =new String(uToken.getPassword());  
  4.     return equals(en, info.getCredentials());  
  5. }  
  public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { 
UsernamePasswordToken uToken =(UsernamePasswordToken) token;
String en =new String(uToken.getPassword());
return equals(en, info.getCredentials());
}


到此java扫码登录完成!

如果各位有别的好思路,希望也分享给我。

文章转载至:http://blog.csdn.net/lawsonjin/article/details/76856025

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值