Discuz! 论坛官方's Archiver

lovaling 发表于 2006-1-4 11:28

发一个java版的passport工具类

[code]import java.util.Map;
import java.util.Random;
import java.util.Set;

import sun.misc.BASE64Decoder;

/**
*
* @author 李杰
*
*/
public class DiscuzPassportUtils {

        public static String passportEncrypt(String src, String key) {
                Random random = new Random();
                random.setSeed(System.currentTimeMillis());
                String rand = "" + random.nextInt() % 32000;
                String encryptKey = EncryptUtil.encrypt(rand, "MD5");

                int ctr = 0;
                String tmp = "";

                for (int i = 0; i < src.length(); ++i) {
                        ctr = (ctr == encryptKey.length() ? 0 : ctr);
                        tmp += encryptKey.charAt(ctr);
                        char c = (char) (src.charAt(i) ^ encryptKey.charAt(ctr));
                        tmp += c;
                        ctr++;
                }
                String passportKey = passportKey(tmp, key);
                return new sun.misc.BASE64Encoder().encode(passportKey.getBytes());
        }

        public static String passortDecrypt(String src, String key) {
                byte[] bytes = null;
                try {
                        bytes = new BASE64Decoder().decodeBuffer(src);
                        src = new String(bytes);
                } catch (Exception e) {
                        return null;
                }
                src = passportKey(src, key);

                String tmp = "";
                for (int i = 0; i < src.length(); ++i) {
                        char c = (char)(src.charAt(i) ^ src.charAt(++i));
                        tmp += c;
                }
                return tmp;
        }

        public static String passportKey(String src, String key) {
                String encryptKey = EncryptUtil.encrypt(key, "MD5");

                int ctr = 0;
                String tmp = "";
                for (int i = 0; i < src.length(); ++i) {
                        ctr = (ctr == encryptKey.length() ? 0 : ctr);
                        char c = (char) (src.charAt(i) ^ encryptKey.charAt(ctr));
                        tmp += c;
                        ctr++;
                }
                return tmp;
        }

        public static String passportEncode(Map<String, String> data) {
                Set<String> keys = data.keySet();
                String ret = "";
                for (String key : keys) {
                        ret += key + "=" + data.get(key) + "&";
                }
                if (ret.length() > 0)
                        return ret.substring(0, ret.length() - 1);
                return "";
        }
}[/code]

从D4文档的“高级应用”->“Discuz! Passport 接口技术文档”里面差不多,本代码从那个php版本转换过来。下面是使用代码:

[code]
                Map<String, String> member = new LinkedHashMap<String, String>();
                member.put("cookietime", "31536000");
                member.put("time", "1117415922");
                member.put("username", "Abcd");
                member.put("password", "e2fc714c4727ee9395f324cd2e7f331f");
                member.put("email", "abcd@efgh.com");
                member.put("credits", "123");
                member.put("regip", "210.120.222.111");
                member.put("regdate", "1012752000");
                member.put("msn", "email@hotmail.com");

                String key="aa";
               
                String enc=DiscuzPassportUtils.passportEncode(member);
                String auth = DiscuzPassportUtils.passportEncrypt(enc, key);
                System.out.println(auth);  // 输出加密结果
                enc = DiscuzPassportUtils.passortDecrypt(auth, key);
                System.out.println(enc);  // 输出解密结果
               
                // 1000次调用
                long start = System.currentTimeMillis();
                for (int i=0; i<1000; ++i){
                        enc = DiscuzPassportUtils.passportEncode(member);
                        auth = DiscuzPassportUtils.passportEncrypt(enc, key);
                }
                System.out.println(System.currentTimeMillis() - start);
[/code]

在我的机器上,1000次调用时间是1.8秒。

紫云杉 发表于 2006-1-4 11:28

我不懂

lovaling 发表于 2006-1-4 11:29

[quote]原帖由 [i]紫云杉[/i] 于 2006-1-4 11:28 发表
我不懂 [/quote]
晕,怎么灌得这么快?发了还没10秒就有回复了?

紫云杉 发表于 2006-1-4 11:32

[quote]原帖由 [i]lovaling[/i] 于 2006-1-4 11:29 发表

晕,怎么灌得这么快?发了还没10秒就有回复了? [/quote]
;P

741147 发表于 2006-1-4 12:58

起什麼作用的

lovaling 发表于 2006-1-4 13:03

