Redis的安裝和引用參考上一篇:Redis下載鏈接
1:什么是單點(diǎn)登錄胸嘴?
答:單點(diǎn)登錄的英文名叫做:Single Sign On(簡稱SSO)。
一般我們的模塊都是在同一個(gè)系統(tǒng)下斩祭,同一個(gè)tomcat(如圖筛谚,以商城為例)
后來為了維護(hù)和資源我們把一個(gè)系統(tǒng)拆成多個(gè)子系統(tǒng)。
而單點(diǎn)登錄就是其中的一部分停忿。
我們有多個(gè)系統(tǒng)驾讲,每個(gè)系統(tǒng)都要輸入一次賬號(hào)和密碼的話就會(huì)變得很麻煩,這時(shí)候就需要單點(diǎn)登錄席赂,只要其中一個(gè)子系統(tǒng)登錄的話吮铭,其他系統(tǒng)都能自動(dòng)登錄。最為熟悉的例子就是淘寶和天貓颅停,如果你淘寶登錄后谓晌,打開天貓就能自動(dòng)登錄無需再輸入賬號(hào)和密碼。
2:實(shí)現(xiàn)單點(diǎn)登錄的思路(整個(gè)頁面的流程)
假設(shè)兩個(gè)頁面
用戶A系統(tǒng)沒登陸癞揉,B系統(tǒng)沒登陸
這時(shí)用戶在A登陸纸肉,A生成token令牌存入cookie溺欧,redis存入已經(jīng)登錄參數(shù)
然后用戶打開B系統(tǒng)登錄頁面,B系統(tǒng)登錄頁面發(fā)送請(qǐng)求柏肪,后端通過cookie獲取到用戶在A系統(tǒng)登錄的信息
判斷獲取到的信息沒有錯(cuò)誤進(jìn)行自動(dòng)登陸
3:Demo代碼(兩個(gè)頁面的代碼是一樣的姐刁,路徑什么的改改就行了)
簡單的登陸jq,ajax請(qǐng)求
前端
<body background="jquery/loginbg.jpg">
<div>
<form style="margin: auto; width:230px" class="form-signin" >
<h2 class="form-signin-heading"><font color="white">SSO1用戶登錄</font></h2>
<!-- <label>賬號(hào):</label> -->
<input type="text" id="txtUsername" class="form-control" name="username" placeholder="請(qǐng)輸入賬號(hào)" /><br/>
<!-- <label>密碼:</label> -->
<input type="password" id="txtPassword" class="form-control" name="password" placeholder="請(qǐng)輸入密碼" /><br/>
<!-- <input type="submit" value="提交" /> -->
<a class="btn btn-primary btn-block" id="tijiao">提交</a><br>
<!-- <button class="btn btn-primary btn-block" id="tijiao">提交</button><br> -->
<button class="btn btn-primary btn-block" >重置</button><br>
<!-- <input type="reset" value="重置" /> -->
<input type="button" class="btn btn-primary btn-block" value="注冊(cè)" onclick="window.location.href='add.jsp';"/>
</div>
<div id="chartmain" style="width:600px; height: 400px; margin: auto; " class="form-signin"></div>
</body>
<script type="text/javascript">
$("#tijiao").click(function(){
var paramMap = {};
paramMap.username = $("#txtUsername").val();
paramMap.userpasswd = $("#txtPassword").val();
$.ajax({
type:'POST',
data:JSON.stringify(paramMap),
dataType:'JSON',
url:"user/slogin",
contentType :"application/json;charset=UTF-8",
async: true,
error:function(jqXHR){
alert("發(fā)生錯(cuò)誤:"+ jqXHR.status);
},
success:function(data){
if(data){
if(data.state == "success"){
window.location.href ='index.jsp';
}else if(data.state == "fault"){
window.location.href ='login.jsp';
}
}
}
});
})
window.onload = function(){
var paramMap = {};
var i = 0;
paramMap.username = $("#txtUsername").val();
paramMap.userpasswd = $("#txtPassword").val();
$.ajax({
type:'POST',
data:JSON.stringify(paramMap),
dataType:'JSON',
url:"user/slogin",
// xhrFields: {
// withCredentials: true // 攜帶跨域cookie
// },
contentType :"application/json;charset=UTF-8",
async: true,
error:function(jqXHR){
alert("發(fā)生錯(cuò)誤:"+ jqXHR.status);
},
success:function(data){
if(data){
if(data.state == "success"){
window.location.href ='index.jsp';
}else if(data.state == "fault"){
debugger;
var str=location.href; //取得整個(gè)地址欄
var num=str.indexOf("=")
str=str.substr(num+1);
if(str!="1"||str==null){
window.location.href ='login.jsp?state=1';
}
}
}
}
});
}
</script>
后端
/**
* 登陸
* @param <Account>
* @param model
* @param session
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/slogin", method = RequestMethod.POST)
public ResultInfo slogin(@RequestBody Map<String, String> param,
HttpSession session, HttpServletRequest request,
ServletResponse response, HttpServletResponse responses)
throws Exception {
ResultInfo resultinfo = new ResultInfo();
/**
* 判斷redis是否連接成功
*/
//連接本地的 Redis 服務(wù)
@SuppressWarnings("resource")
Jedis jedis = new Jedis("localhost");
System.out.println("連接成功");
//用戶驗(yàn)證
String username = param.get("username");
String passwd = param.get("userpasswd");
if(jedis.exists("islogin")){
//判斷是否已經(jīng)登錄
if(!jedis.get("islogin").equals("1")){
// TODO: handle exception
resultinfo.setState(StateType.fault);
jedis.set("islogin", "0");
}
}else if(!jedis.exists("islogin") && username.length()==0 && passwd.length()==0){
resultinfo.setState(StateType.fault);
return resultinfo;
}
/**
* 從cookie中獲取數(shù)據(jù)
*/
Cookie[] cookies = request.getCookies();
System.out.println(cookies);
String cookievalue = null;
for(Cookie cookiexs : cookies){
if(cookiexs.getName().equals("token")){
cookievalue = cookiexs.getValue();
break;
}
}
if(cookievalue!=null){
//base64解密
String decusername = null;
String decpasswd = null;
int a = 1;
byte[] decoded = Base64Utils.decode(cookievalue.getBytes());
String decodeStr = new String(decoded,"UTF-8");
System.out.println("Base 64 解密后:" + decodeStr);
//獲取用戶名和密碼
for(int i=-1; i<=decodeStr.lastIndexOf("=");++i){
i=decodeStr.indexOf("=",i);
System.out.print(i+"\t");
if(a==1){
decusername = decodeStr.substring(i, i);
a++;
}else if(a>1){
decusername = decodeStr.substring(5,i-6);
decpasswd = decodeStr.substring(i+1, decodeStr.length()-6);
a=1;
}
System.out.println("賬號(hào)為:"+decusername+"\t"+"密碼為:"+decpasswd);
}
username = decusername;
passwd = decpasswd;
}
try {
if(username != "" && passwd !=""){
User user = userService.loginUsername(username);
if(user ==null){
resultinfo.setState(StateType.fault);
jedis.set("islogin", "0");
return resultinfo;
}else if(!user.getPassword().equals(passwd)){
resultinfo.setState(StateType.fault);
jedis.set("islogin", "0");
return resultinfo;
}
//設(shè)置token
String token = tokenset(user);
//將數(shù)據(jù)保存到cookie中
Cookie cookie = new Cookie("token", token);
//cookie.setMaxAge(600);
responses.addCookie(cookie);
//將token發(fā)送給客戶端,附帶本次全局會(huì)話的sessionId
//String allSessionId=request.getSession().getId();
//獲取sessionid
String sessionid = session.getId();
//設(shè)置狀態(tài)(通過session判斷該瀏覽器與認(rèn)證中心的全局會(huì)話是否已經(jīng)建立)烦味,生成令牌
//判斷用戶是否登錄
request.getSession().setAttribute("isLogin", username);
Map<String, String> tosession = new HashMap<String, String>();
tosession.put("sessionid", sessionid);
jedis.set("islogin", "1");
jedis.set(token,username+passwd);
jedis.expire("islogin", 120);
// jedis.expire("token", 600);
resultinfo.setData(token);
resultinfo.setState(StateType.success);
}
if(jedis.get("islogin").equals("1")){
resultinfo.setState(StateType.success);
}else{
resultinfo.setState(StateType.fault);
}
} catch (Exception e) {
// TODO: handle exception
resultinfo.setState(StateType.fault);
resultinfo.setData(e.toString());
}
return resultinfo;
}
/**
* 設(shè)置token
*/
private String tokenset(User user) {
// TODO Auto-generated method stub
String token = null;
String sign = "hitomi";
String param = "name="+user.getUsername()+"passwd="+user.getPassword()+sign;
token = Base64Utils.encodeToString(param.getBytes());
return token;
}
此代碼只是簡單的實(shí)現(xiàn)單點(diǎn)登錄的思路和功能聂使,僅供參考