2013-02-15 2 views
3

Я создал API REST в области моего веб-приложения ASP.NET MVC 4. API работает правильно, и теперь я хотел бы его защитить.Поставщик DotNetOpenAuth для службы REST

Есть ли простой пример того, как я могу это сделать? Я просматриваю образцы, которые поставляются с загрузкой DotNetOpenAuth, и я полностью потерял ее.

ответ

9

У меня была такая же проблема несколько дней назад. Этот ответ смехотворно длинный, может быть, есть более простой способ.

Лично я больше не пользуюсь DNOA, потому что он разработан для самонатверждающих (то есть зашифрованных токенов), поэтому вам не нужно ударять БД каждым запросом. Очень важным побочным эффектом этого является то, что аннулирование доступа не вступит в силу немедленно, но только после того, как токен должен быть обновлен. Кроме того, токены доступа станут довольно длинными (около 500 байт).

В самом первом шаге, убедитесь, что вы знаете, что вам нужно:


OAuth/OAuth2 выглядеть легким на первый, но очень важно, чтобы понять, как рабочие процессы авторизации разработаны. Кроме того, их терминология может быть раздражающей, например, «Клиент» относится к тому, что я наивно называю клиентом приложение. Это не пользователь (который называется «владелец ресурса» в терминах OAuth). Мое предложение: Прочитано RFC 6749. Это выглядит скучно, но это интересно читать (и вы можете пропустить половину его ...)

Ключевой вопрос: вам нужен двуглавый OAuth или 3-legged OAuth (или оба?). Какие типы грантов вам нужны для поддержки?

Если вы в основном хотите заменить HTTP Basic Auth, будет использоваться простой «Ресурс учетных данных пароля владельца ресурса». Тип вида facebook/twitter «имеет доступ к моей информации о профиле» - это 3-значный OAuth.

Существует документация IBM, которая поставляется с красивым grant type diagrams.


Теперь, чтобы DNOA, взгляните на Samples/OAuthAuthorizationServer.

Хорошей точкой входа является файл OAuthController.cs. Обратите внимание, что действия Authorize и AuthorizeResponse требуются только в том случае, если вы хотите, чтобы ваши пользователи предоставляли доступ к сторонним приложениям (3-сторонний OAuth).

В сценарии с двумя ногами пользователи напрямую обращаются к конечной точке OAuth token и просто запрашивают токен доступа. В любом случае вам понадобится такой контроллер в вашем приложении REST.

Ключом к внутренней обработке является класс OAuth2AuthorizationServer (НЕ класс AuthorizationServer). Посмотрите на Code/OAuth2AuthorizationServer.cs. Он реализует IAuthorizationServerHost.

Половина этого класса занимается хранением данных (которые вы можете изменить, если работаете с другим хранилищем данных), а половина из них касается шифрования токенов доступа. Вам также потребуется реализовать IAuthorizationServerHost для вашего приложения.

Убедитесь, что у вас есть строка #define SAMPLESONLY в вашем коде, чтобы она приняла жесткий код.

Чтобы действительно авторизовать запрос, полезно написать обычай ActionFilterAttribute. Вот некоторые супер сгущенное код, не готовый к производству:

public sealed class BasicAuthenticationAttribute : System.Web.Http.Filters.ActionFilterAttribute 
{ 
    private readonly OAuthResourceServer _authServer; 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     if (actionContext.Request.Headers.Authorization.Scheme == "Bearer" 
      || actionContext.Request.Properties.ContainsKey("access_token")) 
     { 
      authenticatedUser = _authServer.VerifyOAuth2(request, required_claims); 
      HttpContext.Current.User = authenticatedUser; 
      Thread.CurrentPrincipal = authenticatedUser; 
     } 
    } 
} 

