2014-09-25 16 views
26

Я начал создавать веб-api для мобильных приложений, и мне сложно выполнять аутентификацию. Я использую Bearer, и хотя все должно быть хорошо, я не могу заставить текущего пользователя действовать в контроллере. HttpContext.Current.User.Identity.Name является нулевым (это же результат HttpContext.Current.User.Identity.GetUserId()). Вот куски важного кода:Текущий пользователь в аутентификации owin

Startup.cs:

public partial class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      var config = new HttpConfiguration(); 
      ConfigureAuth(app); 
      WebApiConfig.Register(config); 
      app.UseWebApi(config); 
     } 
    } 

Startup.Auth.cs

public partial class Startup 
{ 
     static Startup() 
     { 
      OAuthOptions = new OAuthAuthorizationServerOptions 
      { 
       TokenEndpointPath = new PathString("/token"), 
       Provider = new ApplicationOAuthProvider(), 
       AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), 
       AllowInsecureHttp = true 
      }; 

      OAuthBearerOptions = new OAuthBearerAuthenticationOptions(); 
     } 

     public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; } 
     public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; } 


     public static string PublicClientId { get; private set; } 

     public void ConfigureAuth(IAppBuilder app) 
     { 
      app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions 
      { 
       AccessTokenProvider = new AuthenticationTokenProvider() 
      }); 
      app.UseOAuthBearerTokens(OAuthOptions); 

      app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 

     } 
} 

ApplicationOAuthProvider.cs:

 public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
     { 

      string clientId, clientSecret; 

      if (!context.TryGetBasicCredentials(out clientId, out clientSecret)) 
      { 
       return SetErrorAndReturn(context, "client error", ""); 
      } 

      if (clientId == "secret" && clientSecret == "secret") 
      { 
       context.Validated(); 
       return Task.FromResult<object>(null); 
      } 

      return SetErrorAndReturn(context, "client error", ""); 
     } 

     public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
     { 

      context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); 

      using (AuthRepository _repo = new AuthRepository()) 
      { 
       IdentityUser user = await _repo.FindUser(context.UserName, context.Password); 

       if (user == null) 
       { 
        context.SetError("invalid_grant", "The user name or password is incorrect."); 
        return; 
       } 
      } 

      var identity = new ClaimsIdentity(context.Options.AuthenticationType); 
      identity.AddClaim(new Claim("sub", context.UserName)); 
      identity.AddClaim(new Claim("role", "user")); 

      context.Validated(identity); 
     } 


     public override Task TokenEndpoint(OAuthTokenEndpointContext context) 
     { 
      foreach (KeyValuePair<string, string> property in context.Properties.Dictionary) 
      { 
       context.AdditionalResponseParameters.Add(property.Key, property.Value); 
      } 

      return Task.FromResult<object>(null); 
     } 

AuthRepository.cs:

public class AuthRepository : IDisposable 
    { 
     private readonly AuthContext _ctx; 

     private readonly UserManager<IdentityUser> _userManager; 

     public AuthRepository() 
     { 
      _ctx = new AuthContext(); 
      _userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(_ctx)); 
     } 

     public async Task<IdentityResult> RegisterUser(UserModel userModel) 
     { 
      var user = new IdentityUser 
      { 
       UserName = userModel.UserName 
      }; 

      var result = await _userManager.CreateAsync(user, userModel.Password); 

      return result; 
     } 

     public async Task<IdentityUser> FindUser(string userName, string password) 
     { 
      IdentityUser user = await _userManager.FindAsync(userName, password); 
      return user; 
     } 

     public void Dispose() 
     { 
      _ctx.Dispose(); 
      _userManager.Dispose(); 

     } 
    } 

AuthContext.cs:

public class AuthContext : IdentityDbContext<IdentityUser> 
    { 
     public AuthContext() 
      : base("AuthContext") 
     { 

     } 
    } 

И finnaly ValuesController.cs:

[Authorize] 
public class ValuesController : ApiController 
{ 

    public IEnumerable<string> Get() 
    { 
     return new String[] {HttpContext.Current.User.Identity.Name, HttpContext.Current.User.Identity.GetUserId(),ClaimsPrincipal.Current.Identity.Name}; 
    } 
} 

Когда я иду к этому действию, я получаю нуль 3 раза. Несмотря на это, весь процесс проверки подлинности кажется прекрасным - только когда я отправляю хороший токен, у меня есть доступ. Кто-нибудь знает, что здесь не так?

+0

У вас есть точка останова на 'return new String [] {HttpContext ...'? Где первый нуль? – user1477388

+0

Последнее не пустое значение Identity (поэтому я не получаю ошибку, но null как возвращаемое значение) – user3558203

+0

Является ли 'GetUserId()' также null? – user1477388

ответ

55

по методу GrantResourceOwnerCredentials после добавления требования после проверки имени пользователя пароля необходимо добавить требование:

identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); 

Делая это UserId будет заполнена, когда вы звоните Пользователь.Идентичность.Имя внутри защищенного контроллера. Надеюсь, это решит вашу проблему.

+1

К сожалению, это не помогло. Я все еще получаю null. Я не уверен, что понял часть с защищенным контроллером. То, что я сделал, просто добавило вашу личность после identity.AddClaim (новое требование («роль», «пользователь»)); – user3558203

+2

Я имею в виду под защищенным контроллером атрибут контроллера с [Авторизовать], если вы отметили значение User.Identity.IsAuthenticated, оно установлено в true и User.Identity.Name всегда пусто после добавления этого требования? –

+3

Также хочу поблагодарить вас за вышеуказанное решение! Просто чтобы уточнить, что сказал пользователь55. Вам нужно добавить заявку в провайдер, а затем повторно войти в систему, чтобы создать новый токен, прежде чем вы увидите изменение (я обновлял страницу с помощью существующего токена и задавался вопросом, почему я мог не видеть имя пользователя, га) – alimac83

Смежные вопросы