在涉及到关键业务操作的web页面,应为当前web页面生成一次性随机令牌,作为主会话标识的补充。在执行关键业务前,应确保用户提交的一次性随机令牌与服务器端保存的一次性随机令牌匹配,以避免跨站请求伪造(CSRF)等攻击。
1、在公共JS中定义一个function 用来生成token ,然后将生成的token赋值给JSP里的隐藏域<input id="tokenValue" type="hidden"/>
前端jsp:
<html> <body style="background-color:#f8f8f8"> <div class="content"> <!-- 页面存储的token值 --> <input id="tokenValue" type="hidden"/> </div> </body> <script type="text/javascript"> $(document).ready(function(){ //生成token makeToken(); }); var dom='{"login_type":"01","oldpwd":"'+oldpwd+'",newpwd:"'+newpwd+'",name:"'+name+'",id_nbr:"'+id_nbr+'",token:"'+token+'"}'; $.ajax({ url : baseUrl+"/user/changePassword", data:"dom="+dom, cache : false, async : true, type : "POST", dataType : 'json', success : function (xmlRes){ var item = xmlRes.return_info; if(item.retcode!="0"){ // 重新生成token makeToken(); var er_msg = item.message; return alert(er_msg); } } }); </script> </html>
公共js:
//生成token function makeToken(){ var dom = '{"login_type":"01"}'; $.ajax({ url : baseUrl+"/common/makeToken", data:"dom="+dom, cache : false, async : true, type : "POST", dataType : 'json', success : function (jsonRes){ $("#tokenValue").val(jsonRes.token); } }); }
2、在后台Action 中定义一个方法用来产生token,并将token保存到session中,返回token值到前台jsp
后台CommonAction:
/** * 生成token * * @return */ public String makeToken() { TokenProcessor tokenProcessor = TokenProcessor.getInstance(); String token = tokenProcessor.generateToken(); // 将生成的token值放到session中 session.put(TokenProcessor.TOKEN_INFO, token); responseData.put("token", token); return SUCCESS; }
token处理类:
package com.waukeen.util; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random; /** * 令牌处理类 * * @author * */ public class TokenProcessor { private TokenProcessor() { } /** * 存储在session中token的key */ public static final String TOKEN_INFO = "token_info"; private static final TokenProcessor instance = new TokenProcessor(); public static TokenProcessor getInstance() { return instance; } /** * 生成token * * @return */ public String generateToken() { try { String token = System.currentTimeMillis() + new Random().nextInt(99999999) + ""; MessageDigest md = MessageDigest.getInstance("MD5"); md.update(token.getBytes()); return toHex(md.digest()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } private String toHex(byte buffer[]) { StringBuffer sb = new StringBuffer(buffer.length * 2); for (int i = 0; i < buffer.length; i++) { sb.append(Character.forDigit((buffer[i] & 240) >> 4, 16)); sb.append(Character.forDigit(buffer[i] & 15, 16)); } return sb.toString(); } }
3、前台jsp提交请求到后台,将token值传到后台,与session中的token值比对,如果一致,继续处理,如果不一致,提示“非法的请求!”
UserAction:
/** * 需要验证token的业务请求(如:修改密码) */ public String changePassword(){ // 取得前端页面传过来的token值 String token = requestData.containsKey("token") ? (String) requestData.get("token") : ""; String tokenInfo = (String) session.get(TokenProcessor.TOKEN_INFO); session.remove(TokenProcessor.TOKEN_INFO); // 将前端的token值与session中的token值比对,如果一致,继续处理,如果不一致,提示“非法的请求!” if (!token.equals(tokenInfo)) { returnInfo.setRetcode("1"); returnInfo.setMessage("非法的请求!"); return SUCCESS; } }