Ajax Cross-domain and save user information is the key and difficult point in the project of separating the front and back.
If you use the Shiro framework for permission control in the background, you need to use the Cookie+session mode to save the user's information.
In the previous article, "in the back-and-forth project, how the Ajax Cross-domain request comes with cookies," I specifically wrote how to carry cookies in the context of Ajax Cross-domain Use this method to enable Cross-domain requests to carry cookies to use Shrio sessions (Session management systems) in a project that is detached from the back and forth.
But since that approach is almost as tricky as changing access-control-allow-origin from * to "null" is not universally acknowledged by all front-end Ajax frameworks, we need a better model for using session.
In the traditional back-and-forth separation mode, we usually add a request header authorization to the request header, whose value is a string of encrypted information or keys, in the background through the reading of the request header value, get the user's information.
In such a pattern, it is usually the developer's own design of the session or encryption to read and save the user information, while in Shiro, the integration of the rights control and user management in its session system, which means that we can only through his provisions of the session+ Cookie to hold the user information, in which case the Shiro is used in a project that is separated from the back and forth.
Through the query of the data and the interpretation of the Shiro design pattern, I found that Shiro is just as real as the servlet. The ID of a session conversation is stored in a cookie and then the ID of the sessions is fetched in each request, This allows you to get the user information stored in the specified session.
My idea is to get the key in the request header authorization by rewriting the method in the Shiro to get the SessionID in the cookie, while the key stores the login as the return SessionID, which enables the Shiro framework to be used in a project separated from the back and forth.
The next step is the code demo (using Springmvc+shiro), which only pastes the core code:
The first is the login code:
@ResponseBody @RequestMapping (value = "/login", method = Requestmethod.post, produces = "application/json;charset= Utf-8 ") public string login (@RequestParam (required = False) string username, @RequestParam (re
quired = false) String Password {jsonobject jsonobject = new Jsonobject ();
Subject Subject = Securityutils.getsubject ();
Password = md5tools.md5 (password);
Usernamepasswordtoken token = new Usernamepasswordtoken (username, password); try {//Login, authentication Subject.login (token); ONLINESESSIONM
Anager.addonlinesession (Subject.getsession (). GetId ());
User user = Userservice.getuserbyloginname (token.getusername ()); //storing user information in session subject.getsession () setattribute ("Userlogin")
, user);
jsonobject.put ("error", 0); &NBsp
Jsonobject.put ("msg", "Login Success"); //return SessionID as token Jsonobject.put ("token", Subject.getsession (
). GetId ());
catch (Incorrectcredentialsexception e) {throw new Jsonexception ("Username or password error", 405);
catch (Lockedaccountexception e) {throw new Jsonexception ("Login failed, the user has been Frozen", 405);
catch (Authenticationexception e) {throw new Jsonexception ("Username or password error", 405);
return jsonobject.tostring (); }
Then rewrite the Defaultwebsessionmanager GetSessionID method
Package com.cangshi.shiro.ssesion;
Import Org.apache.shiro.web.servlet.ShiroHttpServletRequest;
Import Org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
Import Org.apache.shiro.web.util.WebUtils;
Import Org.slf4j.Logger;
Import Org.slf4j.LoggerFactory;
Import Javax.servlet.ServletRequest;
Import Javax.servlet.ServletResponse;
Import Javax.servlet.http.HttpServletRequest;
Import java.io.Serializable; /** * Created by Palerock/public class SessionManager extends Defaultwebsessionmanager {private static final Log
Ger log = Loggerfactory.getlogger (Defaultwebsessionmanager.class);
Private String authorization = "Authorization";
/** * Overrides fetch SessionID method call Current Manager Fetch method * @param request * @param response * @return * * @Override protected Serializable GetSessionID (ServletRequest request, servletresponse response) {return this
. Getreferencedsessionid (Request, response); /** * Get SessionID from Request * * @param request * @param response * @return/private Serializable Getreferencedsessionid (servletreque
St request, servletresponse Response) {String id = this.getsessionidcookievalue (request, response);
if (ID!= null) {Request.setattribute (Shirohttpservletrequest.referenced_session_id_source, "Cookie");
else {id = this.geturipathsegmentparamvalue (request, "Jsessionid"); if (id = = NULL) {//Get the session ID in the request Header = Webutils.tohttp (Request). GetHeader (This.authoriza
tion);
if (id = = null) {String name = This.getsessionidname ();
id = request.getparameter (name);
if (id = = NULL) {id = request.getparameter (name.tolowercase ()); }} if (id!= null) {Request.setattribute (shirohttpservletreque St. Referenced_seSsion_id_source, "url"); } if (id!= null) {Request.setattribute (shirohttpservletrequest.referenced_session_id, id)
;
Request.setattribute (Shirohttpservletrequest.referenced_session_id_is_valid, boolean.true);
} return ID;
}//Copy Super Private String Getsessionidcookievalue (servletrequest request, servletresponse response) { if (!this.issessionidcookieenabled ()) {Log.debug ("Session ID Cookie ' disabled-session ID")
Quired from a request cookie. ");
return null; Or else if (! Request instanceof HttpServletRequest)) {log.debug ("The current request is not a httpservletrequest-cannot get Session ID Cookie.
Returning null. ");
return null;
else {HttpServletRequest HttpRequest = (httpservletrequest) request;
Return This.getsessionidcookie (). ReadValue (HttpRequest, webutils.tohttp (response)); }//Copy Super private string Geturipathsegmentparamvalue (ServletRequest servletrequest, string param Name} {if (!) (
ServletRequest instanceof HttpServletRequest)) {return null;
else {HttpServletRequest request = (httpservletrequest) servletrequest;
String uri = Request.getrequesturi ();
if (URI = = null) {return null;
else {int querystartindex = Uri.indexof (63);
if (querystartindex >= 0) {uri = uri.substring (0, Querystartindex);
int index = Uri.indexof (59);
if (Index < 0) {return null;
else {String TOKEN = paramname + "=";
URI = uri.substring (index + 1);
index = Uri.lastindexof (TOKEN);
if (Index < 0) {return null; else {uri = uri.substring (index + token.length ());
index = Uri.indexof (59);
if (index >= 0) {uri = uri.substring (0, index);
} return URI; }}}//Copy Super Private String Getsessionidname () {Strin G name = This.getsessionidcookie ()!= null?
This.getsessionidcookie (). GetName (): null;
if (name = = null) {name = ' Jsessionid ';
} return name;
}
}
When overriding this method, a private method of the parent class is invoked, but the private method cannot be overridden, so the purpose of the rewrite is to invoke the private method of the subclass's same name, which is the Getreferencedsessionid method, in which the steps to get the SessionID In which three private methods of the parent class were invoked, Getsessionidcookievalue, Geturipathsegmentparamvalue, Getsessionidname, which is what I use the copy super callout, This is part of my way of copying the parent class so that I can use the cookie+session mode without using AJAX, and we include in the step the part that gets the SessionID from the request header:
Gets the session ID in the request header
= webutils.tohttp (Request). GetHeader (this.authorization);
When the ID is present, the ID is not obtained from the cookie, which naturally achieves the purpose of obtaining the SessionID through the authorization request header and obtaining the session.
The next step is the configuration Session Manager in the XML in spring
<!--Session Manager-->
<bean id= "SessionManager" class= "Com.cangshi.shiro.ssesion.SessionManager" >
<!--Other related settings-->
</bean>
This allows us to login to get token in a cross-domain Ajax request and then add Authorization:[token to the request header of the next request to use Shrio's own session manager to use Shiro permission control.