安卓登陸以及會話保持的解決方案

項目作到一半技術經理辭職了,留個爛攤子。web基本已作完,安卓的app要新寫,項目開發完作個總結,這東西已是很久前作的了。html

登陸接口很快就寫好了,登陸成功後用戶信息是緩存再session當中的java

 /**
     * 用戶登陸
     *
     * @param user
     * @return
     */
    @RequestMapping(value = "doLogin")
    @ResponseBody
    public Map doLogin(User user, HttpServletRequest request) {
        Map result = Maps.newHashMap();
        try {
            LoginResult flag = FrontUserUtils.doLogin(user, request);
            if (flag == LoginResult.登陸成功) {

                Map<String, Object> map = new HashMap<>();
                String[] propertys = new String[]{"name", "photo", "singleId"};
                for (String property : propertys) {
                    map.put(property, Reflections.invokeGetter(FrontUserUtils.getUserBySession(), property));
                }
                result.put("flag", 1);
                result.put("user", map);
                return result;
            } else if (flag == LoginResult.用戶被鎖定) {
                result.put("flag", 0);
                result.put("msg", "用戶被鎖定,請聯繫管理員!");
                return result;
            } else if (flag == LoginResult.登陸失敗) {
                result.put("flag", 0);
                result.put("msg", "帳號或密碼錯誤!");
                return result;
            }
        } catch (Exception e) {
            result.put("flag", 0);
            result.put("msg", "操做失敗!");
            e.printStackTrace();
        }
        return result;
    }
 /

 

可是登陸成功後,再調用其餘須要獲取登陸用戶信息的時候的時候發如今session中沒有,不對啊,明明自已用瀏覽器測試是OK的啊,我本身補不瞭解嘛,web

技術經理也跑了,不知道怎麼回事啊、咋整,我去問安卓,他也不懂啊,我也走吧。json

 

而後debug測試吧,用瀏覽器不這樣啊,session是同一個吶。測試一下,在後臺打印一下sessionid:瀏覽器

瀏覽器訪問接口:緩存

模擬安卓訪問接口:服務器

每次都生成了新的session,這麼搞不行啊,每次請求都生成新session,我怎麼緩存你登陸用戶的信息啊。cookie

 

而後就想辦法解決啊 ,想來想去想了兩個方案網絡

方案1:自定義身份識別方式(token),相似本身模擬sessionsession

  再用戶登陸之後,在系統內生成一個惟一的身份標識,並將此標識返回給客戶端。身份標識保存15天,若是用戶,在其餘終端登陸,或者15天超時在服務器沒有業務,將通知終端會話超時,從新登陸。

 

  後臺代碼就不貼了,使用的uuid生成的一個字符串,做爲用戶的登陸標識,將用戶信息寫入緩存,相似key :user這種方式存儲。

 

         用戶請求其餘接口的時候,會被個人一個攔截器攔截,若是發現根據字符串查詢用戶查詢不到,就會將用戶剔除系統。

攔截器:

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        User user = FrontUserUtils.getUser();
        if (user == null || user.getId() == null || user.getId().equals("")) {
            returnJson(httpServletResponse);
            return false;
        } else {
            return true;
        }
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        e.notifyAll();
    }


    private void returnJson(HttpServletResponse response) throws Exception {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=utf-8");
        try {
            Map map = new HashMap();
            map.put("flag", 0);
            map.put("msg", "登錄會話已通過期,請從新登錄!");
            JSONObject jsonObject = JSONObject.fromObject(map);
            writer = response.getWriter();
            writer.print(jsonObject);
        } catch (IOException e) {

        } finally {
            if (writer != null)
                writer.close();
        }
    }
}

這樣寫,犧牲掉了一部分系統性能,來實現安卓與服務器之間的長鏈接,由於基本攔截了全部的接口,每次都判斷是否登陸,或者登陸超時。

 

 

 

方案2:仍是使用sessionId,其實兩種方式都差很少,不過我仍是推薦這種,第一種的花同一時間用戶太多,session過多,可能致使其餘的問題。

 

web瀏覽器保持會話,是由於有session的存在,不一樣的服務器在瀏覽器請求的時候會判斷是否爲第一次請求,若是是第一次就回返回一個參數Set-Cookie,通常瀏覽器支持本身保存這個數據,這個數據也是瀏覽器與服務器保持會話的標識;

好比以百度爲例:

再次請求相同的服務器,瀏覽器會從cookie中取出這些這值,加載到瀏覽器的請求中去

 

瀏覽器若是不由用cookie的話,瀏覽器就會將服務器返回的數據保存到cookie當中去,session與cookie不清楚的,去查資料吧。

 

 安卓的訪問方式

儘管安卓可使用許多網絡框架來進行訪問,可是我不是很瞭解吶,加上公司的安卓開發也不甚瞭解,

 

我以爲他是使用httpclient相似的方式來進行訪問的,我就謝了一個代碼模擬了下安卓的請求,來獲取下服務器返回的數據,看能不能獲取到 Set-Cookie;

 

public class MainActivity {

    public static final String login_url="http://192.168.0.112:8080/login/doLogin?loginName=18866601116&password=123456zxc";

    /**
     * 安卓登陸測試
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        URL url=new URL(login_url);
        HttpURLConnection con=(HttpURLConnection) url.openConnection();
        con.setRequestMethod("GET");
        String cookieString=con.getHeaderField("Set-Cookie");
        System.out.print(cookieString);

    }
}
//控制檯輸出

 

 

  哎能夠的。就讓安卓再第一次請求服務器的時候將這個sessionid保存下來吧,緩存到手機,

而後請求後臺的時候,將保存的cookie放在httpPost的請求當中,這樣訪問服務器時,服務器就會認爲是同一個用戶了。也就是說保持了這個會話。

 

 

 

其實兩種方式的原理都差很少,若是有更好的方案,也能夠跟我說,學習嘛。

相關文章
相關標籤/搜索