2013-02-15 2 views
3

내 ASP.NET MVC 4 웹 응용 프로그램 영역에 REST API를 만들었습니다. API가 제대로 작동하고 있으며 이제 보안 설정을하고 싶습니다.REST 서비스를위한 DotNetOpenAuth 공급자

내가 할 수있는 방법에 대한 간단한 예가 있습니까? DotNetOpenAuth 다운로드와 함께 제공되는 샘플을 살펴보고 완전히 잃어 버렸습니다.

답변

9

나는 이틀 전에 같은 문제가 발생했습니다. 이 답변은 어리석게 길어 아마도 더 쉬운 방법 일 것입니다.

개인적으로 DNOA는 개인 확인 (즉, 암호화 된 토큰)을 위해 설계 되었기 때문에 개인적으로 DNOA를 사용하지 않으므로 요청할 때마다 DB를 치지 않아도됩니다. 이것의 매우 중요한 부작용은 토큰을 갱신해야만 액세스 권한이 즉시 유효하게되지 않는다는 것입니다. 또한 액세스 토큰은 꽤 길어집니다 (약 500 바이트).


의 OAuth/OAuth2를 처음에는 쉽게 보이지만, 그것은 승인 워크 플로를 설계하는 방법을 이해하는 것이 중요하다 : 매우 첫 번째 단계로

, 당신은 당신이 필요로하는 무엇을 알고 있는지 확인하십시오. 또한, 그들의 용어는 짜증나게 할 수 있습니다. 예를 들어 '클라이언트'는 순진한 클라이언트 애플리케이션을 말합니다. 사용자가 아닙니다 (OAuth 용어로 '리소스 소유자'라고 함). 저의 제안 : RFC 6749을 읽으십시오. 보기가 어두워 보이지만 흥미로운 읽기입니다. 절반을 건너 뛸 수 있습니다.

중요한 질문은 2 다리 OAuth 또는 3 다리 OAuth (또는 둘 다?)가 필요합니까? 어떤 보조금 종류를 지원해야합니까?

기본적으로 HTTP 기본 인증을 바꾸려면 간단한 "리소스 소유자 암호 자격 증명 흐름"이 필요합니다. Facebook/twitter 종류의 "이 응용 프로그램에 내 프로필 정보 액세스"는 3-legged OAuth입니다.

멋진 grant type diagrams과 함께 제공되는 IBM 문서가 있습니다.


이제 DNOA로 이동하십시오. Samples/OAuthAuthorizationServer을보십시오.

좋은 진입 점은 OAuthController.cs 파일입니다. AuthorizeAuthorizeResponse 작업은 사용자가 타사 응용 프로그램 (3-legged OAuth)에 액세스 할 수있게하려는 경우에만 필요합니다.

2 다리 시나리오에서 사용자는 OAuth token 엔드 포인트에 직접 액세스하여 간단하게 액세스 토큰을 요청합니다. 어쨌든 REST 응용 프로그램에 이러한 컨트롤러가 필요합니다.

내부 작동의 핵심은 OAuth2AuthorizationServer 클래스입니다 (AuthorizationServer 클래스는 아님). Code/OAuth2AuthorizationServer.cs을보십시오. 그것은 IAuthorizationServerHost을 구현합니다.

해당 클래스의 절반은 데이터 저장소 (다른 데이터 저장소로 작업하는 경우 수정할 수 있음)를 처리하고 절반은 액세스 토큰의 암호화를 처리합니다. 응용 프로그램에 IAuthorizationServerHost도 구현해야합니다.

코드에 #define SAMPLESONLY이라는 줄이 있는지 확인하십시오. 그러면 하드 코드 된 인증서를 사용할 수 있습니다.

실제로 요청을 승인하려면 ActionFilterAttribute 사용자 지정을 작성하는 것이 좋습니다. DNOA 개발에 SSL 연결 누락에 대해 불평하지 않도록 Web.config를 수정,

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); 
    } 
} 

다음 누락되었습니다 : 여기에 몇 가지 슈퍼 응축 코드, 준비되지 생산의

<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에 대한 좋은 답변입니다. –

관련 문제