如何使用第二个身份验证因素保护某些REST请求?

时间:2016-12-29 12:09:43

标签: java spring spring-mvc spring-security

我有资源服务(REST服务)和其他一些使用资源服务的服务。

通过OAuth保护资源服务。此外,有些请求必须受到OTP(一种类型的密码)的保护,这是通过短信发送的。

我知道如何生成代码并通过短信发送,但我不知道如何组织Rest控制器以及在收到资源请求后该怎么做。

例如:我们向Controller / api / user发出GET请求。此时资源服务器向用户的手机发送消息,接下来是什么?

  • 我无法使用另一个端点来获取otp,然后使用HTTP标头或请求正文发送它,因为其他服务并不需要知道此代码。

如何正确组织此互动? 如何组织这种休息服务的保护?

我们使用Spring。 非常感谢任何建议。

1 个答案:

答案 0 :(得分:4)

嗯,你可以做到这一点:

  1. 使用动态路径创建REST服务。 /rest/some/service/unique-long-id
  2. 请勿向此动态路径请求安全性。
  3. 如果unique-long-id存在且未过期,则创建服务以便chek并提供对资源服务的访问权。
  4. 用户POST短信代码后,仅为此用户重定向到此动态路径。
  5. 示例:

    您发送短信代码:1234567890

    REST服务验证此密码并将我重定向到

    /rest/some/service/c83b5cf29d264ac7b86f27cc77af3f54979feefaf820edae36b2518a7e613385

    如果此唯一代码有效,您可以授予我访问资源服务的权限。如果没有,404错误或401错误。

    修改

    满足您要求的两种方法:

    • ServiceB需要验证动态ID以授予/api/protectedResource/unique-long-id的访问权限。

    • 使用filters截取/api/protectedResource/unique-long-id的网址(ServiceB)。如果它通过验证,则授予或拒绝受保护资源的访问权。

    在第一种情况下,ServiceA生成代码并通知用户。仅当使用动态网址发送有效的密码时,ServiceB才会授予访问权限:

    看看这个模拟:

    var secretCode;
    
    function generateCode(){
        secretCode = parseInt(Math.random() * 100000000);
        wrongCode  = (secretCode+"").split("").reverse().join("");
        $("#serviceA").val(secretCode);
        $("#resource1").val("/api/protectedResource/" +  wrongCode);
        $("#resource1").attr("onclick", "getAccess('" + wrongCode + "', 'protectedResource1')");
      
        $("#resource2").val("/api/protectedResource/" + secretCode);
        $("#resource2").attr("onclick", "getAccess('" + secretCode + "', 'protectedResource2')");
      
        $("#protectedResource1").val("");
        $("#protectedResource2").val("");
      
    }
    
    function getAccess(code, id){
        $("#" + id).val($("#serviceA").val() === code ? "Access granted" : "Access denied");
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
    
    ServiceA<br>
    POST <input type="button" value="/api/user" onclick="generateCode()" /> Secret code: <input id="serviceA" type="text" value="" />
    
    <br>
    <br>
    ServiceB<br>
    Wrong-ID POST <input id="resource1" type="button" value="/api/protectedResource/-1" onclick="getAccess('-1', 'protectedResource1')" /> Response <input id="protectedResource1" type="text" readonly="true" value="" />
    <br>
    Correct-ID POST <input id="resource2" type="button" value="/api/protectedResource/-1" onclick="getAccess('1234567890', 'protectedResource2')" /> Response <input id="protectedResource2" type="text" readonly="true" value="" />

    如果您需要帮助,我们可以打开聊天