Visual Studio 2015 Web Api个体认证项目如何添加自定义令牌登录?
Great question! The Individual Authentication template in VS2015 includes the OWIN-based foundation for token auth, but it doesn’t expose a straightforward login endpoint out of the box. Here’s a step-by-step guide to implement it:
Step 1: Configure OAuth Authorization Server in Startup.Auth.cs
Open App_Start/Startup.Auth.cs and update the authentication configuration to enable bearer token generation. Replace or extend the existing code with this:
using Microsoft.Owin.Security.OAuth; using System.Security.Claims; using System.Threading.Tasks; public partial class Startup { public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; } public static string PublicClientId { get; private set; } public void ConfigureAuth(IAppBuilder app) { // Keep existing context setup code here app.CreatePerOwinContext(ApplicationDbContext.Create); app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create); app.UseCookieAuthentication(new CookieAuthenticationOptions()); app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); // Configure OAuth token endpoint PublicClientId = "self"; OAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/Token"), Provider = new ApplicationOAuthProvider(PublicClientId), AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), // Set to false in production AllowInsecureHttp = true }; // Enable bearer token authentication app.UseOAuthBearerTokens(OAuthOptions); } }
Step 2: Create the Custom OAuth Provider
Add a new class App_Start/ApplicationOAuthProvider.cs to handle user credential validation and token generation:
using Microsoft.Owin.Security.OAuth; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; using System.Security.Claims; using System.Threading.Tasks; public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider { private readonly string _publicClientId; public ApplicationOAuthProvider(string publicClientId) { _publicClientId = publicClientId ?? throw new ArgumentNullException(nameof(publicClientId)); } public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>(); ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password); if (user == null) { context.SetError("invalid_grant", "The username or password is incorrect."); return; } ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, OAuthDefaults.AuthenticationType); AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, null); context.Validated(ticket); } public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { // Allow resource owner password flow without client ID if (context.ClientId == null) { context.Validated(); } return Task.FromResult<object>(null); } }
Step 3: Add a Dedicated Login Action (Optional)
If you want a custom login endpoint in AccountController instead of using the default /Token endpoint, add this:
[AllowAnonymous] [HttpPost] [Route("api/Account/Login")] public async Task<IHttpActionResult> Login(LoginViewModel model) { if (!ModelState.IsValid) { return BadRequest(ModelState); } var userManager = Request.GetOwinContext().GetUserManager<ApplicationUserManager>(); var user = await userManager.FindAsync(model.UserName, model.Password); if (user == null) { return Unauthorized(); } // Generate token var oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, OAuthDefaults.AuthenticationType); var ticket = new AuthenticationTicket(oAuthIdentity, null); var accessToken = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket); return Ok(new { AccessToken = accessToken, ExpiresIn = (int)Startup.OAuthOptions.AccessTokenExpireTimeSpan.TotalSeconds, UserName = user.UserName }); } // Add this view model class if it doesn't exist public class LoginViewModel { [Required] public string UserName { get; set; } [Required] [DataType(DataType.Password)] public string Password { get; set; } }
Step 4: Test the Token Generation
Option 1: Use the default /Token endpoint
Send a POST request to http://your-api-url/Token with form data:
grant_type:passwordusername: Your registered usernamepassword: Your registered password
Option 2: Use the custom /api/Account/Login endpoint
Send a POST request with this JSON body:
{ "UserName": "your-username", "Password": "your-password" }
Step 5: Protect API Endpoints
Add the [Authorize] attribute to any controller or action you want to restrict:
[Authorize] public class ValuesController : ApiController { public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } }
To access protected endpoints, include the token in the request header:Authorization: Bearer your-access-token-here
内容的提问来源于stack exchange,提问作者Mangrio

