您的位置:

首页 >

软件编程 >

双token实现token超时策略示例 >

双token实现token超时策略示例

2016-01-06 14:27:13

分类:软件编程

复制代码 代码如下:import com.google.common.base.Charsets;import com.google.common.hash.Hashing;import java.util.Date;import org.apache.commons.lang.time.FastDateFormat;/** * * @author Charles */public class TokenUtils {    private static final String privateKey = "fdas34ljfr好[email protected]#8$%dfkl;js&4*daklfjsdl;akfjsa342";    public static String getToken(String password, String date) {        return Hashing.md5().newHasher().                putString(password, Charsets.UTF_8).                putString(privateKey, Charsets.UTF_8).                putString(date, Charsets.UTF_8).hash().toString();    }        public static String getToken(String password, Date date) {        return Hashing.md5().newHasher().                putString(password, Charsets.UTF_8).                putString(privateKey, Charsets.UTF_8).                putString(getDate(date), Charsets.UTF_8).hash().toString();    }        public static String getToken(String password) {        return Hashing.md5().newHasher().                putString(password, Charsets.UTF_8).                putString(privateKey, Charsets.UTF_8).putString(getDate(), Charsets.UTF_8).hash().toString();    }    public static boolean validToken(String token,

前面几篇关于servlet的随笔,算是梳理了servlet的简单使用流程,接下去的文章将主要围绕手机APP访问接口这块出发续写,md5加密传输--->短信验证--->手机推送--->分享--->百度云图---->支付....第三方的业务 ...由于我是新手我也是一边学一边写,不足地方希望谅解。今天这篇文章主要涉及到 javaservlet传输数据的加密,客户端请求参数的组合,并且会附带上我中途遇到的所有问题以及解决方法。 由于手机访问接口是公布出来的,所以不管用什么语言编写接口,我们就应该做相应的安全措施,否则人家知道你的URL之后,截获客户端的请求,然后修改提交参数,这样损失就大了。用servlet写接口用得最多的也应该是对传输数据进行一个加密,如果是webservice .net的wcf这些这样的技术来编写,还会涉及到证书的匹配.... 一、请求数据参数的加密与实现思路。     加密这里我使用的md5 32位的加密,32位是一个不可逆的加密,这样即使被黑客截获了,也是没办法将我们加密后的MD5值,解密成我们加密时组合的字符串的。  当然这个不是绝对的,好像前几年已经有计算机方面的专家破译了MD5的加密方式,但我觉得那技术首先可能不会随意公布出来,然后即使公布了也不是一般人能明白的,否则      你随便问一个程序员 MD5加密你还在用吗,那肯定回答是 没有了。     1、首先我说下我请求参数的组合思路,因为这里涉及到了MD5加密,所以我们必须在用户使用APP登录帐号之后,反馈给用户两个token,第一个token是表示用户身份的唯一值,这个token是需要增加到请求接口参数中的(这个参数是否参与加密,是你自己定不影响,我这里是参与了的),因为servlet需要通过它来查询用户的加密所需token, 第二个token是用来加密md5的值,这个token是不能增加到请求接口参数中去的,而且这两个token我们都必须保存到数据库中,因为用户请求接口之后,serlvet需要获取参数中的用户token然后去数据库中查询 md5加密所需token,然后servlet再将查询来的加密token增加到用户传递来的字符串中去,再次进行一个md5加密,加密后对比用户传递的md5加密后的值,是否与servlet加密后的值一样,如果不一样,那么原因就可能有两个,servlet这边加密字符串组合错误,用户传输数据中途被截修改过。这两个token我都是使用的java uuid生成的,应为uuid生成的是一个唯一值。生成方式很简单。下面是代码 public static String getUUID() { return UUID.randomUUID().toString(); } 下面是java md5 32位加密方法public static String md5Encrypt(String groupParamertStr) throws UnsupportedEncodingException { MessageDigest messageDigest = null; try { messageDigest = MessageDigest.getInstance("MD5"); messageDigest.reset(); messageDigest.update(groupParamertStr.getBytes("UTF-8")); } catch (NoSuchAlgorithmException e) { System.out.println("NoSuchAlgorithmException caught!"); System.exit(-1); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } byte[] byteArray = messageDigest.digest(); StringBuffer md5StrBuff = new StringBuffer(); for (int i = 0; i < byteArray.length; i++) { if (Integer.toHexString(0xFF & byteArray[i]).length() == 1) md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i])); else md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i])); } return md5StrBuff.toString(); }下面是servlet这边获取参数进行加密后,使用加密结果与用户请求传递的加密结果进行一个对比。如果一样说明请求没问题,否则请求参数值有可能被修改过//下面这个方法三个参数 第一个是用户token 第二个是加密所需要的参数,等会我们通过用户token查询出 加密token之后,我们需要将它拼接到servlet加密所需json字符串中去,第三个就是从客户端传来的 加密结果字符串 这里方法返回0表示 用户加密后的结果没有问题,否则就有错 public static int postTokenVerify(String token, JSONObject requestJsonObject, String encryptStrValue) { int returnValue=0; String[] mysqlParameter=new String[]{token}; //下面就是通过用户token查询 用户的加密token ResultSet returnData=MySqlHepler.executeQuery("select * from infosheet where idToken=?", mysqlParameter); JSONObject returnObject=null; try { returnObject = ResultToJsonTool.resultSetToJsonObject(returnData); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (JSONException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } String byEncryptStrValue=""; try { if (returnObject.getString("encryptToken").length()>2) {//说明用户的idToken存在, // return returnValueString; //{"idToken":"123456","id":"34","pwd":"23","encryptToken":"2345678","account":"hang"} /*下面的代码是在匹配JAVAMD5加密字符串, 因为用户加密时,增加了加密token到加密字符串中去,但是请求时又不能传递这个加密token,所以我们servlet加密时需要通过用户token去查询用户的加密toke, 查询出来了,我们就需要拼接到,请求参数json后面,这样servlet加密的字符串就与用户加密的字符串一致了。下面就是查询出加密token后拼接到请求参数后面的方法, */ byEncryptStrValue=requestJsonObject.toString().substring(0, requestJsonObject.toString().length()-1); JSONObject encryptTokenJsonObject=new JSONObject(); encryptTokenJsonObject.put("encryptToken",returnObject.getString("encryptToken")); String value1=encryptTokenJsonObject.toString().substring(1, encryptTokenJsonObject.toString().length()); byEncryptStrValue=byEncryptStrValue+","+value1; // } else { returnValue=1;//idtoken错 误 } } catch (JSONException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } try { //下面方法就是使用拼接正确的字符串 在servlet上进行加密的方法调用,返回一个结果后,对比用户传递的加密结果 String javaMd5Result=EncryptSafa.md5Encrypt(byEncryptStrValue); if (javaMd5Result.equals(encryptStrValue)) {//加密串是正确的 } else { returnValue= 2;//加密结果有错 } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return returnValue; }前面都是封装好的被servlet调用的方法,下面是servlet页调用的所有代码1、请求的URL这里我是传递的是一个字典转换json格式的参数,是一个键值对形式,请求参数只用了一个。 参数中的idToken就是用户token,值我是在数据库中随便增加的一个123456没使用uuid,当然正式做肯定不会这样。http://localhost:8080/JAVAServletTest/2.jsp?parameter={"parameter":"{\"idToken\":\"123456\",\"pwd\":\"汉字\",\"account\":\"hang\"}","md5Str":"672f4a8c6fb92103c01d4275e46df790"} 下面是servlet页面处理的代码,整个流程就是为了验证用户请求在传递的途中是否被修改过。 //昨天在这里遇到个问题,就是当我请求参数中带中文时,servlet获取之后是乱码的,之后用了下面这种方式好了. String requestJsonStr=new String(request.getParameter("parameter").getBytes("ISO8859-1"),"UTF-8"); //提交参数 JSONObject objectParameter=null; //idToken JSONObject requestParmeter=null; //idToken String idToken=""; //客户端加密字符串 String md5Str=""; try { //获取总的JSON字符串,这里其实是我们从URL只传递的那个paramter一个参数 objectParameter=new JSONObject(requestJsonStr); //提交参数,json的一个key值,请求参数内部的paramter,其实这个参数里面放的是业务中所需参数,比如你登录 帐号 密码 这类型的 requestParmeter=new JSONObject(objectParameter.getString("parameter")); //idToken 这个是用户token,他就是用户的唯一标识,我们是需要通过他来查询数据库中对应的 加密token的 idToken=requestParmeter.getString("idToken"); //客户端加密字符串 md5Str=objectParameter.getString("md5Str"); } catch (JSONException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } //MD5加密后生成的字符串 //下一步是验证token是否正确 int tokenVerifyResult=EncryptSafa.postTokenVerify(idToken, requestParmeter, md5Str); if (tokenVerifyResult==0) { out.println("token加密方式正确"); } else { out.println("加密token或加密方式错误"); return; }以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

