未经授权的 webapi 调用返回登录页面而不是 401 [英] Unauthorised webapi call returning login page rather than 401

查看:24
本文介绍了未经授权的 webapi 调用返回登录页面而不是 401的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何配置我的 mvc/webapi 项目,以便从 razor 视图调用的 webapi 方法在未经授权时不返回登录页面?

How do I configure my mvc/webapi project so that a webapi method called from a razor view doesn't return the loginpage when its unauthorised?

它是一个 MVC5 应用程序,它还具有用于通过 javascript 调用的 WebApi 控制器.

Its a MVC5 application which also has WebApi controllers for calls via javascript.

下面两种方法

[Route("api/home/LatestProblems")]      
[HttpGet()]
public List<vmLatestProblems> LatestProblems()
{
    // Something here
}

[Route("api/home/myLatestProblems")]
[HttpGet()]
[Authorize(Roles = "Member")]
public List<vmLatestProblems> mylatestproblems()
{
   // Something there
}

通过以下角度代码调用:

are called via the following angular code:

angular.module('appWorship').controller('latest', 
    ['$scope', '$http', function ($scope,$http) {         
        var urlBase = baseurl + '/api/home/LatestProblems';
        $http.get(urlBase).success(function (data) {
            $scope.data = data;
        }).error(function (data) {
            console.log(data);
        });
        $http.get(baseurl + '/api/home/mylatestproblems')
          .success(function (data) {
            $scope.data2 = data;
        }).error(function (data) {
            console.log(data);
        });  
    }]
);

所以我没有登录,第一种方法成功返回数据.第二种方法返回(在成功函数中)包含等价于登录页面的数据.即,如果您请求一个带有 [Authorize] 标记的控制器操作并且您没有登录,您会在 mvc 中得到什么.

So I'm not logged in and the first method successfully returns data. the second method returns (in the success function) data which contains the equivalent of a login page. i.e. what you would get in mvc if you requested a controller action which was stamped with [Authorize] and you weren't logged in.

我希望它返回未经授权的 401,以便我可以根据用户是否登录显示不同的数据.理想情况下,如果用户已登录,我希望能够访问控制器的用户属性,以便我可以返回特定于该成员的数据.

I want it to return a 401 unauthorized, so that i can display different data for users based on if they are logged in or not. Ideally if the user is logged in i want to be able to access the Controller's User property so i can return data specific to that Member.

更新:由于下面的建议似乎都不再起作用(对身份或 WebAPI 的更改),我在 github 应该可以说明问题.

UPDATE: Since none of the suggestions below seem to work anymore (changes to Identity or WebAPI) ive created a raw example on github which should illustrate the problem.

推荐答案

有两个 AuthorizeAttribute 实现,您需要确保为 Web API 引用正确的一个.有 System.Web.Http.AuthorizeAttribute 用于 Web API 和 System.Web.Mvc.AuthorizeAttribute 用于具有视图的控制器.如果授权失败,Http.AuthorizeAttribute 将返回 401 错误,Mvc.AuthorizeAttribute 将重定向到登录页面.

There are two AuthorizeAttribute implementations and you need to make sure you are referencing the correct one for Web API's. There is System.Web.Http.AuthorizeAttribute which is used for Web API's, and System.Web.Mvc.AuthorizeAttribute which is used for controllers with views. Http.AuthorizeAttribute will return a 401 error if authorization fails and Mvc.AuthorizeAttribute will redirect to the login page.

2013 年 11 月 26 日更新

因此,正如 Brock Allen 指出的那样,MVC 5 似乎发生了巨大的变化 在他的文章中.我猜 OWIN 管道接管并引入了一些新行为.现在,当用户未被授权时,状态 200 将在 HTTP 标头中返回,并带有以下信息.

So it appears things have drastically changed with MVC 5 as Brock Allen pointed out in his article. I guess the OWIN pipeline takes over and introduces some new behavior. Now when the user is not authorized a status of 200 is returned with the following information in the HTTP header.

X-Responded-JSON: {"status":401,"headers":{"location":"http://localhost:59540/Account/Login?ReturnUrl=%2Fapi%2FTestBasic"}}

您可以在客户端更改逻辑以检查标头中的此信息以确定如何处理此问题,而不是在错误分支上查找 401 状态.

You could change your logic on the client side to check this information in the header to determine how to handle this, instead of looking for a 401 status on the error branch.

我尝试通过在 OnAuthorizationHandleUnauthorizedRequest 方法中设置响应中的状态,在自定义 AuthorizeAttribute 中覆盖此行为.>

I tried to override this behavior in a custom AuthorizeAttribute by setting the status in the response in the OnAuthorization and HandleUnauthorizedRequest methods.

actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);

但这没有用.新管道必须稍后获取此响应并将其修改为我之前得到的相同响应.抛出 HttpException 也不起作用,因为它只是变成了 500 错误状态.

But this did not work. The new pipeline must grab this response later and modify it to the same response I was getting before. Throwing an HttpException did not work either as it is just changed into a 500 error status.

我测试了 Brock Allen 的解决方案,当我使用 jQuery ajax 调用时它确实有效.如果它不适合您,我的猜测是因为您使用的是 angular.使用 Fiddler 运行您的测试,看看以下内容是否在您的标题中.

I tested Brock Allen's solution and it did work when I was using a jQuery ajax call. If it is not working for you my guess is that it is because you are using angular. Run your test with Fiddler and see if the following is in your header.

X-Requested-With: XMLHttpRequest

如果不是,那就是问题所在.我不熟悉 angular,但如果它允许您插入自己的标头值,那么将其添加到您的 ajax 请求中,它可能会开始工作.

If it is not then that is the problem. I am not familiar with angular but if it lets you insert your own header values then add this to your ajax requests and it will probably start working.

这篇关于未经授权的 webapi 调用返回登录页面而不是 401的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