Spring cookie 實戰

測試環境搭建

使用Springboot構建web server, 在測試方法中打印接收的cookie。

@RestController
@RequestMapping("/register/test/service")
public class TestService {
    private Log logger = LogFactory.getLog(TestService.class);
//   使用HttpServletRequest 獲取cookie
    @RequestMapping(value = "/ping", method = RequestMethod.GET)
    public Response ping(HttpServletRequest httpRequest, HttpServletResponse httpServletResponse) throws IOException {

        Cookie[] cookies = httpRequest.getCookies();
        logger.info("cookies info"+JsonUtils.toJson(cookies));
        //Mice
        return new Response().setData("OK!!!");
    }
}

Postman開起Interceptor,在以下圖所示

輸URL: http://localhost:8080/register/test/service/ping
Header:Cookie:test=hello(name= test, value=hello的cookie)html

測試結果

返回cookie, Cookie在使用期限內,一值存在,在服務器端能夠修改cookie的生命週期
前端

Cookie的幾點常識

//文本數據明文,登錄分配,用於後臺校驗識別不一樣的用戶java

簡單地說,cookie就是瀏覽器儲存在用戶電腦上的一小段文本文件。cookie 是純文本格式,不包含任何可執行的代碼。一個web頁面或服務器告知瀏覽器按照必定規範來儲存這些信息,並在隨後的請求中將這些信息發送至服務器,Web服務器就可使用這些信息來識別不一樣的用戶。大多數須要登陸的網站在用戶驗證成功以後都會設置一個cookie,只要這個 cookie 存在並能夠,用戶就能夠自由瀏覽這個網站的任意頁面。再次說明,cookie 只包含數據,就其自己而言並不有害。web

//區分訪問web服務器的來源,維護狀態
爲何須要Cookie?
由於HTTP協議是無狀態的,對於一個瀏覽器發出的屢次請求,WEB服務器沒法區分是否是來源於同一個瀏覽器。因此,須要額外的數據用於維護會話。 Cookie 正是這樣的一段隨HTTP請求一塊兒被傳遞的額外數據。spring

//存儲大小受限
Cookie 的限制。 大多數瀏覽器支持最大爲 4096 字節的 Cookie。因爲這限制了 Cookie 的大小,最好用 Cookie 來存儲少許數據,或者存儲用戶 ID 之類的標識符。用戶 ID 隨後即可用於標識用戶,以及從數據庫或其餘數據源中讀取用戶信息。 瀏覽器還限制站點能夠在用戶計算機上存儲的 Cookie 的數量。大多數瀏覽器只容許每一個站點存儲 20 個 Cookie;若是試圖存儲更多 Cookie,則最舊的 Cookie 便會被丟棄。有些瀏覽器還會對它們將接受的來自全部站點的 Cookie 總數做出絕對限制,一般爲 300 個。數據庫

詳細描述見下文
http://bubkoo.com/2014/04/21/http-cookies-explained/apache

Java Spring Read Cookie

使用CookieVlaue標籤來獲取指定name的Cookie編程

//   使用HttpServletRequest 獲取cookie
@RequestMapping(value = "/ping", method = RequestMethod.GET)
public Response ping(@CookieValue("test") String fooCookie) throws IOException {
    //Mice
    return new Response().setData("OK, cookieValue=!!!" + fooCookie);
}

在上面的的代碼中若是CooKie不存在,會拋出返回異常:瀏覽器

{
  "timestamp": 1466584427218,
  "status": 400,
  "error": "Bad Request",
  "exception": "org.springframework.web.bind.ServletRequestBindingException",
  "message": "Missing cookie 'majun' for method parameter of type String",
  "path": "/register/test/service/ping"
}

能夠經過設置默認值來解決這個異常,若是業務上不呈現這個異常的話!!springboot

使用HttpServletRequest能夠獲取Cookie列表

Java Spring Create Cookie

使用HttpServletResponse, Cookie類,

//   使用HttpServletResponse增長cookie, cookie會返回給前端
@RequestMapping(value = "/getCookie", method = RequestMethod.GET)
public Response getCookie(HttpServletResponse httpServletResponse) throws IOException {
    Cookie cookie = new Cookie("majun", "xiaoya");
    cookie.setMaxAge(10); //設置cookie的過時時間是10s
    httpServletResponse.addCookie();
    return new Response().setData("allocate cookie success!!!");
}

若是建立的Cookie (name相同)已經存在,那麼新的Cookie會覆蓋老的cookie。

能夠在Postman看到Cookie的返回信息

攔截器和Cookie

攔截器是什麼?
攔截器的做用在於對處理器進行預處理和後處理,相似於filter。攔截器的原理詳見:
http://www.cnblogs.com/fangjian0423/p/springmvc-interceptor.html

攔截器的使用場景
一、日誌記錄:記錄請求信息的日誌,以便進行信息監控、信息統計、計算PV(Page View)等。
二、權限檢查:如登陸檢測,進入處理器檢測檢測是否登陸,若是沒有直接返回到登陸頁面;
三、性能監控:有時候系統在某段時間莫名其妙的慢,能夠經過攔截器在進入處理器以前記錄開始時間,在處理完後記錄結束時間,從而獲得該請求的處理時間(若是有反向代理,如apache能夠自動記錄);
四、通用行爲:讀取cookie獲得用戶信息並將用戶對象放入請求,從而方便後續流程使用,還有如提取Locale、Theme信息等,只要是多個處理器都須要的便可使用攔截器實現。
五、OpenSessionInView:如Hibernate,在進入處理器打開Session,在完成後關閉Session。
…………本質也是AOP(面向切面編程),也就是說符合橫切關注點的全部功能均可以放入攔截器實現。

Springboot實現攔截器

定義攔截面類

package com.im.server.Interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created by majun on 16/6/22.
 */
public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {

        System.out.println(">>>MyInterceptor>>>>>>>在請求處理以前進行調用(Controller方法調用以前)");
        Cookie[] cookies = httpServletRequest.getCookies();
        if (cookies == null || cookies.length == 0) {
            throw new Exception("illegal Login");
        }
        try {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("USER_TOKEN")) {
                    //User user =
                    httpServletRequest.setAttribute("USER_TOKEN", "{name: GUHUA, age: 20}");
                    return true;
                }
            }
            throw new Exception("illegal Login");
        } catch (Exception exp) {
            throw exp;
        }
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println(">>>MyInterceptor>>>>>>>請求處理以後進行調用,可是在視圖被渲染以前(Controller方法調用以後)");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println(">>>MyInterceptor>>>>>>>在整個請求結束以後被調用,也就是在DispatcherServlet 渲染了對應的視圖以後執行(主要是用於進行資源清理工做)");
    }
}

配置攔截器:繼承WebMvcConfigurerAdapter類便可

package com.im.server.conf;

import com.im.server.Interceptor.MyInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/register/test/service/**");
        super.addInterceptors(registry);
    }

}

控制器中獲取USER_TOKEN對應的用戶內容

//   使用HttpServletResponse增長cookie, cookie會返回給前端
@RequestMapping(value = "/getUserInfo", method = RequestMethod.GET)
public Response getUser(HttpServletRequest httpServletRequest) throws IOException {
    Object user_token = httpServletRequest.getAttribute("USER_TOKEN");
    return new Response().setData(user_token);
}

測試結果

下面的連接詳細講了Spring mvc攔截器的實現原理: http://www.cnblogs.com/fangjian0423/p/springmvc-interceptor.html

相關文章
相關標籤/搜索