sso系統使用

一:什麼是sso(single sign on) ? html

  sso(單點登陸系統)簡單說就是客戶端第一次訪問應用1的時候,因爲沒有登陸,會被引導到登陸頁面進行登陸,若是登陸校驗經過,將返回一個認證信息ticket,做爲認證憑據。下次客戶端訪問應用2的時候,發送的url請求會攜帶着ticket做爲本身的認證憑據,服務器會將該請求攜帶的ticket交給認證中心進行比對,檢驗,若是檢驗經過,應用2在能夠不登陸的狀況下訪問內部的資源信息。ajax

 

二:單點登陸系統的整個登陸過程redis

 

(1)傳統登陸方式(單應用下)json

 

圖一:爲傳統的登陸方式。在一個工程下這套登陸機制是沒有問題的。可是集羣環境下會出現要求用戶屢次登陸的狀況跨域

 

如何解決集羣環境中用戶屢次登陸的狀況?tomcat

解決屢次登陸的方案有兩種:就是解決session共享的問題服務器

1.配置tomcat集羣,在tomcat中配置session共享(session複製),可是問題是tomcat部署的節點過多,會出現性能問題。因此通常不適用這種方式cookie

2.可使用session服務器,是每一個節點保持無狀態,保存session信息。模擬session。session

單點登陸就是爲了解決session共享問題提出的一套解決方案。使用redis模擬session,實現session的統一管理。app

(2)使用單點登陸的業務流程

 

 

      

 

 

 

 登陸流程解析:

第一步:第一次訪問,進入登陸系統輸入用戶名密碼進行驗證登陸,若是登陸成功,生成Token對象,做爲認證令牌(token至關於原來的jsessionid字符串,這裏使用uuid)  

第二步:將返回的token對象信息存入redis服務器。key 就是token , value就是登陸用戶的信息

第三步:既然是模擬session,因此也須要設置key的過時時間。

第四步:將token(存儲的key)寫入cookie中,做爲用戶請求的url參數信息

第五步:用戶第二次訪問,首先檢查用戶是否登陸,將寫入cookie中的token做爲請求參數,服務器會從url中解析token的值,而後將解析的token值做爲key查詢redis服務器;若是查詢結果爲空,表示session已通過期,要求客戶端跳轉到登陸頁面完成登陸操做;若是查詢結果不爲空,須要將查詢的信息(登陸用戶的信息)做爲對象返回,而後從新設置key的過時時間。

第六步:解決跨域的問題,使用js發送ajax請求, 使用jsonp解決跨域問題。須要服務器返回的數據格式爲mycallback:{id:xx,name:xx},因此將返回的json數據進行拼接成要求的格式便可。

三:登陸過程的核心代碼

    @Override
    public E3Result login(String username, String password) {
        try {
            TbUserExample example = new TbUserExample();
            Criteria criteria = example.createCriteria();
            criteria.andUsernameEqualTo(username);
            List<TbUser> list = userMapper.selectByExample(example);
            if (list == null || list.size() == 0) {
                // 登陸失敗
                return E3Result.build(400, "用戶名或密碼錯誤");
            }
            //得到用戶對象
            TbUser user = list.get(0);
            //校驗用戶密碼
            if(!(user.getPassword()).equals(DigestUtils.md5Hex(password.getBytes()))) {
                //校驗失敗
                return E3Result.build(400, "用戶名或者密碼錯誤");
            }

            //登陸成功
            //1.建立token對象,使用uuid
            String token = UUID.randomUUID().toString();
            //2.將uuid做爲key,用戶信息做爲value值存入redis中
            jedisClient.set("USER_INFO:"+token, JsonUtils.objectToJson(user));
            //3.設置過時時間,半小時
            jedisClient.expire("USER_INFO:"+token, 1800);
            
            //4.返回登陸成功的信息
            
            return E3Result.ok(token);
            
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
View Code

解決跨域問題的服務端

    @RequestMapping(value = "/user/token/{token}", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public String getTokenName(@PathVariable String token, String callback) {
        E3Result result = tokenService.getToken(token);
        if (StringUtils.isNotBlank(callback)) {
            // 拼接成頁面須要的數據給事
            // mycall({id:1,name:z});
            String json = callback + "(" + JsonUtils.objectToJson(result) + ");";
            System.out.println(json);
            return json;
        }
        return JsonUtils.objectToJson(result);
    }

客戶端代碼:

var E3MALL = {
    checkLogin : function(){
    //COOKIE_TOKEN_KEY設置的cookie的name值 var _ticket = $.cookie("COOKIE_TOKEN_KEY"); if(!_ticket){ return ; } $.ajax({ url : "http://localhost:8088/user/token/" + _ticket, dataType : "jsonp", type : "GET", success : function(data){ if(data.status == 200){ var username = data.data.username; var html = username + ",歡迎!
<a href=\"http://www.e3mall.cn/user/logout.html\" class=\"link-logout\">[退出]</a>"; $("#loginbar").html(html); } } }); } } $(function(){ // 查看是否已經登陸,若是已經登陸查詢登陸信息 E3MALL.checkLogin(); });
相關文章
相關標籤/搜索