【问题标题】:Web API – authenticate with bearer tokenWeb API – 使用不记名令牌进行身份验证
【发布时间】:2017-08-16 12:17:48
【问题描述】:

我创建了一个允许外部身份验证/注册的 MVC 应用程序。它已经创建了所有必要的组件(Owin、EF、注册、登录、注销),我能够在应用程序中执行所有基本活动。

现在,我想将 Web 应用程序与我的移动应用程序也将使用的 Web API 集成。我在 Web API 调用中卡住了身份验证(使用从 Web 应用程序收到的不记名令牌)。

我看到了创建启用 OWIN 中间件的 WEB API 项目的示例。但我不知道如何集中外部身份验证过程并将令牌用于我的 Web 应用程序和移动应用程序 我不想使用 ANGULAR 或单页应用程序。 谁能建议我解决此问题的正确技术途径。 谢谢。

第 1 步:

我在 Visual Studio 2015 中创建了一个启用了个人登录的 MVC 项目。并配置了我在谷歌开发者控制台中配置所有内容的密钥。我的 Startup.cs 将有以下代码

 public void ConfigureAuth(IAppBuilder app)
    {
        // Configure the db context, user manager and signin manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

        // Enable the application to use a cookie to store information for the signed in user
        // and to use a cookie to temporarily store information about a user logging in with a third party login provider
        // Configure the sign in cookie
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                // Enables the application to validate the security stamp when the user logs in.
                // This is a security feature which is used when you change a password or add an external login to your account.  
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            }
        });

第 2 步:

更改 webconfig 文件以指向我的本地数据库并运行应用程序,我能够使用我的 gmail 帐户通过 google 成功登录,并且用户详细信息已成功添加到数据库中的 ASPUSerTables

第 3 步:

现在我想创建一个 WEB API 项目,它将连接到数据库并将一些数据检索到 MVC Web 应用程序和移动应用程序(我在这里停留在身份验证部分)。我也需要对我的移动应用程序(Xamarin)使用第三方身份验证,并使用我的移动应用程序和 MVC 网站中的通用 API

第 4 步 所以我想,我应该创建 WEB API 项目,而不是 WEB 应用程序(第 1 步),该项目如下所示,以在 Startup.cs 中返回身份验证令牌并将该 cookie 存储在网站中以通过在随后的请求中。

app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // Configure the application for OAuth based flow
        PublicClientId = "self";
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId),
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            // In production mode set AllowInsecureHttp = false
            AllowInsecureHttp = true
        };

我不想使用 ANGULAR,我需要我的 WebApplication(MVC) 和 WEB API 项目正确验证所有请求。请告诉我 正确的道路。 谢谢

【问题讨论】:

  • 您在哪里卡住不记名令牌的身份验证??您遇到的错误是什么,这将有助于回答您的问题。我做过一些项目,移动端和网络端都使用相同的 Api,没有任何问题。
  • 嗨贾万德。感谢您的即时回复。在我的 MVC 项目中,我能够在我的 AccountController 中从 google 获取用户声明,并能够在 ASPUsers 表中注册详细信息。我创建了单独的 web api 项目,没有 owin 组件(对吗),需要从 web 应用程序授权。我不确定如何在 webapp cookie 中获取访问令牌并授权 REST 调用。请指导我创建简单的 MVC 客户端应用程序(非 Angular)和 Web api 项目以支持 Web 和移动应用程序中的外部身份验证。
  • @DevOne 你能在问题中添加一些代码吗?
  • 嗨。谢谢我已经更新了如果您需要更多信息请告诉我
  • @DevOne 我假设您想在您的 Web 应用程序中使用标准 MVC 控制器,对吗?你想从 MVC 控制器调用你的 Web API 吗?如果我错了,请纠正我。这将帮助我回答你的问题。

标签: asp.net-mvc authentication oauth-2.0 asp.net-web-api2 owin


【解决方案1】:

你需要做的是按照这些步骤操作

  • 使用个人用户帐户身份验证创建一个 Web API 项目。
  • 现在,您将准备好使用 API 进行注册、更改密码以及 API 端点为用户生成令牌。
  • 创建另一个项目,但这次是 MVCNo Authentication 在同一解决方案中。

这将是我们的架构

这是 API 控制器

[Authorize]
public class ValuesController : ApiController
{
      [HttpGet]
      public IEnumerable<string> Get()
      {
         return new string[] { "values1", "values2" };
      }
}

