First, preface
Small in the previous blog to introduce you to the use of single sign-on evolution process, the last step when the small series to show you the distributed architecture. The single sign-on system is used. This blog continues to follow a blog to achieve a single sign-on system. Second, the environment preparation
Eclipse
Redis Three, Single sign-on flowchart
This is a simple single sign-on flowchart, on that Taobao, when we improve the Taobao home page is not logged in, click on the login, will jump to the user login interface. At this point the user login interface is part of our SSO system, according to the requirements of the login, will receive the user name and password, and then according to the user name query password is correct.
If not correct, jump to the login page, the prompt is incorrect;
The following steps are necessary if correct:
1. Generate a UUID as token;
2. The user information is serialized to the Redis, the stored key is token, after the storage is successful, the token is returned;
3. Store tokens in cookies;
4. Determine if there is a callback URL, if any, jump to the specified URL, if not, jump to the system homepage;
Iv. process of realization 4.1 Use of the technology
Mybatis
Spring
Springmvc
Jedis 4.2 Creating a project
To create a MAVEN project:
4.3 dependent jar packages
Pom file:
<project xmlns= "http://maven.apache.org/POM/4.0.0" xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance" xsi: schemalocation= "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < modelversion>4.0.0</modelversion> <parent> <groupId>com.dmsd</groupId> <artifactid >parent</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupid>com.dm Sd</groupid> <artifactId>sso</artifactId> <version>0.0.1-SNAPSHOT</version> < packaging>war</packaging> <dependencies> <dependency> <groupid>com.dmsd& Lt;/groupid> <artifactId>dao</artifactId> <version>0.0.1-snapshot</version > </dependency> <!--Spring-to <dependency> <groupid>org.springfra Mework</groupid> <artifactid>spring-context</artifactid> </dependency> <dependency> <GROUPID>ORG.SPRINGF
Ramework</groupid> <artifactId>spring-beans</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactid>spring-we bmvc</artifactid> </dependency> <dependency> <groupid>org.springframew ork</groupid> <artifactId>spring-jdbc</artifactId> </dependency> <d Ependency> <groupId>org.springframework</groupId> <artifactid>spring-aspects& lt;/artifactid> </dependency> <dependency> <GROUPID>ORG.SPRINGFRAMEWORK&L
T;/groupid> <artifactId>spring-context-support</artifactId> </dependency>
<dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId> Javax.servlet</groupid> <artifactId>jsp-api</artifactId> <SCOPE>PROVIDED&L T;/scope> </dependency> <!--redis clients--<dependency> <groupi
D>redis.clients</groupid> <artifactId>jedis</artifactId> </dependency>
</dependencies> <!--adding tomcat plugins--<build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactid>tomcat7-maven-plug
In</artifactid> <configuration> <port>8084</port> <path>/</path> </configuration> </plugin> </plugins> </build> </project>
4.4 Integrating the SSM framework
The integration here can refer to the pre-written SSM integration blog.
4.5 Login Logic Implementation
DAO Layer:
Direct use of the code generated by MyBatis reverse engineering.
Service Layer:
Receive parameters: User name, password.
Verify that the password is correct, generate tokens, write user information to Redis, write tokens to a cookie, and return the Systemresult entity containing tokens.
Parameters: User name, password, httpservletresponse, httpservletrequest
return value: Taotaoresult
@Service public class Loginserviceimpl implements Loginservice {@Autowired private tbusermapper usermapper;
@Autowired private jedisclient jedisclient;
@Value ("${redis_session_key}") Private String Redis_session_key;
@Value ("${session_expire}") Private Integer Session_expire; @Override Public systemresult Login (string username, string password, httpservletrequest request, Httpserv
Letresponse response) {//Verify user name password is correct tbuserexample example = new Tbuserexample ();
Criteria = Example.createcriteria ();
Criteria.andusernameequalto (username);
list<tbuser> list = Usermapper.selectbyexample (example);
Fetch user Information if (list = = NULL | | list.isempty ()) {return Taotaoresult.build (400, "Username or password error");
} tbuser user = List.get (0); Verify the password if (!user.getpassword (). Equals (Digestutils.md5digestashex (Password.getbytes ()))) {return SysTemresult.build (400, "User name or password error");
}//Login succeeded//Generate token String token = Uuid.randomuuid (). toString ();
Write user information to REDIS//key:redis_session:{token}//value:user to JSON user.setpassword (NULL);
Jedisclient.set (Redis_session_key + ":" + token, Jsonutils.objecttojson (user));
Set the SESSION Expiration Time Jedisclient.expire (Redis_session_key + ":" + token, session_expire);
Write Cookie Cookieutils.setcookie (request, Response, "Tt_token", TOKEN);
return Systemresult.ok (token);
}
}
Controller layer:
Url:/user/login of the request
Receive parameters: Username, password
Call service to return the Taotaoresult object.
Respond to JSON data.
@Controller public
class Logincontroller {
@Autowired
private loginservice loginservice;
@RequestMapping (value= "/user/login", Method=requestmethod.post)
@ResponseBody public
systemresult Login ( String Username, string password,
httpservletrequest request, httpservletresponse response) {
try {
Systemresult result = Loginservice.login (username, password, request, response);
return result;
} catch (Exception e) {
e.printstacktrace ();
Return Systemresult.build ($, exceptionutil.getstacktrace (e));}}}
4.6 Query user information via token
Note: According to the token to Redis query user information, if the user information does not exist stating that the session has expired, returned 400 and prompted the user session has expired. If the user is queried, the user information is returned, and the user's expiration time is updated.
Request Url:/user/token/{token}
Need to support JSONP
return: Systemresult
DAO Layer:
Access the Redis implementation using Jedis.
Service Layer:
Parameters: String Token
Query Redis based on token, query to result return user object, update expiration time. If the query does not reach the result, the return session has expired, status code 400.
return value: Systemresult
@Override public
Systemresult Getuserbytoken (String token) {
//based on token fetch user information
String JSON = Jedisclient.get (Redis_session_key + ":" + token);
Determine whether to query the result
if (Stringutils.isblank (JSON)) {
return Systemresult.build (400, "user session has expired");
}
Convert JSON to Java object
tbuser user = Jsonutils.jsontopojo (JSON, tbuser.class);
Update SESSION Expiration Time
jedisclient.expire (Redis_session_key + ":" + token, session_expire);
return Systemresult.ok (user);
Controller:
The requested Url:/user/token/{token}
The contents of the token are taken from the URL, the service is invoked to fetch the user information, and the Taotaoresult is returned. (JSON data)
@RequestMapping ("/user/token/{token}")
@ResponseBody public
Object Getuserbytoken (@PathVariable String Token, String callback) {
try {
Taotaoresult result = Loginservice.getuserbytoken (token);
Support for Jsonp call
if (Stringutils.isnotblank (callback)) {
Mappingjacksonvalue mappingjacksonvalue = new Mappingjacksonvalue (result);
Mappingjacksonvalue.setjsonpfunction (callback);
return mappingjacksonvalue;
}
return result;
} catch (Exception e) {
e.printstacktrace ();
Return Systemresult.build ($, exceptionutil.getstacktrace (e));
}
}
Home System login Jump code:
Using the Ajax cross-domain invocation, we first get the cookie stored in the browser, and then use the Ajax Jsonp to invoke the user information across the domain, because the return is Systemresult JSON form, he contains the Err, MSG, data three parts, So to get the user information is to be obtained through data.data.username.
var TT = Taotao = {
checklogin:function () {
var _ticket = $.cookie ("Tt_token");
if (!_ticket) {
return;
}
$.ajax ({
URL: "http://localhost:8084/user/token/" + _ticket,
dataType: "Jsonp",
Type: "GET",
Success:function (data) {
if (data.status = =) {
var username = data.data.username;
var html = username + ", welcome to. <a href=\ "http://www.taotao.com/user/logout.html\" class=\ "link-logout\" >[exit]</a> ";
$ ("#loginbar"). HTML (HTML);}}
);
}} $ (function () {
///See if the login is already logged in, if the login information
tt.checklogin ();
});
v. Summary
This single sign-on is mostly done using Redis. Redis is really a great caching technology. Have done a good job in many ways. In addition, this is the generation of distributed, the login system separately extracted, this idea is very good. Come on.