javascript OWIN 和带有 SPA 的 WEB API 2 的表单身份验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19792261/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 16:48:48  来源:igfitidea点击:

OWIN and Forms Authentication with WEB API 2 with SPA

javascript.netasp.net-web-apisingle-page-applicationowin

提问by amcdnl

I have a Web API 2 Project that is referenced by a SPA JavaScript application.

我有一个由 SPA JavaScript 应用程序引用的 Web API 2 项目。

I'm using OWIN to authenticate the requests and upon login with Forms authentication, however, on each send back to the server my resources are not authenticated after I login.

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

App_Start/WebApiConfig.cs

App_Start/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();
        }
    }
}

/Startup.cs

/Startup.cs

[assembly: OwinStartup(typeof(API.Startup))]

namespace API
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }
    }
}

App_Start/Startup.Auth.cs

App_Start/Startup.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);
        }
    }
}

Controllers/AccountController.cs

控制器/AccountController.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)
            };
        }
    }
}

Then I invoke it with JavaScript like:

然后我用 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');
        }

My cookies are set on the browser:

我的 cookie 是在浏览器上设置的:

ASPXAUTH 040E3B4141C86457CC0C6A10781CA1EFFF1A32833563A6E7C0EF1D062ED9AF079811F1600F6573181B04FE3962F36CFF45F183378A3E23179E89D8D009C9E6783E366AF5E4EDEE39926A39E64C76B165

ASPXAUTH 040E3B4141C86457CC0C6A10781CA1EFFF1A32833563A6E7C0EF1D062ED9AF079811F1600F6573181B04FE3962F36CFF45F183378A3E23179E89D8D009C9E6783E366AF5E4EDEE39926A39E64C76B165

but after login, further requests are deemed unauthorized...

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

Status Code:401 Unauthorized

状态码:401 未授权

I feel like I'm REALLY close just missing one little piece, anyone got any ideas?

我觉得我真的很接近只是缺少一小部分,有人有任何想法吗?

采纳答案by amcdnl

Way too long to post but added all the details on how to set this up on github gist.

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

回答by Hongye Sun

Are you using Bearer token from your app? If you didn't use it and just want to use cookie, please remove following code:

您是否使用应用中的不记名令牌?如果您没有使用它而只想使用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));

The code above will only allow bearer authentication for web api.

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

And you may also remove app.UseOAuthBearerAuthentication(OAuthBearerOptions);to remove bearer authentication middleware from OWIN pipeline.

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

If you want to use bearer token in your app, you need to set the token before sending ajax request in browser.

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