这是你的 MVC 控制器

public class MVCValuesController : Controller
{
     HttpClient client;

     // web api Url
     string url = string.Format("http://localhost:60143/api/Values");
     string bearerToken = string.Format("bearer token from web api");
     public MVCValuesController()
     {
        client = new HttpClient(); 
        client.BaseAddress = new Uri(url);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Accept.Add("Authorization", "Bearer " + bearerToken);
     }

     public ActionResult GetValues()
     {
         HttpResponseMessage responseMessage = client.Get(url);
         if (responseMessage.IsSuccessStatusCode)
         {
             var responseData =   responseMessage.Content.ReadAsStringAsync().Result;
             var jsonResponse = JsonConvert.DeserializeObject<List<string>>(responseData);
             return View(jsonResponse);
         }
         return View("Error");
     }
}

我没有在这里使用异步,但你可以做到。而且你需要在运行它时启动你的两个项目。右键单击解决方案并单击Set Start Up projects,然后您可以选择多个项目并将操作设置为Start

public class MVCAccountController : Controller
{
     HttpClient client;

     // web api Url
     string url = string.Format("http://localhost:60143/");
     //string bearerToken = string.Format("bearer token from web api");
     public MVCValuesController()
     {
        client = new HttpClient(); 
        client.BaseAddress = new Uri(url);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
         // just adding a JObject you can create a class 

         JObject tokenJobject = new JObject(
                                        new JProperty("Email", "someone@example.com"),
                                        new JProperty("Password", "Pass123"));
                                        new JProperty("ConfirmPassword", "Pass123"));
            HttpContent baseContent = new StringContent(tokenJobject.ToString(), Encoding.UTF8, "application/json");
        //client.DefaultRequestHeaders.Accept.Add("Authorization", "Bearer " + bearerToken);


     }

     public async Task<ActionResult> GetValues()
     {
         string requestUri = string.Format("api/Account/Register");
         HttpResponseMessage responseMessage = await client.PostAsync(requestUri, baseContent);
         if (responseMessage.IsSuccessStatusCode)
         {
             var responseData =   responseMessage.Content.ReadAsStringAsync();
             var jsonResponse = JsonConvert.DeserializeObject<string>(responseData);
             return View(jsonResponse);
         }
         return View("Error");
     }
}

【讨论】:

  • 嗨贾万德。感谢您的回答。我也考虑过这个解决方案,但我想使用 OWIN 的所有默认功能,例如注册、忘记密码、重置密码、外部身份验证重定向等。我是否仍然能够使用 MVC 应用程序中的所有 API 功能 - 无身份验证申请没有任何麻烦? .
  • 是的,您可以毫无问题地使用它。我将添加更多代码来回答。
  • @DevOne 看看我使用了一个名为Register 的 web api 方法并用它来注册新用户。如果您需要更多帮助,请告诉我
  • 感谢您的努力。我正在寻找减少注册过程的开发时间,否则我需要在 WEB API 中手动完成所有这些操作。 (重置密码,忘记密码等)。所以我创建了所有代码都附带的 MVC WEB API。我想有一个单独的 web api 项目,可供移动应用程序和 WEB 用于其他调用。但是所有的请求都应该是授权的。可能我会创建另一个启用 Individual Auth 的简单 API 项目,并具有在所有请求中验证令牌的基本功能。标记为答案!
  • @JawandSingh 我对来自 Web 应用程序和移动应用程序的用户身份验证有类似的要求。你能解释一下我如何在没有认证的mvc项目中保持用户的身份吗?
【解决方案2】:
 public class MVCValuesController : Controller 
 {
       HttpClient client;

       // web api Url
       string url = string.Format("http://localhost:60143/api/Values");
       string bearerToken = string.Format("bearer token from web api");

       public MVCValuesController()
       {
          client = new HttpClient(); 
          client.BaseAddress = new Uri(url);
          client.DefaultRequestHeaders.Accept.Clear();
          client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
          client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
       }

       public ActionResult GetValues()
       {
          HttpResponseMessage responseMessage = client.Get(url);
          if (responseMessage.IsSuccessStatusCode)
          {
              var responseData =   responseMessage.Content.ReadAsStringAsync().Result;
              var jsonResponse = JsonConvert.DeserializeObject<List<string>>(responseData);
              return View(jsonResponse);
          }
          return View("Error");
       }
 }

【讨论】:

  • 没有解释,看起来像是上面答案的复制粘贴。
最近更新 更多