【问题标题】:Jhipster + REST client + authenticationJhipster + REST 客户端 + 身份验证
【发布时间】:2016-01-31 21:34:40
【问题描述】:

我需要了解如何对 REST 客户端进行身份验证(可以是 Paw,也可以是一个 android 应用程序,一个使用 AFNetworking 和 jHipster 的 iOs 应用程序,我认为,更一般地说,我不是 spring-boot 的专家) .

虽然我能够在登录浏览器时获取令牌,并随后在以下请求中使用此令牌,但我不明白如何首先使用 RESTful 最佳实践进行身份验证。

例如,在 Paw.app 中,我可以通过基本身份验证或 Oauth2,但我不明白如何像在 Web 浏览器上那样简单地进行身份验证来获取会话令牌。

同样,在 AFNetworking 中我能够通过基本身份验证,例如

NSString*auth=[NSString stringWithFormat:@"%@:%@", @"admin", @"admin"];
NSString *authValue = [NSString stringWithFormat:@"Basic %@", [auth base64EncodedString]];
[manager.requestSerializer setValue:authValue forHTTPHeaderField:@"Authorization"];

但我很难理解如何使用 jHipster/spring boot 中捆绑的会话安全性进行身份验证。

【问题讨论】:

标签: rest security spring-boot jhipster


【解决方案1】:

首先,不要对移动应用使用 HTTP 会话身份验证。

另一方面,Oauth2 或 JWT 也适用于移动应用。它们背后的基本思想是从 Jhipster 获取 token 到移动设备,该令牌具有到期时间。届时您可以使用令牌访问 Jhipster 的任何 REST API 来访问数据。

下面我将展示如何在基于 angularjs 的 ionic 应用程序中使用 Jhipster rest API 的代码 sn-p。我希望它能告诉你你需要做什么。

jhipster

中的 application.yml 中取消注释 cors
cors: #By default CORS are not enabled. Uncomment to enable.
        allowed-origins: "*"
        allowed-methods: GET, PUT, POST, DELETE, OPTIONS
        allowed-headers: "*"
        exposed-headers:
        allow-credentials: true
        max-age: 1800

要在 ionic 中使用 Oauth2 身份验证访问 REST API,您必须首先在 ionic 应用程序中通过以下方式获取令牌

    $http({
    method: "post", 
    url: "http://192.168.0.4:8085/[Your app name]/oauth/token",
    data:  "username=admin&password=admin&grant_type=password&scope=read write&client_secret=my-secret-token-to-change-in-production&client_id=auth2Sconnectapp",
    withCredentials: true,
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Accept': 'application/json',
      'Authorization': 'Basic ' + 'YXV0aDJTY29ubmVjdGFwcDpteS1zZWNyZXQtdG9rZW4tdG8tY2hhbmdlLWluLXByb2R1Y3Rpb24='
      }
  })                
  .success(function(data) {
      alert("success: " + data);
  })
  .error(function(data, status) {
      alert("ERROR: " + data);
  });

这里"YXV0aDJTY29ubmVjdGFwcDpteS1zZWNyZXQtdG9rZW4tdG8tY2hhbmdlLWluLXByb2R1Y3Rpb24=" is equal to (clientId + ":" + clientSecret)--all base64-encoded

如果成功,上面的 $http 会给你这个 JSON,其中包含令牌和它的到期时间

{
  "access_token": "2ce14f67-e91b-411e-89fa-8169e11a1c04",
  "token_type": "bearer",
  "refresh_token": "37baee3c-f4fe-4340-8997-8d7849821d00",
  "expires_in": 525,
  "scope": "read write"
}

如果您想访问任何 API,请注意“access_token”和“token_type”,这是您必须使用的。我们使用 API 发送令牌以访问数据,直到令牌过期,然后我们要么刷新它,要么访问一个新的。

例如

$http({
    method: "get", 
    url: "http://192.168.0.4:8085/auth-2-sconnect/api/countries",
    withCredentials: true,
    headers: {
      'Authorization':' [token_type] + [space] + [access_token] '
      }
  })                
  .success(function(data) {
      alert("success: " + data);
  })
  .error(function(data, status) {
      alert("ERROR: " + data);
  });

【讨论】:

    【解决方案2】:

    这里总结了我是如何实施该解决方案的。这是真正的swift代码,但请把它当作伪代码,因为它可能不正确。

    1. 调用您需要调用的任何方法,在此类方法中传递一个回调(块或等效)表示成功,一个回调表示失败

      func action(
          URLString:String,
          method:Method,
          encoding:Encoding = .JSON,
          parameters:[String : AnyObject]?,
          success:(statusCode:Int, responseObject:AnyObject)->Void,
          failure:(statusCode:Int, error:NSError)->Void
      )
      
    2. 在方法es里面。 /events 你处理一个特定的失败案例,即状态码为 401 时。

       if(r!.statusCode==ResponseCodes.HTTP_UNAUTHORIZED.rawValue){
      
           loginAndAction(URLString, method: method, encoding: encoding, parameters: parameters, success: success, failure: failure)
      
       }else{
      
           failure(statusCode: response.response!.statusCode, error:response.result.error!)
      
       }
      
    3. 在这种特殊情况下,不是返回结果并调用失败回调,而是调用 login() 方法,该方法在必要的参数之后接受原始的 success() 回调

      func loginAndAction(
          URLString:String,
          method:Method,
          encoding: Encoding,
          parameters:[String:AnyObject]?,
          success:(statusCode:Int, responseObject:AnyObject)->Void,
          failure:(statusCode:Int, error:NSError)->Void
          )->Void
      
    4. 如果认证成功

      var d:[String:AnyObject] = response.result.value as! [String:AnyObject]
      self.authToken = d["access_token"] as! String
      
      action(URLString, method: method,encoding:encoding, parameters: parameters, success: success, failure: failure)
      

    此时方法操作可以使用正确的工作令牌。

    这应该每天只发生一次(基于令牌到期),它是一种适用于 oauth2 refresh_token 调用的机制。

    【讨论】: