java微信公众平台开发二(请求来源校验)

上次我们进行tkozen 认真的时候却没有校验请求的来源是否来自微信服务器,这次我们加上这个校验。

首先官方这样描述首先我们要编写个sha1加密的算法,网上很多例子

SHA1:

public class SHA1 {  

   private static final boolean hexcase = false;  
   private static final int chrsz = 8;  

   // 得到字符串SHA-1值的方法  
   public static String hex_sha1(String s) {  
       s = (s == null) ? "" : s;  
       return binb2hex(core_sha1(str2binb(s), s.length() * chrsz));  
   }  

   private static String binb2hex(int[] binarray) {  
       String hex_tab = hexcase ? "0123456789abcdef" : "0123456789abcdef";  
       String str = "";  

       for (int i = 0; i < binarray.length * 4; i++) {  
           char a = (char) hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xf);  
           char b = (char) hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8)) & 0xf);  
           str += (new Character(a).toString() + new Character(b).toString());  
       }  
       return str;  
   }  

   private static String binb2str(int[] bin) {  
       String str = "";  
       int mask = (1 << chrsz) - 1;  

       for (int i = 0; i < bin.length * 32; i += chrsz) {  
           str += (char) ((bin[i >> 5] >>> (24 - i % 32)) & mask);  
       }  
       return str;  
   }  

   private static int[] core_sha1(int[] x, int len) {  
       int size = (len >> 5);  
       x = strechbinarray(x, size);  
       x[len >> 5] |= 0x80 << (24 - len % 32);  
       size = ((len + 64 >> 9) << 4) + 15;  
       x = strechbinarray(x, size);  
       x[((len + 64 >> 9) << 4) + 15] = len;  

       int[] w = new int[80];  
       int a = 1732584193;  
       int b = -271733879;  
       int c = -1732584194;  
       int d = 271733878;  
       int e = -1009589776;  

       for (int i = 0; i < x.length; i += 16) {  
           int olda = a;  
           int oldb = b;  
           int oldc = c;  
           int oldd = d;  
           int olde = e;  

           for (int j = 0; j < 80; j++) {  
               if (j < 16) {  
                   w[j] = x[i + j];  
               } else {  
                   w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);  
               }  

               int t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j)));  

               e = d;  
               d = c;  
               c = rol(b, 30);  
               b = a;  
               a = t;  
           }  

           a = safe_add(a, olda);  
           b = safe_add(b, oldb);  
           c = safe_add(c, oldc);  
           d = safe_add(d, oldd);  
           e = safe_add(e, olde);  
       }  

       int[] retval = new int[5];  

       retval[0] = a;  
       retval[1] = b;  
       retval[2] = c;  
       retval[3] = d;  
       retval[4] = e;  

       return retval;  
   }  

   private static int rol(int num, int cnt) {  
       return (num << cnt) | (num >>> (32 - cnt));  
   }  

   private static int safe_add(int x, int y) {  
       int lsw = (int) (x & 0xffff) + (int) (y & 0xffff);  
       int msw = (x >> 16) + (y >> 16) + (lsw >> 16);  

       return (msw << 16) | (lsw & 0xffff);  
   }  

   private static int sha1_ft(int t, int b, int c, int d) {  
       if (t < 20)  
           return (b & c) | ((~b) & d);  

       if (t < 40)  
           return b ^ c ^ d;  

       if (t < 60)  
           return (b & c) | (b & d) | (c & d);  

       return b ^ c ^ d;  
   }  

   private static int sha1_kt(int t) {  
       return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : (t < 60) ? -1894007588 : -899497514;  
   }  

   public static String str_sha1(String s) {  
       s = (s == null) ? "" : s;  

       return binb2str(core_sha1(str2binb(s), s.length() * chrsz));  
   }  

   private static int[] str2binb(String str) {  
       str = (str == null) ? "" : str;  

       int[] tmp = new int[str.length() * chrsz];  
       int mask = (1 << chrsz) - 1;  

       for (int i = 0; i < str.length() * chrsz; i += chrsz) {  
           tmp[i >> 5] |= ((int) (str.charAt(i / chrsz)) & mask) << (24 - i % 32);  
       }  

       int len = 0;  
       for (int i = 0; i < tmp.length && tmp[i] != 0; i++, len++)  
           ;  

       int[] bin = new int[len];  

       for (int i = 0; i < len; i++) {  
           bin[i] = tmp[i];  
       }  

       return bin;  
   }  

   private static int[] strechbinarray(int[] oldbin, int size) {  
       int currlen = oldbin.length;  

       if (currlen >= size + 1) {  
           return oldbin;  
       }  

       int[] newbin = new int[size + 1];  
       for (int i = 0; i < size; newbin[i] = 0, i++)  
           ;  

       for (int i = 0; i < currlen; i++) {  
           newbin[i] = oldbin[i];  
       }  

       return newbin;  
   }  
} 

2.编写个辅助类用于请求来源校验

import java.util.Arrays;

public class Util {
	public static final String tokzen="tailre";
	
	/**
	 * 对请求进行校验,看是否来自微信服务器
	 * @param signature
	 * @param timestamp
	 * @param nonce
	 * @return
	 */
	public static boolean isSignature(String signature,String timestamp,String nonce){
		boolean flag=false;
		String [] array={tokzen,timestamp,nonce};
		
		//字典排序
		Arrays.sort(array);
		StringBuilder str= new StringBuilder();
		for(String temp:array){
			str.append(temp);
		}
		
		//加密
		String signature2=SHA1.hex_sha1(str.toString());
		
		//判断和服务器传来的是否相同
		if(signature.equals(signature2))
			flag=true;
		
		return flag;
	}
}
3.修改上次的demoServlet 如下:

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class Servlet extends HttpServlet {
	
	
	@Override
	public void destroy() {
		super.destroy();
	}
	
	@Override
	public void init() throws ServletException {
		super.init();
	}
	
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String signature = request.getParameter("signature");//微信加密签名
      String timestamp = request.getParameter("timestamp");//时间戳
      String nonce = request.getParameter("nonce");//随机数
      String echostr = request.getParameter("echostr");//随机字符串

      //对接收到的参数做数据验证,来确认该请求来自微信,避免被第三方随意攻击
      if(Util.isSignature(signature, timestamp, nonce))
      	//验证通过后,需要将随机字符串原样返回给微信,微信才确认你的这个服务正常
      	response.getWriter().print(echostr);

     

	}
	
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}
4.重新测试下tokzen 是否通过就OK了!


你可能感兴趣的:(java,微信,SHA1)