简体   繁体   English

授权总是返回401

[英]authorization always returns 401

I am trying to create a SOA with a web calling rest api but I have authorization problem. 我正在尝试通过网络调用rest api创建SOA,但是我遇到了授权问题。 AuthenticateUser can get "test" as user and password but in OnApplicationEndRequest returns 401 anyway. AuthenticateUser可以获取“ test”作为用户名和密码,但是无论如何在OnApplicationEndRequest中返回401。 What am I missing? 我想念什么?

please ask for any extra information, I will do my best. 请索取更多信息,我会尽力而为。

using IIS Express 使用IIS Express

ApiController ApiController

[Authorize]
public class BookController : ApiController
{
   public object Get()
   {
       return "";
   }
}

REST - Auth Module REST-身份验证模块

namespace REST.Modules
{
    public class BasicAuthHttpModule : IHttpModule
    {
        private const string Realm = "XX WebAPI";

        public void Init(HttpApplication context)
        {
            // Register event handlers
            context.AuthenticateRequest += OnApplicationAuthenticateRequest;
            context.EndRequest += OnApplicationEndRequest;
        }

        private static void SetPrincipal(IPrincipal principal)
        {
            Thread.CurrentPrincipal = principal;
            if (HttpContext.Current != null)
            {
                HttpContext.Current.User = principal;
            }
        }

        private static bool AuthenticateUser(string credentials)
        {
            var encoding = Encoding.GetEncoding("iso-8859-1");
            credentials = encoding.GetString(Convert.FromBase64String(credentials));

            var credentialsArray = credentials.Split(':');
            var username = credentialsArray[0];
            var password = credentialsArray[1];

            if (!(username == "test" && password == "test"))
            {
                return false;
            }

            var identity = new GenericIdentity(username);
            SetPrincipal(new GenericPrincipal(identity, null));

            return true;
        }

        private static void OnApplicationAuthenticateRequest(object sender, EventArgs e)
        {
            var request = HttpContext.Current.Request;
            var authHeader = request.Headers["Authorization"];
            if (authHeader != null)
            {
                var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);

                // RFC 2617 sec 1.2, "scheme" name is case-insensitive
                if (authHeaderVal.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase) && authHeaderVal.Parameter != null)
                {
                    AuthenticateUser(authHeaderVal.Parameter);
                }
            }
        }

        // If the request was unauthorized, add the WWW-Authenticate header
        // to the response.
        private static void OnApplicationEndRequest(object sender, EventArgs e)
        {
            var response = HttpContext.Current.Response;
            if (response.StatusCode == 401)
            {
                response.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\"{0}\"", Realm));
            }
        }

        public void Dispose()
        {
        }
    }
}

WEB WEB

    readonly static string baseUri = "http://localhost:XXXX/api/book/";

    public static void GetBookList()
    {
        string uri = baseUri;
        using (HttpClient httpClient = new HttpClient(new HttpClientHandler { Credentials = new NetworkCredential("test", "test") }))
        {
            Task<HttpResponseMessage> response = httpClient.PostAsJsonAsync(uri, data);
            var x = response.Result.Content.ReadAsAsync<object>().Result.ToJson();
        }
    }

applicationhost.config 对ApplicationHost.config

        <authentication>

            <anonymousAuthentication enabled="false" userName="" />

            <basicAuthentication enabled="true" />

            <clientCertificateMappingAuthentication enabled="false" />

            <digestAuthentication enabled="false" />

            <iisClientCertificateMappingAuthentication enabled="false">
            </iisClientCertificateMappingAuthentication>

            <windowsAuthentication enabled="true">
                <providers>
                    <add value="Negotiate" />
                    <add value="NTLM" />
                </providers>
            </windowsAuthentication>

        </authentication>

        <authorization>
            <add accessType="Allow" users="*" />
        </authorization>

ApplicationUserManager ApplicationUserManager

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
        // Configure validation logic for usernames
        manager.UserValidator = new UserValidator<ApplicationUser>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };
        // Configure validation logic for passwords
        manager.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };
        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
        return manager;
    }

It seems that you do not create an identity for you test user, you return false right away, so if you want to have test@test account (which you should be very careful not to leave for production), then you need to create identity in that case as well. 似乎您没有为测试用户创建身份,而是立即返回false,因此,如果您想拥有test @ test帐户(应非常小心,不要离开生产环境),则需要创建身份在那种情况下也是一样。

Lack of identity causes ASP.NET to generate 401 since you have [Authorize] attribute. 缺少身份会导致ASP.NET生成401,因为您具有[Authorize]属性。

You need to create an Identity from the ApplicationUser Object 您需要从ApplicationUser对象创建一个身份

private async Task SignInAsync(ApplicationUser user, bool isPersistent)
    {
        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);


        var identity = await pApplicationUserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);


        AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
    }

Two things: 两件事情:

  1. Its probably better to set the unauthorized header in the OnApplicationAuthenticateRequest method. 在OnApplicationAuthenticateRequest方法中设置未授权的标头可能更好。 So that the same method either authorizes or denies. 因此,相同的方法可以授权或拒绝。
  2. You need to assign a role to the user. 您需要为用户分配一个角色。 Null roles is not the same as No roles. 空角色与无角色不同。

      private static bool AuthenticateUser(string credentials) { var encoding = Encoding.GetEncoding("iso-8859-1"); credentials = encoding.GetString(Convert.FromBase64String(credentials)); var credentialsArray = credentials.Split(':'); var username = credentialsArray[0]; var password = credentialsArray[1]; if (!(username == "test" && password == "test")) { return false; } var identity = new GenericIdentity(username); //0 roles not null roles SetPrincipal(new GenericPrincipal(identity, string[]{})); return true; } private static void OnApplicationAuthenticateRequest(object sender, EventArgs e) { var request = HttpContext.Current.Request; var authHeader = request.Headers["Authorization"]; if (authHeader != null) { var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader); // RFC 2617 sec 1.2, "scheme" name is case-insensitive if (authHeaderVal.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase) && authHeaderVal.Parameter != null) { bool userIsAuthenticated =AuthenticateUser(authHeaderVal.Parameter); //If not authenticated then user is not Authorized. if (!userIsAuthenticated){ addUnauthorizedHeader() } } } } private static void addUnauthorizedHeader(){ response.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\\"{0}\\"", Realm)); } 

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

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