授权总是返回 401
Posted
技术标签:
【中文标题】授权总是返回 401【英文标题】:authorization always returns 401 【发布时间】:2016-05-22 05:40:23 【问题描述】:我正在尝试使用 web 调用 rest api 创建一个 SOA,但我遇到了授权问题。 AuthenticateUser 可以获得“test”作为用户和密码,但在 OnApplicationEndRequest 中无论如何都会返回 401。我错过了什么?
请询问任何额外的信息,我会尽力而为。
使用 IIS Express
ApiController
[Authorize]
public class BookController : ApiController
public object Get()
return "";
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()
网络
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
<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
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;
【问题讨论】:
【参考方案1】:您似乎没有为您的测试用户创建身份,您立即返回 false,所以如果您想拥有 test@test 帐户(您应该非常小心不要离开生产),那么您需要在这种情况下也可以创建身份。
缺少身份会导致 ASP.NET 生成 401,因为您有 [Authorize] 属性。
【讨论】:
我认为 ApplicationUserManager 会即时创建用户(代码添加到问题中)我尝试添加 Windows 用户,因为测试/测试不起作用。我应该如何添加该帐户? 问题是在将主体设置为线程之前,您确实返回 false。 看来test/test是唯一的用户,你用那个用户登录吗?我认为您根本不需要一个帐户来获得 401,这些没有连接。我认为我之前的评论是错误的,所以我可能误解了这个问题。【参考方案2】:您需要从 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);
【讨论】:
【参考方案3】:两件事:
-
在 OnApplicationAuthenticateRequest 方法中设置未授权的标头可能会更好。这样相同的方法要么授权要么拒绝。
您需要为用户分配一个角色。空角色与无角色不同。
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));
【讨论】:
以上是关于授权总是返回 401的主要内容,如果未能解决你的问题,请参考以下文章
WebApi 2 在使用自定义 JWT 令牌进行授权时总是返回 401
Laravel 护照 oauth 路线总是返回 401 未经授权