Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java服务器中通过facebook登录验证用户_Java_Android_Facebook_Security_Google App Engine - Fatal编程技术网

在Java服务器中通过facebook登录验证用户

在Java服务器中通过facebook登录验证用户,java,android,facebook,security,google-app-engine,Java,Android,Facebook,Security,Google App Engine,我真的不知道该怎么做,所以我只想解释一下我想做什么 我已经为我的移动应用程序构建了一个RESTAPI,在客户端,用户将使用facebook登录,然后通过上传图片和更新位置等操作向我自己的REST服务器发出请求 当我在PHP中这样做时,用户会在每次请求时发送访问令牌+详细信息,如邮件,我会使用访问令牌验证详细信息是否一致,这是我的基本安全措施(你可能会猜到我不是安全专家) 这在当时似乎是个好主意,但从那时起,我使用Java将我的服务器移动到google app engine,所以我想知道如何使用J

我真的不知道该怎么做,所以我只想解释一下我想做什么

我已经为我的移动应用程序构建了一个RESTAPI,在客户端,用户将使用facebook登录,然后通过上传图片和更新位置等操作向我自己的REST服务器发出请求

当我在PHP中这样做时,用户会在每次请求时发送访问令牌+详细信息,如邮件,我会使用访问令牌验证详细信息是否一致,这是我的基本安全措施(你可能会猜到我不是安全专家)

这在当时似乎是个好主意,但从那时起,我使用Java将我的服务器移动到google app engine,所以我想知道如何使用Java实现这一点,如果这总体上是个好主意,或者我应该采取不同的方法


任何答案都欢迎

几年前,当我需要实现此功能时,我尝试了两种基本方法

简单的方法,但扩展性不是很好:使用访问令牌使用并启动DefaultFacebookClient,然后将该客户端上的信息与我的客户端随令牌发送的用户名进行比较。这无法扩展的原因是它需要对Facebook进行HTTP或HTTPS调用,这可能需要几秒钟的时间。如果有很多用户同时登录,则会降低性能

更复杂的方法使用了由提供的示例。我使用的关键部分是(不记得它是否与ptarjan的版本相同):

public static SignedRequestResponse解析签名请求(字符串输入、字符串机密、整数最大值){
字符串[]split=input.split(“[.]”,2);
SignedRequestResponse响应=新的SignedRequestResponse();
响应.设置状态(状态.故障);
字符串编码_sig=split[0];
字符串编码的_信封=拆分[1];
JSONParser=新的JSONParser();
地图封套;
试一试{
envelope=(Map)parser.parse(新字符串(base64_url_decode(encoded_envelope));
}捕获(例外情况除外){
响应。添加错误(“ParsingError”);
返回响应;
}
响应。设置信封(信封);
字符串算法=(字符串)envelope.get(“算法”);
如果(!algorithm.equals(“HMAC-SHA256”)){
回复。添加错误(“不支持的算法”);
返回响应;//即时失败
}
byte[]key=secret.getBytes();
SecretKey hmacKey=新的SecretKeySpec(键,“HMACSHA256”);
Mac=null;
试一试{
mac=mac.getInstance(“HMACSHA256”);
mac.init(hmacKey);
}捕获(例外e){
回复。添加错误(“解密错误”);
返回响应;//即时失败
}
byte[]digest=mac.doFinal(encoded_envelope.getBytes());
试一试{
if(!array.equals(base64_url_decode(encoded_sig),摘要)){
回复。添加错误(“无效签名”);
返回响应;//即时失败
}
}捕获(例外情况除外){
回复。添加错误(“无效签名”);
返回响应;//即时失败
}
if(((长)信封.get(“发出时间”))

secret变量是app secret key。

如何在移动应用程序中获得已签名的请求?这是令牌附带的,不是吗?如果没有,看看这篇文章是否有帮助:我认为Facebook只会将已签名的请求发布到画布或页面标签应用程序。RestFB lib听起来好像对OP tho有帮助。谢谢你的回答,但老实说,我没有足够的知识来理解这一点:P你能解释一下第二种方法的区别吗?你知道最低级的方法是什么吗?在我的案例中,性能很重要在第二种方法中,客户机使用自己的Facebook API(无论它首先登录到Facebook使用哪个API)来请求已签名的请求。它将已签名的请求发送到服务器。然后,服务器使用上述代码验证已签名的请求是否合法,而无需致电Facebook。这意味着它需要纳秒而不需要进行HTTP调用。您正在寻找一个新的解决方案,而不仅仅是将PHP代码移植到Java?我想知道这是否是正确的方法,如果是,如何在Java中实现这一点,因为Facebook没有Java SDK
    public static SignedRequestResponse parse_signed_request(String input, String secret, int max_age) {
        String[] split = input.split("[.]", 2);
        SignedRequestResponse response = new SignedRequestResponse();
        response.setStatus(Status.Failure);

        String encoded_sig = split[0];
        String encoded_envelope = split[1];
        JSONParser parser = new JSONParser();
        Map envelope;
        try {
            envelope = (Map) parser.parse(new String(base64_url_decode(encoded_envelope)));
        } catch (Exception ex) {
            response.addError("ParsingError");
            return response;
        }

        response.setEnvelope(envelope);

        String algorithm = (String) envelope.get("algorithm");

        if (!algorithm.equals("HMAC-SHA256")) {
            response.addError("UnsupportedAlgorithm");
            return response;    // instant fail
        }

        byte[] key = secret.getBytes();
        SecretKey hmacKey = new SecretKeySpec(key, "HMACSHA256");
        Mac mac = null;
        try {
            mac = Mac.getInstance("HMACSHA256");
            mac.init(hmacKey);
        } catch (Exception e) {
            response.addError("DecryptionError");
            return response; // instant fail
        }

        byte[] digest = mac.doFinal(encoded_envelope.getBytes());
        try {

            if (!Arrays.equals(base64_url_decode(encoded_sig), digest)) {
                response.addError("InvalidSignature");
                return response; // instant fail
            }
        } catch (Exception ex) {
            response.addError("InvalidSignature");
            return response; // instant fail
        }

        if (((Long) envelope.get("issued_at")) < System.currentTimeMillis() / 1000 - max_age) {
            response.addError("Expired");
            response.setStatus(Status.PartialSuccess);
            return response;    // partial fail
        }

        response.setStatus(Status.Success);
        return response;
    }
}