为 WebApi 实现两条腿的 OAuth 2.0

Posted

技术标签:

【中文标题】为 WebApi 实现两条腿的 OAuth 2.0【英文标题】:Implementation of two legged OAuth 2.0 for WebApi 【发布时间】:2012-09-01 08:30:27 【问题描述】:

我使用 VS2012RC 创建了一个 mvc4 webapi 项目。我试图在我的项目中实现两条腿的 Oauth 2。我按照教程“http://community.codesmithtools.com/CodeSmith_Community/b/tdupont/archive/2011/03/18/oauth-2-0-for-mvc-two-legged-implementation.aspx”,即使它适用于 mvc,我正在为 web api 实现它。但是不工作

我为我的客户端创建了一个 html 页面。当 html 页面加载时,它会执行一个 ajax 函数,该函数旨在返回“访问令牌”。

       <script type="text/javascript">
        $(document).ready(function () 
        var url = 'http://localhost:9792/api/Login';
            $.get(url, function(data) 

            alert(data);
            , "jsonp");
        );
        </script>

服务器端代码是,

[NoCache]
public class LoginController : ApiController


    public LoginModelOAuth GetLogin()
    

        var response = OAuthServiceBase.Instance.RequestToken();

        LoginModelOAuth lmo = new LoginModelOAuth();
         lmo.RequestToken = response.RequestToken;

        return lmo;
    

RequestToken() 方法的样子,

    public override OAuthResponse RequestToken()
    
        var token = Guid.NewGuid().ToString("N");
        var expire = DateTime.Now.AddMinutes(5);
        RequestTokens.Add(token, expire);

        return new OAuthResponse
        
            Expires = (int)expire.Subtract(DateTime.Now).TotalSeconds,
            RequestToken = token,
            RequireSsl = false,
            Success = true
        ;
    

LoginModelOAuth 模型的样子,

public class LoginModelOAuth


    public string RequestToken  get; set;       


    public string ErrorMessage  get; set; 

    public string ReturnUrl  get; set; 

当我执行客户端代码时,我收到以下错误

"500 Internal Server Error"

所以我调试了服务器端代码,在服务器端我收到了与此代码对应的错误

"var 响应 = OAuthServiceBase.Instance.RequestToken();" ,错误是

  NullReferenceException was unhandled by user code

  "Object reference not set to an instance of an object."

我的 webconfig 文件看起来像,

  <configuration>
  <configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<section name="oauth" type="OAuth2.Mvc.Configuration.OAuthSection, OAuth2.Mvc, Version=1.0.0.0, Culture=neutral"/>
<sectionGroup name="dotNetOpenAuth" type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection, DotNetOpenAuth.Core">
  <section name="messaging" type="DotNetOpenAuth.Configuration.MessagingElement, DotNetOpenAuth.Core" requirePermission="false" allowLocation="true" />
  <section name="reporting" type="DotNetOpenAuth.Configuration.ReportingElement, DotNetOpenAuth.Core" requirePermission="false" allowLocation="true" />
</sectionGroup>
 </configSections>
   <oauth defaultProvider="DemoProvider" defaultService="DemoService">
    <providers>
      <add name="DemoProvider" type="MillionNodesApi.OAuth.DemoProvider, MillionNodesApi" />
    </providers>
<services>
  <add name="DemoService" type="MillionNodesApi.OAuth.DemoService, MillionNodesApi" />
</services>
  </oauth>
    <system.web>
    <httpModules>
      <add name="OAuthAuthentication"     type="OAuth2.Mvc.Module.OAuthAuthenticationModule, OAuth2.Mvc, Version=1.0.0.0, Culture=neutral"/>
    </httpModules>
    <compilation debug="true" targetFramework="4.0" />
    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login" timeout="2880" />
    </authentication>
     <pages>
     <namespaces>
    <add namespace="System.Web.Helpers" />
    <add namespace="System.Web.Mvc" />
    <add namespace="System.Web.Mvc.Ajax" />
    <add namespace="System.Web.Mvc.Html" />
    <add namespace="System.Web.Optimization" />
    <add namespace="System.Web.Routing" />
    <add namespace="System.Web.WebPages" />
  </namespaces>
</pages>
</system.web>
 <dotNetOpenAuth>
    <messaging>
      <untrustedWebRequest>
    <whitelistHosts>
      <!-- Uncomment to enable communication with localhost (should generally not activate in production!) -->
      <!--<add name="localhost" />-->
    </whitelistHosts>
  </untrustedWebRequest>
</messaging>
<!-- Allow DotNetOpenAuth to publish usage statistics to library authors to improve the library. -->
<reporting enabled="true" />

它适用于 web api 吗?

如果没有,请向我推荐任何有用的教程。

谢谢。

【问题讨论】:

你能分享你的 web.config 吗? 【参考方案1】:

我认为问题在于您在IIS7 with integrated mode so you will need to migarate your config 从 system.web/httpModules 到 system.webServer/modules

<system.web>
    <httpModules>
       <add name="OAuthAuthentication"     type="OAuth2.Mvc.Module.OAuthAuthenticationModule, OAuth2.Mvc, Version=1.0.0.0, Culture=neutral"/>
    </httpModules>

变成

<system.webServer>
    <modules>
        <add name="OAuthAuthentication"     type="OAuth2.Mvc.Module.OAuthAuthenticationModule, OAuth2.Mvc, Version=1.0.0.0, Culture=neutral" preCondition="" />
    </modules>

也试试

你可以尝试通过设置这个来让模块被命中

<modules runAllManagedModulesForAllRequests="true">

或者也许

如果您仍然遇到问题,可能是模块的执行顺序,请尝试删除路由选项并将 OAuth 选项放在顶部...

<modules>
  <remove name="UrlRoutingModule-4.0" />
<add name="OAuthAuthentication"     type="OAuth2.Mvc.Module.OAuthAuthenticationModule, OAuth2.Mvc, Version=1.0.0.0, Culture=neutral" preCondition="" />
  <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />

【讨论】:

我在客户端获取请求令牌。但是当我发布时,我收到错误“XMLHttpRequest cannot load localhost:9792/api/Login. Origin null is not allowed by Access-Control-Allow -起源。”。我以前可以解决这个问题,但现在跨域无法与身份验证一起使用。我使用以下教程解决了 CORS "blogs.msdn.com/b/carlosfigueira/archive/2012/07/02/…"。 @Kishore 我认为您有一个新问题可能需要另一个问题,但您可以尝试将其添加到您的 Web 配置中 感谢您的建议。我修改了 Web 配置文件,但出现错误“Access-Control-Allow-Headers 不允许请求标头字段 Content-Type。”。我在这里发布了一个关于这个错误的问题是链接***.com/questions/12409600/…

以上是关于为 WebApi 实现两条腿的 OAuth 2.0的主要内容,如果未能解决你的问题,请参考以下文章

SalesForce.com Rest API身份验证。它是否允许双腿oauth交易

验证API响应完整性

二叉树常有,三叉数有木有呢?

WebApi使用Token(OAUTH 2.0方式)

Owin OAuth 2.0密码授权流程

当 2 条腿运行良好时,为啥还有 3 条腿 OAuth2?