OWIN和表单认证的WEB API 2与SPA

OWIN and Forms Authentication with WEB API 2 with SPA

本文关键字:API SPA WEB 表单 认证 OWIN      更新时间:2023-09-26

我有一个Web API 2项目,它被SPA JavaScript应用程序引用。

我使用OWIN对请求进行身份验证,在使用Forms身份验证登录时,但是,在每次发送回服务器时,我的资源在登录后都不会进行身份验证。

应用程序启动/WebApiConfig.cs

namespace API
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            // Configure Web API to use only bearer token authentication.
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(Startup.OAuthBearerOptions.AuthenticationType));
            config.EnableCors(new EnableCorsAttribute(
                origins: "*", headers: "*", methods: "*"));
            // Web API routes
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            // Use camel case for JSON data.
            config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =
                new CamelCasePropertyNamesContractResolver();
        }
    }
}

/启动.cs

[assembly: OwinStartup(typeof(API.Startup))]
namespace API
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }
    }
}

应用程序启动/启动.Auth.cs

namespace API
{
    public partial class Startup
    {
        static Startup()
        {
            OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
        }
        public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }
        public void ConfigureAuth(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseOAuthBearerAuthentication(OAuthBearerOptions);
        }
    }
}

控制器/会计控制器.cs

namespace API.Controllers
{
    public class AccountController : ApiController
    {
        public AccountController()
        {
            HttpContext.Current.Response.SuppressFormsAuthenticationRedirect = true;
        }
        [HttpPost]
        [AllowAnonymous]
        [Route("api/account/login")]
        [EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)]
        public HttpResponseMessage Login(LoginBindingModel login)
        {
            var authenticated = false;
            if (authenticated || (login.UserName == "a" && login.Password == "a"))
            {
                var identity = new ClaimsIdentity(Startup.OAuthBearerOptions.AuthenticationType);
                identity.AddClaim(new Claim(ClaimTypes.Name, login.UserName));
                AuthenticationTicket ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
                var currentUtc = new SystemClock().UtcNow;
                ticket.Properties.IssuedUtc = currentUtc;
                ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30));
                var token = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);
                var response = new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new ObjectContent<object>(new  
                    { 
                        UserName = login.UserName,
                        AccessToken = token
                    }, Configuration.Formatters.JsonFormatter)
                };
                FormsAuthentication.SetAuthCookie(login.UserName, true);
                return response;
            }
            return new HttpResponseMessage(HttpStatusCode.BadRequest);
        }
        [HttpGet]
        [Route("api/account/profile")]
        [Authorize]
        public HttpResponseMessage Profile()
        {
            return new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new ObjectContent<object>(new
                {
                    UserName = User.Identity.Name
                }, Configuration.Formatters.JsonFormatter)
            };
        }
    }
}

然后我用JavaScript调用它,比如:

       $httpProvider.defaults.withCredentials = true;
       login: function(user, success, error) {
            return $http.post('/api/account/login', user);
        },
        profile:function(){
            return $http.get('/api/account/profile');
        }

我的cookie设置在浏览器上:

ASPXAUTH040e3b4141c86457cc0c6a10781ca1eff1a32833563a6e7eff1062ed9f079811f1600f6573181b04fe3962f36cff45f183378a3e23179e89d8d009c9e6783e366af5e4ede39926a9e64c76b165

但登录后,进一步的请求将被视为未经授权。。。

状态代码:401未授权

我觉得我真的很接近,只是错过了一小部分,有人有什么想法吗?

您是否使用应用程序中的Bearer令牌?如果您没有使用它,只想使用cookie,请删除以下代码:

        // Web API configuration and services
        // Configure Web API to use only bearer token authentication.
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(Startup.OAuthBearerOptions.AuthenticationType));

上面的代码只允许对web api进行承载身份验证。

您还可以删除app.UseOAuthBearerAuthentication(OAuthBearerOptions);以从OWIN管道中删除承载身份验证中间件。

如果您想在应用程序中使用承载令牌,则需要在浏览器中发送ajax请求之前设置令牌。

发布时间太长,但添加了关于如何在github gist上设置的所有细节。