[quote]原帖由 [i]741147[/i] 于 2006-1-4 12:58 发表
起什麼作用的 [/quote]
你看一下D4的文档就知道了,高级应用->Discuz! Passport 接口技术文档 里面,网站整合用的。

如果你有一个java开发的网站,D4要调用你那个网站的注册、登录、退出等功能,需要对一些信息加密传送到论坛,上面就是一些加密的函数。

gp_99 发表于 2006-1-4 23:29

试过了吗?

试过能用嘛?感觉你这个缺少点东西:passportEncode里面的需要URLEncoder.encode吧。另外我这里BASE64Encode出来的是有空格的。还有我这里用另外的包做的MD5.不知道你的EncryptUtil是否返回的MD5字符串是大写还是小写。注意论坛需要小写的,大写的是不行的。

gp_99 发表于 2006-1-4 23:31

请求发全了。

改进一下吧,最好能够将整个都测试以下,然后发一个全的文件上来。

gp_99 发表于 2006-1-4 23:35

passport调试失败,进不去论坛了。

急啊,怎么办哪?另外如果passport成功管理界面应该单独登录吧.

咕咕 发表于 2006-1-4 23:36

不会JAVA..纯支持~~

lovaling 发表于 2006-1-5 19:57

我已经用上了,URLEncode.encode是要调用的,原来是让使用者来调用的,后来想想这也是个普遍的需求,就放到里面了,新的代码如下:


[code]import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import sun.misc.BASE64Decoder;

/**
*
* @author 李杰
*
*/
public class DiscuzPassportUtils {

        public static String passportEncrypt(String src, String key) {
                Random random = new Random();
                random.setSeed(System.currentTimeMillis());
                String rand = "" + random.nextInt() % 32000;
                String encryptKey = EncryptUtil.encrypt(rand, "MD5");

                int ctr = 0;
                String tmp = "";

                for (int i = 0; i < src.length(); ++i) {
                        ctr = (ctr == encryptKey.length() ? 0 : ctr);
                        tmp += encryptKey.charAt(ctr);
                        char c = (char) (src.charAt(i) ^ encryptKey.charAt(ctr));
                        tmp += c;
                        ctr++;
                }
                String passportKey = passportKey(tmp, key);
                return new sun.misc.BASE64Encoder().encode(passportKey.getBytes());
        }

        public static String passortDecrypt(String src, String key) {
                byte[] bytes = null;
                try {
                        bytes = new BASE64Decoder().decodeBuffer(src);
                        src = new String(bytes);
                } catch (Exception e) {
                        return null;
                }
                src = passportKey(src, key);

                String tmp = "";
                for (int i = 0; i < src.length(); ++i) {
                        char c = (char)(src.charAt(i) ^ src.charAt(++i));
                        tmp += c;
                }
                return tmp;
        }

        public static String passportKey(String src, String key) {
                String encryptKey = EncryptUtil.encrypt(key, "MD5");

                int ctr = 0;
                String tmp = "";
                for (int i = 0; i < src.length(); ++i) {
                        ctr = (ctr == encryptKey.length() ? 0 : ctr);
                        char c = (char) (src.charAt(i) ^ encryptKey.charAt(ctr));
                        tmp += c;
                        ctr++;
                }
                return tmp;
        }

        public static String passportEncode(Map<String, String> data) {
                Set<String> keys = data.keySet();
                String ret = "";
                for (String key : keys) {
                        try {
                                ret += java.net.URLEncoder.encode(key, "UTF-8") + "=" + java.net.URLEncoder.encode(data.get(key), "UTF-8") + "&";
                        } catch (UnsupportedEncodingException e) {
                                return "";
                        }
                }
                if (ret.length() > 0)
                        return ret.substring(0, ret.length() - 1);
                return "";
        }
}[/code]

lovaling 发表于 2006-1-5 20:00

同事写的调用代码:


[code]//给论坛返回验证
Map<String, String> mb = new LinkedHashMap<String, String>();
mb.put("cookietime", cookieTime);
mb.put("time", ""+System.currentTimeMillis());
mb.put("username", member.getLoginName());
mb.put("password", loginForm.getPassword());
mb.put("email", member.getEmail());
mb.put("credits", ""+member.getCredit());
mb.put("regdate", ""+member.getCreateTime().getTime());
String key = privateKey;                                       
String enc=DiscuzPassportUtils.passportEncode(mb);
String auth = DiscuzPassportUtils.passportEncrypt(enc, key);
String verify = "login" + auth + forward + key;
verify = EncryptUtil.encrypt(verify, "MD5");                                       
String location = forumURL+"/api/passport.php?action=login&auth="+URLEncoder.encode(auth, "UTF-8")+"&forward="+URLEncoder.encode(forward, "UTF-8")+"&verify="+URLEncoder.encode(verify, "UTF-8");[/code]
下面那行就是用来跳转的,写得有点长,不过是正确的,要写得好看些可以使用String.format。

