web-dev-qa-db-fra.com

L'autorisation a été refusée pour cette demande. Toujours

J'ai déjà créé un projet MVC webApi et je souhaite maintenant utiliser l'authentification et l'autorisation ... Je pense avoir déjà implémenté cette sécurité, mais pour une raison quelconque, quelque chose se passe mal lorsque j'écris mes informations d'identification et que j'essaie d'appeler des méthodes webApi le message "L'autorisation a été refusée pour cette demande" s'affiche.

C'est le code que j'ai implémenté.

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 }
        );
    }

Manette:

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'). cliquez sur (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')
        }
    });
8
user3442776

Vous devez ajouter l'attribut [AllowAnonymous] à la variable LogInPost de votre contrôleur.

Lorsque vous avez ajouté la variable AuthorizeAttribute à vos filtres, vos contrôleurs ont supposé qu'ils avaient besoin d'une autorisation par défaut pour toutes les actions, y compris celle utilisée pour la connexion.

12
Jonathon Chase

Faites-vous l'authentification Windows? obtenez-vous l'erreur "Accès refusé"?

Parfois, IISEXpress et IIS font quelque chose de mal et pour remédier à cela, j'ai hébergé le site dans des iis locaux (inetmgr), j'autorise l'authentification (windows si applicable) et je l'exécute maintenant.

P.S. Le serveur IIS n'est pas installé par défaut sur tous les ordinateurs. Par conséquent, si inetmgr ne fonctionne pas, vous devez l'installer à partir du Panneau de configuration -> Fonctionnalités Windows -> sélectionnez toutes les fonctionnalités de IIS et ASP .NET

J'espère que cela aidera.

3
dotNetAuthor

Désolé de votre réponse si tardive - j'ai trouvé votre question car, après avoir basculé d'une API Web hébergée par IIS vers une API Web auto-hébergée, je viens tout juste de rencontrer le même problème.

Dans mon cas, le problème était dû à la façon dont j'avais initialisé Thread.CurrentPrincipal. Quelques antécédents:

  1. J'utilise un AuthenticationHandler personnalisé (héritant de DelegationHandler)
  2. Dans ce gestionnaire, je remplace la méthode SendAsync pour effectuer une validation utilisateur personnalisée.
  3. Si la validation réussit, je construis une instance de la classe ClaimsPrincipal pour contenir des revendications sur l'utilisateur actuel.

Auparavant, j'affectais cette instance ClaimsPrincipal à Thread.CurrentPrincipal avant de transmettre le message au gestionnaire de messages restant dans le pipeline. Cependant, la solution pour moi était d'utiliser à la place le membre Principal de l'instance HttpRequestContext qui appartient à l'instance HttpRequestMessage transmise à SendAsync. D'où (en F #),

override this.SendAsync(request : HttpRequestMessage, cancellationToken : CancellationToken) =
  // Do some user validation here first
  // .. then setup the claims (method details omitted) 
  let principal = BuildClaimsPrincipal

  // Assign to Principal on HttpRequestContext
  let requestContext = request.GetRequestContext
  requestContext.Principal <- principal

  // Rest of method omitted...

J'espère que cela pourra vous aider d'une manière ou d'une autre.

2
1MuddyDog