// See OAuthResourceServer/Code/OAuthAuthorizationManager.cs in DNOA samples 
public sealed class OAuthResourceServer 
{ 
    public IPrincipal VerifyOAuth2(HttpRequestMessage httpDetails, params string[] requiredScopes) 
    { 
     // for this sample where the auth server and resource server are the same site, 
     // we use the same public/private key. 
     using (var signing = CreateAuthorizationServerSigningServiceProvider()) 
     { 
      using (var encrypting = CreateResourceServerEncryptionServiceProvider()) 
      { 
       var tokenAnalyzer = new StandardAccessTokenAnalyzer(signing, encrypting); 
       var resourceServer = new ResourceServer(_myUserService, tokenAnalyzer); 
       return resourceServer.GetPrincipal(httpDetails, requiredScopes); 
      } 
     } 
    } 
} 

Сервер ресурсов по-прежнему отсутствует

public sealed class MyResourceServer : ResourceServer 
{ 
    public override System.Security.Principal.IPrincipal GetPrincipal([System.Runtime.InteropServices.OptionalAttribute] 
     [System.Runtime.InteropServices.DefaultParameterValueAttribute(null)] 
     HttpRequestBase httpRequestInfo, params string[] requiredScopes) 
    { 
     AccessToken accessToken = this.GetAccessToken(httpRequestInfo, requiredScopes); 
     string principalUserName = !string.IsNullOrEmpty(accessToken.User) 
      ? this.ResourceOwnerPrincipalPrefix + accessToken.User 
      : this.ClientPrincipalPrefix + accessToken.ClientIdentifier; 
     string[] principalScope = accessToken.Scope != null ? accessToken.Scope.ToArray() : new string[0]; 

     // Now your own code that retrieves the user 
     // based on principalUserName from the DB: 
     return myUserService.GetUser(userName); 
    } 
} 

Далее, изменение web.config так DNOA не жалуется на отсутствие SSL соединений в развитии:

<configSections> 
     <sectionGroup name="dotNetOpenAuth" type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection, DotNetOpenAuth"> 
     <section name="openid" type="DotNetOpenAuth.Configuration.OpenIdElement, DotNetOpenAuth" requirePermission="false" allowLocation="true" /> 
     <section name="oauth" type="DotNetOpenAuth.Configuration.OAuthElement, DotNetOpenAuth" requirePermission="false" allowLocation="true" /> 
     <sectionGroup name="oauth2" type="DotNetOpenAuth.Configuration.OAuth2SectionGroup, DotNetOpenAuth"> 
      <section name="authorizationServer" type="DotNetOpenAuth.Configuration.OAuth2AuthorizationServerSection, DotNetOpenAuth" requirePermission="false" allowLocation="true" /> 
     </sectionGroup> 
     <section name="messaging" type="DotNetOpenAuth.Configuration.MessagingElement, DotNetOpenAuth" requirePermission="false" allowLocation="true" /> 
     <section name="reporting" type="DotNetOpenAuth.Configuration.ReportingElement, DotNetOpenAuth" requirePermission="false" allowLocation="true" /> 
     </sectionGroup>  
    </configSections> 
    <dotNetOpenAuth> 
    <!-- Allow DotNetOpenAuth to publish usage statistics to library authors to improve the library. --> 
    <reporting enabled="true" /> 
    <openid> 
     <provider> 
     <security requireSsl="false"> 
     </security> 
     </provider> 
    </openid> 
    <oauth2> 
     <authorizationServer > 
     </authorizationServer> 
    </oauth2> 
    <!-- Relaxing SSL requirements is useful for simple samples, but NOT a good idea in production. --> 
    <messaging relaxSslRequirements="true"> 
     <untrustedWebRequest> 
     <whitelistHosts> 
      <!-- since this is a sample, and will often be used with localhost --> 
      <add name="localhost"/> 
     </whitelistHosts> 
     </untrustedWebRequest> 
    </messaging> 
    </dotNetOpenAuth> 
+0

+1 для ссылки RFC 6749 и приятный ответ. –