lovaling 发表于 2006-1-5 20:01

一并把退出代码发出来:

//给论坛返回验证       
String key = privateKey;                                       
String verify = "logout" + forward + key;
verify = EncryptUtil.encrypt(verify, "MD5");       
String location = forumURL+"/api/passport.php?action=logout&forward="+URLEncoder.encode(forward, "UTF-8")+"&verify="+URLEncoder.encode(verify, "UTF-8");

slimzhou 发表于 2006-1-18 08:46

感谢楼主发布的JAVA版类

特此奉上.net版的,按JAVA版和官方说明写的 测试通过
[code]
public class DiscuzPassport
{
        public DiscuzPassport()
        {
                //
                // TODO: Add constructor logic here
                //
        }

    public static string passportEncrypt(string txt, string key)
    {
        Random rd = new Random();
        string rand = rd.Next(0, 32000).ToString();
        string encryptKey = FormsAuthentication.HashPasswordForStoringInConfigFile(rand, "MD5").ToLower();

        int ctr = 0;
        string tmp = "";

        for (int i = 0; i < txt.Length; i++)
        {
            ctr = (ctr == encryptKey.Length ? 0 : ctr);
            tmp += encryptKey[ctr].ToString();
            char c = (char)(txt[i] ^ encryptKey[ctr]);
            tmp += c;
            ctr++;
        }

        string passportkey = passportKey(tmp, key);
        return base64Encode(passportkey);
    }
    public static string base64Encode(string data)
    {
        try
        {
            byte[] encData_byte = new byte[data.Length];
            encData_byte = System.Text.Encoding.UTF8.GetBytes(data);
            string encodedData = Convert.ToBase64String(encData_byte);
            return encodedData;
        }
        catch (Exception e)
        {
            throw new Exception("Error in base64Encode" + e.Message);
        }
    }
    public static string base64Decode(string data)
    {
        try
        {
            System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
            System.Text.Decoder utf8Decode = encoder.GetDecoder();

            byte[] todecode_byte = Convert.FromBase64String(data);
            int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
            char[] decoded_char = new char[charCount];
            utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
            string result = new String(decoded_char);
            return result;
        }
        catch (Exception e)
        {
            throw new Exception("Error in base64Decode" + e.Message);
        }
    }
    public static string passportKey(string txt, string key)
    {
        string encryptKey = FormsAuthentication.HashPasswordForStoringInConfigFile(key, "MD5").ToLower();
        int ctr = 0;
        string tmp = "";
        for (int i = 0; i < txt.Length; i++)
        {
            ctr = (ctr == encryptKey.Length ? 0 : ctr);
            char c = (char)(txt[i] ^ encryptKey[ctr]);
            tmp += c;
            ctr++;
        }
        return tmp;
    }

    public static string passortDecrypt(string txt, string key)
    {
        txt = base64Decode(txt);
        txt = passportKey(txt, key);
        string tmp = "";
        for (int i = 0; i < txt.Length; i++)
        {
            char c = (char)(txt[i] ^ txt[i++]);
            tmp += c;
        }
        return tmp;
    }

    public static string passportEncode(Hashtable ht)
    {
        string r="";
        foreach (string key in ht.Keys)
        {
            r += key + "=" + ht[key].ToString()+"&";
        }
        if (r.Length > 0)
            r = r.TrimEnd('&');
        return r;
    }
}
[/code]

slimzhou 发表于 2006-1-18 08:48

调用请用hashtable

netscope 发表于 2006-1-18 16:15

JAVA 技术要求更高,国内门户只有网易一家采用了JSP,像QQ和SINA这种只用了CGI。。。

天天过年 发表于 2006-2-7 09:49

不懂啊,郁闷

flmnix 发表于 2006-11-17 22:49

你使用了一个EncryptUtil,没这个代码

zlst 发表于 2006-11-26 12:40

哈哈,李老大,你也在这里溜达呀!

我说代码咋那么眼熟,原来我写了一点,哈哈

zlst 发表于 2006-11-26 12:49

回复 #19 flmnix 的帖子

EncryptUtil的功能是加密字符串,用到java.security.MessageDigest

页: [1] 2

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.