结束firefox的进程,一句代码就够了,如下:复制代码 代码如下:Runtime.getRuntime().exec("taskkill /F /IM firefox.exe");  结束qq:复制代码 代码如下:

Java8接口的默认方法什么是默认方法,为什么要有默认方法?简单说,就是接口可以有实现方法,而且不需要实现类去实现其方法。只需在方法名前面加个default关键字即可。为什么要有这个特性?首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8之前的集合框架没有foreach方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了使接口没有引入与现有的实现不兼容发展。如以下所示,public interface Animal { default void eat() { System.out.println("animal eat default method"); }}声明了一个接口,里面只有一个默认方法。然后写一个具体的类实现这个接口,public class Dog implements Animal { public void sayHi() { System.out.println("dog"); } public static void main(String args[]) { Dog dog = new Dog(); dog.eat(); }}再具体的类里面不是必须重写默认方法,但必须要实现抽象方法。默认方法的多重继承如下所示代码,public interface A { void doSomething(); default void hello() { System.out.println("hello world from interface A"); } default void foo() { System.out.println("foo from interface A"); }} interface B extends A { default void hello() { System.out.println("hello world from interface B"); A.super.hello(); this.foo(); A.super.foo(); }} class C implements B, A { @Override public void doSomething() { System.out.println("c object need do something"); } public static void main(String args[]) { A obj = new C(); obj.hello();//调用B的方法 obj.doSomething(); }}打印结果:hello world from interface Bhello world from interface Afoo from interface Afoo from interface Ac object need do somethingobj.hello()调用的是B接口中的默认方法。同时在B接口中的默认方法有调用了父接口中的默认方法。我们再来看一个例子,思考一下在多重继承中,如果出现了同名的默认方法,如下所示,public interface D { default void hello() { System.out.println("hello world from D"); }} interface E { default void hello() { System.out.println("hello world from E"); }} class F implements D, E { @Override public void hello() { System.out.println("hello world F class"); D.super.hello(); E.super.hello(); } public static void main(String args[]) { F f = new F(); f.hello(); } }我们需要制定调用哪个接口的默认方法如下, D.super.hello(); E.super.hello();另一个java8的接口默认方法实例:java8新增了接口的默认方法, 也就是说在接口中也可以有实现了, 这个实现方法是默认的实现,你也可以在接口的实现类里对此默认方法进行重写。如下实例:public class AppInterfaceDefaultMethod { public static interface DefaultMethodDemo { //定义默认方法, 默认方法前面加default关键字, 后面跟方法声明和方法体 default void demo(String input) { System.out.println(input); } void doSomething(); } public static class DemoClass implements DefaultMethodDemo { @Override public void doSomething() { System.out.println("do something"); } } public static class DemoClassOverrideDemo implements DefaultMethodDemo { //重写了默认方法 @Override public void demo(String input) { System.out.println("demo " + input + " by override method"); } @Override public void doSomething() { System.out.println("do something"); } } public static void main(String[] args) { DefaultMethodDemo demo = new DemoClass(); demo.demo("abc"); DefaultMethodDemo demoOverride = new DemoClassOverrideDemo(); demoOverride.demo("abc"); }}以上就是关于Java8接口的默认方法详细介绍,希望对大家的学习有所帮助。

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码不仅比较简短,同时也具有不可读性,即所编码的数据不会被人用肉眼所直接看到。java的加密方式有很多中,现在给大家分享一个Base64加密的方式package com.crypt; import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;/** * BASE64加密解密 * @author YUANWEi */public class BASE64 { /** * BASE64解密 * * @param key * @return * @throws Exception */ public static byte[] decryptBASE64(String key) throws Exception { return (new BASE64Decoder()).decodeBuffer(key); } /** * BASE64加密 * * @param key * @return * @throws Exception */ public static String encryptBASE64(byte[] key) throws Exception { return (new BASE64Encoder()).encodeBuffer(key); } }为什么要使用Base64加密呢?Base64编码的作用:由于某些系统中只能使用ASCII字符。Base64就是用来将非ASCII字符的数据转换成ASCII字符的一种方法。它使用下面表中所使用的字符与编码。而且base64特别适合在http,mime协议下快速传输数据。base64其实不是安全领域下的加密解密算法。虽然有时候经常看到所谓的base64加密解密。其实base64只能算是一个编码算法,对数据内容进行编码来适合传输。虽然base64编码过后原文也变成不能看到的字符格式,但是这种方式很初级,很简单。Base64编码方法要求把每三个8Bit的字节转换为四个6Bit的字节,其中,转换之后的这四个字节中每6个有效bit为是有效数据,空余的那两个 bit用0补上成为一个字节。因此Base64所造成数据冗余不是很严重,Base64是当今比较流行的编码方法,因为它编起来速度快而且简单。知识补充:标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。为解决此问题,可采用一种用于URL的改进Base64编码,它不在末尾填充'='号,并将标准Base64中的“+”和“/”分别改成了“*”和“-”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。另有一种用于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+”,“*”以及前面在IRCu中用到的“[”和“]”在正则表达式中都可能具有特殊含义。此外还有一些变种,它们将“+/”改为“_-”或“._”(用作编程语言中的标识符名称)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)。Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。以上就是关于Base64、Base64加密解密算法的全部内容,希望对大家进行加密解密的学习有所帮助。

焦点访谈

最新最热的文章

更多 >

COPYRIGHT (©) 2017 Copyright ©2017 腾博会官网 网站地图

联系我们

827570882

扫描二维码分享到微信