java掃碼登入__掃碼登入

來源:互聯網
上載者:User

這篇博文主要記錄我實現掃碼登入的步驟,及代碼。其實之前從網上搜了很久掃碼登入,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>


這個實際上沒啥必要。。。直接通過jssionid擷取就可以了。當時沒想到


登入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掃碼登入完成。

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.