JAVA——token理解

Token(令牌)机制
防止因为后退或者刷新来重复提交表单内容的Token机制

Token,就是Token(令牌)机制,最大的特点就是随机性,不可预测。一般黑客或软件无法猜测出来。

实现原理:一致性。

jsp生成表单时,在表单中插入一个隐藏字段,该字段就是保存在页面端的token字符串,同时把该字符串存入session中。等到用户提交表单时,会一并提交该隐藏的token字符串。在服务器端,查看下是否在session中含有与该token字符串相等的字符串。如果有,那么表明是第一次提交该表单,然后删除存放于session端的token字符串,再做正常业务逻辑流程;如果没有,那么表示该表单被重复提交,做非正常流程处理,可以警告提示也可以什么也不做。

那么,Token有什么作用?又是什么原理呢?

Token一般用在两个地方:

1)防止表单重复提交、
2)anti csrf攻击(跨站点请求伪造)。

两者在原理上都是通过session token来实现的。当客户端请求页面时,服务器会生成一个随机数Token,并且将Token放置到session当中,然后将Token发给客户端(一般通过构造hidden表单)。下次客户端提交请求时,Token会随着表单一起提交到服务器端。

然后,如果应用于“anti csrf攻击”,则服务器端会对Token值进行验证,判断是否和session中的Token值相等,若相等,则可以证明请求有效,不是伪造的。

不过,如果应用于“防止表单重复提交”,服务器端第一次验证相同过后,会将session中的Token值更新下,若用户重复提交,第二次的验证判断将失败,因为用户提交的表单中的Token没变,但服务器端session中Token已经改变了。

上面的session应用相对安全,但也叫繁琐,同时当多页面多请求时,必须采用多Token同时生成的方法,这样占用更多资源,执行效率会降低。因此,也可用cookie存储验证信息的方法来代替session Token。比如,应对“重复提交”时,当第一次提交后便把已经提交的信息写到cookie中,当第二次提交时,由于cookie已经有提交记录,因此第二次提交会失败。
不过,cookie存储有个致命弱点,如果cookie被劫持(xss攻击很容易得到用户cookie),那么又一次gameover。黑客将直接实现csrf攻击。

所以,安全和高效相对的。具体问题具体对待吧。

此外,要避免“加token但不进行校验”的情况,在session中增加了token,但服务端没有对token进行验证,根本起不到防范的作用。

还需注意的是,对数据库有改动的增删改操作,需要加token验证,对于查询操作,一定不要加token(查询一般都是Get 提交方式吧,这样token值就暴露了。),防止攻击者通过查询操作获取token进行csrf攻击。但并不是这样攻击者就无法获得token,只是增大攻击成本而已。

查询在后台大部分是提交条件表单的。另外token是在页面加载的时候生成的随机数吗,就是说每个页面都不一致?还是整个系统用同一个随机数?如果不一致的话,在浏览器打开两个选项卡,都进入同一个页面,这时候就会有两个token,结果就是先生成token的那个页面会验证失败跳转登录页。

但是对于查询与修改,修改一般都是要查询出来的,查询出来没有得到token,修改时拿什么token提交?
我认为页面分浏览与管理,管理的就都是有token,不知对否

Token的使用流程是:首先在服务器端生成一个随机的token值并在服务器端保存起来,然后向客户端请求的过程中把这个Token值传过去。之后页面操作完毕后向服务器提交数据的过程中又把这个Token值传回服务器端,同时比较这个Token值是否已经存在于服务器端,若存在,则此次访问是安全的,并在服务器端把这个Token值删除,若不存在,则此次访问无效。

Token的使用流程是:首先在服务器端生成一个随机的token值并在服务器端保存起来,然后向客户端请求的过程中把这个Token值传过去。之后页面操作完毕后向服务器提交数据的过程中又把这个Token值传回服务器端,同时比较这个Token值是否已经存在于服务器端,若存在,则此次访问是安全的,并在服务器端把这个Token值删除,若不存在,则此次访问无效。


在这里插入图片描述

好,了解Token的用法之后来看代码(项目中可直接粘贴使用)

(一)首先是Token工具类

package com.company.util;
import java.util.ArrayList;
import javax.servlet.http.HttpSession;
public class Token {
private static final String TOKEN_LIST_NAME = "tokenList";
public static final String TOKEN_STRING_NAME = "token";
 
private static ArrayList getTokenList(HttpSession session) {
       Object obj = session.getAttribute(TOKEN_LIST_NAME);
       if (obj != null) {
          return (ArrayList) obj;
       } else {
          ArrayList tokenList = new ArrayList();
          session.setAttribute(TOKEN_LIST_NAME, tokenList);
          return tokenList;
       }
    }
 
private static void saveTokenString(String tokenStr, HttpSession session) {
       ArrayList tokenList = getTokenList(session);
       tokenList.add(tokenStr);
       session.setAttribute(TOKEN_LIST_NAME, tokenList);
    }
 
private static String generateTokenString(){
       return new Long(System.currentTimeMillis()).toString();
    }
 
/** *//**
     * Generate a token string, and save the string in session, then return the token string.
     * @param HttpSession session
     * @return a token string used for enforcing a single request for a particular transaction.
     */
 
    public static String getTokenString(HttpSession session) {
       String tokenStr = generateTokenString();
       saveTokenString(tokenStr, session);
       return tokenStr;
    }
 
/** *//**
     * check whether token string is valid. if session contains the token string, return true. 
     * otherwise, return false.
     * @param String tokenStr
     * @param HttpSession session
     * @return true: session contains tokenStr; false: session is null or tokenStr is id not in session
     */
 
    public static boolean isTokenStringValid(String tokenStr, HttpSession session) {
       boolean valid = false;
       if(session != null){
          ArrayList tokenList = getTokenList(session);
          if (tokenList.contains(tokenStr)) {
             valid = true;
             tokenList.remove(tokenStr);
          }
       }
       return valid;
    }
}

(二)JSP页面中

1:先import该Token工具类

<%@ page import="com.company.util.Token" %> 2:在表单中添加隐藏的Token值

<form>
    <input type="hidden" name="<%=Token.TOKEN_STRING_NAME %>" value="<%=Token.getTokenString(session) %>">
</form>

(三)在服务器端Servlet中添加如下代码

if(Token.isTokenStringValid(request.getParameter(Token.TOKEN_STRING_NAME), request.getSession())){
    //To Do 业务代码
}

  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值