This blog post is mainly about the steps I make to implement a code-scanning login. In fact, search from the internet for a long time to scan code login, copy version of a lot, so the answer is on those kinds.
Let me tell you my own ideas. If there is a better opinion or I have something wrong, please point out.
First of all, I use the technology, MAVEN build project, SSH, Redis, Shiro, Goeasy push, zxing two-dimensional code generation.
The picture is a bit rough. Well, let me explain, first of all, I think that session is definitely a unique identifier for browser and server interaction, so I think SessionID can directly navigate to which user is going to scan the code,
OK, so around this, when the browser opens our web site, we getsession, so that we can give the browser a Session object first.
Next I'll show you the process in the form of code presentation
First, a listener listening to the global session is picked up from the Internet.
public class Mysessioncontext {
private static HashMap Mymap = new HashMap ();
public static synchronized void Addsession (HttpSession sessions) {
if (session!= null) {
mymap.put (session.getid (), session);
}
public static synchronized void Delsession (HttpSession sessions) {
if (session!= null) {
Mymap.remove ( Session.getid ());
}
public static synchronized HttpSession getsession (String session_id) {
if (session_id = null) return
null;< C14/>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>
This is really not necessary ... Directly through the Jssionid to get it. I didn't think.
Logon action
@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) {//
If there is session user information, go directly to verify that the mobile phone scan code User user = (user) session.get (sysconstant.current_user_info);
Subject.login (New Usernamepasswordtoken (User.getusername (), User.getpassword ()));
} if (subject.isauthenticated ()) {//Verify success directly returned successfully.
return SUCCESS;
if (Utilfuns.isempty (username)) {//The browser assigns session HttpServletRequest request = Servletactioncontext.getrequest ();
Sessid = Request.getsession (). GetId ();
Super.push (SESSID);
Request.getsession (). setattribute ("SSID", sessid);
return "Login";
try {//Login succeeded assignment 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", "Sorry, Login failed, username or password wrong ...")
");
HttpServletRequest request = Servletactioncontext.getrequest ();
Sessid = Request.getsession (). GetId ();
Super.push (SESSID),//pressure stack request.getsession (). setattribute ("SSID", sessid);//To obtain the picture two-dimensional code when there is a session return "login";
User user = (user) subject.getprincipal ();
4. Save the user object to the session domain Session.put (sysconstant.current_user_info, user);
5. Jump page return SUCCESS;
}
Here, actually, the pages work quietly.
<script>
function ChangeCode () {
$ ("#erweima"). attr (' src ', ' ${ctx}/mobile/mobilecode?t= ' +new Date (). GetTime ())//Select two-dimensional code directly to replace the two-dimensional code picture
}
</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} ',//here bound SessionID guaranteed push is the specified user
onmessage:function (message) {
Location.reload ()
}
);
</script>
public class Qrcodeutil extends baseaction{@Action (value= "Mobilecode") public void GetCode () {//Generate two-dimensional code HTTPSERVLETR
Esponse response;
String URLs;
Hashtable<encodehinttype, string> hints;
Bitmatrix Matrix; try {response = (HttpServletResponse) actioncontext.getcontext (). Get (Org.apache.struts2.StrutsStatics.HTTP_RESPON
SE);
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;//This is the result of the phone's end sweep code hints = new hashtable<
Encodehinttype, string> ();
Hints.put (Encodehinttype.character_set, "UTF-8");
Matrix = null; Matrix = new Multiformatwriter (). EncoDe (URLs, barcodeformat.qr_code, hints, MB, n);
Matrixtoimagewriter.writetostream (Matrix, "JPG", Response.getoutputstream ());
catch (Exception E1) {//TODO auto-generated catch block E1.printstacktrace (); }
}
And then pretending to sweep the code successfully
。
。
。
。
。
。
I have to plug in an android code ...
public void Ineedlogin (View v) {//Sweep code succeeded
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")//to visit the request from the browser and to splice the user's username.
x.http (). Post (params, new callback.cachecallback<string> () {
@Override public
boolean Oncache (String result) {return
false;
}
@Override public
void onsuccess (String result) {
}
@Override
the public void OnError (Throwable ex, Boolean isoncallback) {
}
@Override public
void oncancelled (Cancelledexception CeX) {
}
@ Override public
void onfinished () {
}
});
In fact, I chose a relatively low here. For the sake of convenience, Andrew spelled the username past. Also used a xutils ... There are many ways to rewrite it. Don't laugh at me. haha haha
All right, let's take a look at the sweep code's successful action.
Jedis Jedis =new Jedis ("192.168.123.101");
String jedisparms = Jedis.get (parms); if (Jedisparms!=null&&!jedisparms.equals ("")) {//To see if Redis has a cell phone pass over this code, list<user> find = Userservice.find (New specification<user> () {@Override public predicate topredicate (root<user> ro OT, criteriaquery<?> query, Criteriabuilder CB) {return cb.equal (Root.get ("UserName"). As (String.class), US
Ername);
}
}); User U1 = Find.iterator (). Next ()//Get customer information HttpSession session = Mysessioncontext.getsession (jedisparms);/Get Sessio
N Session.setattribute (Sysconstant.current_user_info, U1);
Final String app_key= "BC-C9196BFFFF9B4FCABD70A200F95A51D2";
Goeasy goeasy =new goeasy (App_key); Goeasy.publish (jedisparms, "heh");
Direct Push front return NONE;
}else{System.out.println ("Validation failed");
The catch (Exception e) {//TODO auto-generated catch block E.printstacktrace ();
return "error";}
The front end receives the push to refresh the page, and the session already has the value, then will go to the login verification method, Sessions has the value method.
We come to see Shiro, here at that time I was a bit Meng, because Shiro actually I used is not very familiar with, knew it runs the flow, at that time did not know how can let him verify through, therefore has walked many times the Shiro login method, if has other good method! I also hope you can tell me ...
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) {//Mobile phone final String username = Object.getusername (); list<user> Finduser = Userservice.find (new specification<user> () {@Override public predicate Topredi
Cate (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{//computer 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-g
enerated 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). GetP
Assword (), This.getname ());
} return null;
}
Because there is no scan code before the login, I HashMd5 is in this password comparator Riga, add a sweep code, the page came out of the clear text I directly encrypted. So in the cipher comparator, it's okay to compare directly.
public boolean Docredentialsmatch (Authenticationtoken token, AuthenticationInfo info) {
Usernamepasswordtoken Utoken = (usernamepasswordtoken) token;
String en =new string (Utoken.getpassword ());
Return equals (en, info.getcredentials ());
}
To this Java sweep code login complete.
If you have other good ideas, hope to share with me.