简体   繁体   English

ASP.Net Web API - 从 ASP.NET MVC 项目生成不记名令牌

[英]ASP.Net Web API - Generate Bearer Token from ASP.NET MVC Project

Sorry if this question is poorly worded, I am new to authentication.对不起,如果这个问题措辞不当,我是身份验证的新手。

I have an ASP.NET MVC project that serves my web frontend and this is authenticated using OWIN and identity cookie based authentication.我有一个 ASP.NET MVC 项目,它为我的 Web 前端提供服务,它使用 OWIN 和基于身份 cookie 的身份验证进行身份验证。 This seems to work fine independently of my Web API.这似乎独立于我的 Web API 工作正常。

I also have an ASP.NET Web API project that is also authenticated using OWIN and identity token based authentication eg make a request to the /Token endpoint and get a bearer token that can be used to make requests to the API endpoints.我还有一个 ASP.NET Web API 项目,该项目也使用 OWIN 和基于身份令牌的身份验证进行身份验证,例如向 /Token 端点发出请求并获取可用于向 API 端点发出请求的不记名令牌。 This works fine when called via postman using the bearer token generated via the /Token endpoint, but as I don't have the password when I want to call the API from the MVC application, I can't use the token endpoint to generate a token.当使用 /Token 端点生成的不记名令牌通过邮递员调用时,这可以正常工作,但是由于我想从 MVC 应用程序调用 API 时没有密码,因此我无法使用令牌端点生成令牌。

My problem is I would like to be able to make requests to the ASP.NET Web API from my authenticated ASP.NET MVC application, how would I go about generating a token that I can call the Web API?我的问题是我希望能够从经过身份验证的 ASP.NET MVC 应用程序向 ASP.NET Web API 发出请求,我将如何生成可以调用 Web API 的令牌? Given that I have a ClaimsIdentity that has been authenticated.鉴于我有一个已通过身份验证的 ClaimsIdentity。

My Startup.Auth for my MVC project is:我的 MVC 项目的 Startup.Auth 是:

public partial class Startup 
{
    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);
        app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.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))
            }
        });            
    }
}

My Startup.Auth for my Web API project is:我的 Web API 项目的 Startup.Auth 是:

public partial class Startup
{
    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    public static string PublicClientId { get; private set; }

    // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
    public void ConfigureAuth(IAppBuilder app)
    {
        // Configure the db context and user manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

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

        // Enable the application to use bearer tokens to authenticate users
        app.UseOAuthBearerTokens(OAuthOptions);
    }
}

Thank you and please let me know if there's any further information that would be useful.谢谢,如果有任何有用的进一步信息,请告诉我。

One option to consider, that I've implemented before, is to retrieve a token from the API upon successful login from the MVC application - using the same credentials that were passed in during login.我之前实施过的一个要考虑的选项是在从 MVC 应用程序成功登录后从 API 检索令牌 - 使用登录期间传入的相同凭据。 Store the token how you please (ie in ASP.NET Session State) then use it as necessary in your application.以您喜欢的方式存储令牌(即在 ASP.NET 会话状态中),然后在您的应用程序中根据需要使用它。

Your MVC application Login controller action could look something like this:您的 MVC 应用程序登录控制器操作可能如下所示:

var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: true);

switch (result)
{
    case SignInStatus.Success:

        BearerToken token;

        using (var httpClient = new HttpClient())
        {
            var tokenRequest =
                new List<KeyValuePair<string, string>>
                    {
                        new KeyValuePair<string, string>("grant_type", "password"),
                        new KeyValuePair<string, string>("username", model.Email),
                        new KeyValuePair<string, string>("password", model.Password)
                    };

            HttpContent encodedRequest = new FormUrlEncodedContent(tokenRequest);

            HttpResponseMessage response = httpClient.PostAsync("https://YourWebApiEndpoint/Token", encodedRequest).Result;
            token = response.Content.ReadAsAsync<BearerToken>().Result;

            // Store token in ASP.NET Session State for later use
            Session["ApiAccessToken"] = token.AccessToken;
        }

        return RedirectToAction("SomeAction", "SomeController");
}

BearerToken is just a bespoke class representation of the full API token structure: BearerToken 只是完整 API 令牌结构的定制类表示:

public class BearerToken
{
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }

    [JsonProperty("token_type")]
    public string TokenType { get; set; }

    [JsonProperty("expires_in")]
    public string ExpiresIn { get; set; }

    [JsonProperty("userName")]
    public string UserName { get; set; }

    [JsonProperty(".issued")]
    public string Issued { get; set; }

    [JsonProperty(".expires")]
    public string Expires { get; set; }
}

An example call from the MVC application to retrieve some data might then look like this:来自 MVC 应用程序的用于检索某些数据的示例调用可能如下所示:

using (var httpClient = new HttpClient())
{
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Session["ApiAccessToken"].ToString());

    var response = httpClient.GetAsync("https://YourWebApiEndpoint/SomeController/SomeGetAction").Result;

    // Do something with response...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM