2015-10-07 14 views
8

Mam już utworzony projekt webApi MVC, a teraz chcę użyć uwierzytelniania i autoryzacji. Myślę, że już zaimplementowałem to bezpieczeństwo, ale z jakiegoś powodu coś pójdzie źle, kiedy piszę swoje poświadczenia i próbuję wywoływać niektóre metody webApi, pojawia się komunikat "Odmowa autoryzacji dla tego żądania".Autoryzacja została odrzucona dla tego żądania. Zawsze

To jest kod, który zaimplementowałem.

WebApiConfig:

public static void Register(HttpConfiguration config) 
    { 
     // Web API configuration and services 

     // Web API routes 
     config.MapHttpAttributeRoutes(); 

     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 

     config.Filters.Add(new AuthorizeAttribute()); 
    } 

Routing Config:

public static void RegisterRoutes(RouteCollection routes) 
    { 
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

     routes.MapRoute(
      name: "Default", 
      url: "{controller}/{action}/{id}", 
      defaults: new { controller = "Routing", action = "LogIn", id = UrlParameter.Optional } 
     ); 
    } 

Kontroler:

public class RoutingController : Controller 
{ 
    // 
    // GET: /Routing/ 
    public ActionResult Index() 
    { 
     return View(); 
    } 

    public ActionResult Projects() 
    { 
     return View(); 
    } 

    public ActionResult Users() 
    { 
     return View(); 
    } 

    public ActionResult LogIn() 
    { 
     return View(); 
    } 

    [HttpPost] 
    public JsonResult LogInPost(string userName, string password) 
    { 
     User user = new User(); 
     RoleByUser rByU = new RoleByUser(); 
     password = UserController.EncriptPassword(password); 
     string url = string.Empty; 
     var checkUser = user.Get(userName); 
     var userExists = (from userInList in checkUser where userInList.UserName == userName && userInList.Password == password select userInList).FirstOrDefault(); 
     if(userExists!= null) 
     { 
      var roles = (from roleByUser in userExists.listOfRole select roleByUser.RoleName.Trim()).ToArray(); 
      IPrincipal principal = new GenericPrincipal(
      new GenericIdentity(userExists.UserName), roles); 
      SetPrincipal(principal); 
      url = "Routing/Users"; 
     } 
     return Json(url); 
    } 

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

} 

HTML:

<link href="~/css/Style.css" rel="stylesheet" type="text/css" /> 

<div class="container"> 
    <div class="card card-container"> 
     <img id="STK" class="profile-img-card" src="Images/Softtek.png" /> 
     <p id="profile-name" class="profile-name-card"></p> 
     <form class="form-signin"> 
      <span id="reauth-email" class="reauth-email"></span> 
      <input type="text" id="txtUserName" class="form-control" placeholder="Email address" required autofocus /> 
      <input type="password" id="txtPassword" class="form-control" placeholder="Password" required /> 
      <div id="remember" class="checkbox"> 
       <label> 
        <input type="checkbox" value="remember-me" /> Remember me 
       </label> 
      </div> 
      @*<button id="btnLogIn" class="btn btn-lg btn-primary btn-block btn-signin" >Sing In</button>*@ 
     </form><!-- /form --> 
     <button id="btnLogIn" class="btn btn-lg btn-primary">Sing In</button> 
     <a href="#" class="forgot-password"> 
      Forgot the password? 
     </a> 
    </div><!-- /card-container --> 
</div><!-- /container --> 

JS.

$ (document) .ready (function() { $ ('# btnLogIn') kliknij (login); });

function logIn() { 
    $.ajax({ 
     type: "POST", 
     url: "http://localhost:21294/Routing/LogInPost", 
     dataType: "json", 
     data: { userName: $('#txtUserName').val(), password: $('#txtPassword').val() }, 
     success: function (data) { 
      if(data!= "" && data!= undefined && data!= null) 
       window.location.href = data; 
     }, 
     error: function (err, e, error) { 
      toastr.error('Error') 
     } 
    }); 

Odpowiedz

11

Należy dodać atrybut [AllowAnonymous] do kontrolera na LogInPost

Po dodaniu AuthorizeAttribute do filtrów, to spowodowało kontrolery do Zakładają one wymagane zezwolenie domyślnie dla wszystkich działań, w tym jeden służy do logowania.

+0

Myślę, że problem polega na tym, że implementuję Thread.CurrentPrincipal i Current.User, ponieważ jeśli dodaję atrybut [AllowAnonymous] w moim kontrolerze API, aplikacja działa poprawnie, ale jeśli dodaję atrybut [Authorize (Roles = RoleEntity) .Collaborator)] na przykład aplikacja nie rozpoznaje tej roli. Dlatego sądzę, że powinienem wdrożyć The CurrentPrincipal w innym miejscu lub w inny sposób, czy wiesz, gdzie powinienem wstawić? – user3442776

+0

To jest późna odpowiedź, ale jak można się spodziewać działania, które upoważnią do roli, jeśli użytkownik nie musi jeszcze uwierzytelnić się? –

3

Czy używasz uwierzytelniania systemu Windows? czy otrzymujesz błąd "Odmowa dostępu"?

Czasami IISEXpress i IIS robią jakąś sztuczkę i pokonują to, że hostowałem lokację w lokalnej iis (inetmgr), włączam Uwierzytelnianie (w razie potrzeby Windows), a teraz go uruchomię.

P.S. nie wszystkie komputery mają domyślnie zainstalowany serwer IIS, więc jeśli inetmgr nie działa, musisz zainstalować go z Panelu sterowania -> Funkcje Windows -> wybierz wszystkie funkcje IIS i ASP .NET

Mam nadzieję, że to będzie Wsparcie.

+0

Wdrażam własne uwierzytelnianie i otrzymuję ten błąd "Odmowa autoryzacji dla tego żądania". Myślę, że to dlatego, że powinienem wdrożyć obecnego dyrektora w innym miejscu, czy wiesz, gdzie powinienem zrobić? – user3442776

2

Przepraszam za tak późną odpowiedź - znalazłem twoje pytanie, ponieważ po przejściu z hostowanego przez IIS interfejsu API na samoobsługowe API, dopiero zacząłem doświadczać tego samego problemu.

W moim przypadku problem został spowodowany przez sposób inicjowania Thread.CurrentPrincipal. Niektóre tła:

  1. Używam zwyczaj AuthenticationHandler (dziedziczenie z DelegationHandler)
  2. W tym obsługi, jestem przesłanianie metody SendAsync zrobić jakiś zwyczaj sprawdzania poprawności użytkownika.
  3. Jeśli sprawdzanie poprawności powiedzie się, konstruuję instancję klasy ClaimsPrincipal, aby zawierała pewne roszczenia dotyczące bieżącego użytkownika.

Poprzednio przypisywałem tę instancję ClaimsPrincipal do wątku.CurrentPrincipal przed przekazaniem wiadomości dalej pozostałym modułom obsługi komunikatów w potoku. Jednak rozwiązaniem dla mnie było użycie zamiast członka głównego w instancji HttpRequestContext, która należy do instancji HttpRequestMessage, która jest przekazywana do SendAsync. Stąd (w języku F),

Mam nadzieję, że to może ci w jakiś sposób pomóc.

Powiązane problemy