前端 - token 是什么?为什么每次请求头(HEADS)里要携带它?___请求时,为什么要携带token?
前端 - token 是什么?為什么每次請求頭(HEADS)里要攜帶它?
Token
token 是客戶端頻繁向服務器端請求數(shù)據(jù),服務器頻繁的去數(shù)據(jù)庫查詢用戶名和密碼進行對比,判斷用戶名和密碼正確與否,并作出相應的提示,在這樣的背景下,token 便應運而生了。
目的
token 的目的是為了減輕服務器的壓力,減少頻繁的查詢數(shù)據(jù)庫。
在前端請求后臺的 API 接口的時候,為了安全性,一般需要再用戶登錄成功之后才能發(fā)送其他請求。
因此,在用戶登錄成功之后,后臺會返回一個 token 給前端,這個時候我們就需要把 token 暫時保存在本地,每次發(fā)送請求的時候需要在 header 里邊帶上 token(無需再次帶上請求名和密碼),這個時候本地的 token 和后臺數(shù)據(jù)庫中的 token 進行一個驗證,如果兩者一致,則請求成功,否則失敗。
用什么作為 Token 標識合適
一、使用設備號/設備mac地址作為token(推薦)
客戶端:客戶端在登錄的時候獲取設備的設備號串號 / mac 地址,并將其作為參數(shù)傳遞到服務器端。
服務器:服務器接收到該參數(shù)之后,使用一個變量接收同時將其作為 token 保存數(shù)據(jù)庫,并將該 token 設置在 session 中,客戶端每次請求的時候都要統(tǒng)一攔截,并將客戶端傳遞的 token 和服務器 session 中的 token 對比,如果相同則放下,不同則拒絕。
優(yōu)點:客戶端不需要重新登錄,只要登錄一次后就能一直使用。
缺點:客戶端需要帶設備號/mac地址作為參數(shù)傳遞
二、用 session 值作為 token
客戶端:客戶端只需要攜帶用戶名和密碼即可登錄。
服務端:客戶端接收到用戶名和密碼后并判斷,如果正確就將本地獲取 sessionId 作為 token 返回給客戶端,客戶端以后只需要帶上請求數(shù)據(jù)即可。
請求時,為什么要攜帶token?
token是什么?
token攜帶在請求頭中,只有登錄請求不需要攜帶token,登錄成功后把token返回給前端,以后的請求前端需要攜帶這個token來才能請求成功!否則請求被攔截……
為什么要用它?
token的目的是減輕服務器壓力,減少數(shù)據(jù)庫請求。
如果沒有token做一層攔截的,每次請求都會去請求數(shù)據(jù)庫,如果惡意請求,很可能擊垮數(shù)據(jù)庫…
如何實現(xiàn)呢?
攔截器:寫一個類實現(xiàn)HandlerInterceptor接口,重寫preHandle方法,在方法里實現(xiàn)攔截邏輯
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 如果是OPTIONS則結(jié)束請求if (Objects.equals(request.getMethod(), HttpMethod.OPTIONS.name())) {response.setStatus(HttpStatus.OK.value());return false;}String token = request.getHeader("token");if (!hasText(token)) {handleErrorResponse(response, ResponseResultEnum.PARAM_ERROR, "can't getHeader token ");return false;}if (TEST_TOKEN.equals(token)) {return true;} } catch (JwtException e) {log.trace(e.getMessage(), e);handleErrorResponse(response, ResponseResultEnum.TOKEN_INVALID);return false;}return true;}這里的攔截,是攔截所有請求,而我們在實際開發(fā)中,要有攔截白名單,比如:登錄接口
那么如何寫攔截白名單呢?
寫一個配置類,實現(xiàn)WebMvcConfigurer接口,重寫addInterceptors方法
@Configuration public class WebConfig implements WebMvcConfigurer {private final TokenInterceptor tokenInterceptor;public WebConfig(TokenInterceptor tokenInterceptor) {this.tokenInterceptor = tokenInterceptor;}/*** 不需攔截-白名單*/private static final String[] WHITELIST = {// 登錄相關(guān)"/login/verify","/login/sms/**","/heartbeat"};@Overridepublic void addInterceptors(InterceptorRegistry registry) {List<String> patterns = Arrays.asList(WHITELIST);registry.addInterceptor(tokenInterceptor) // 攔截器實例.addPathPatterns("/**") // 攔截所有請求.excludePathPatterns(patterns); // 排除哪些請求}}small tips:
1.JWT:JSON WEB TOKEN,用于生產(chǎn)token的插件
Jwts.builder().setIssuedAt(new Date()).signWith(this.key).claim(Global.USER_CODE, userCode).claim(Global.PHONE, phone).claim(Global.UNION_NUM, unionNum).setExpiration(new Date(System.currentTimeMillis() + this.expiration)).setId(UUID.randomUUID().toString()).compact();使用以上,需要導入jar包
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.2</version><scope>runtime</scope></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.2</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.11.2</version><scope>runtime</scope></dependency>token設置多久有效期?
根據(jù)具體情況來定,失效時間寫在生成token的方法里,token的失效時間一般存在緩存或內(nèi)存中,而不會數(shù)據(jù)庫中
public String generateTokenCache(String userCode, String phone, String unionNum) {String token = generateToken(userCode, phone, unionNum);String key = String.format(RedisConstants.APP_TOKEN_KEY, userCode);redisTemplate.opsForValue().set(key, ShaKit.hashString(token), this.expiration, TimeUnit.MILLISECONDS);return token; }總結(jié)
以上是生活随笔為你收集整理的前端 - token 是什么?为什么每次请求头(HEADS)里要携带它?___请求时,为什么要携带token?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux内核杂记(11)-进程调度(6
- 下一篇: 2017年html5行业报告,云适配发布