Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WebAPI[授权]登录时返回错误_C#_Asp.net Mvc_Asp.net Web Api - Fatal编程技术网

C# WebAPI[授权]登录时返回错误

C# WebAPI[授权]登录时返回错误,c#,asp.net-mvc,asp.net-web-api,C#,Asp.net Mvc,Asp.net Web Api,我正在尝试使用MVC5/WebAPI 2设置WebAPI,它目前正在使用默认配置和其他默认设置。当我使用浏览器中的帐户登录时,我可以使用[Authorize]属性进入常规的MVC控制器操作,例如主页在授权时显示为它应该显示的状态,但是如果我进入/api/Me(默认内置的api控制器操作)或者我使用默认MVC Web api 2脚手架构建的任何需要授权的自定义api控制器操作,我会得到如下错误: {"message":"Authorization has been denied for this

我正在尝试使用
MVC5
/
WebAPI 2
设置
WebAPI
,它目前正在使用默认配置和其他默认设置。当我使用浏览器中的帐户登录时,我可以使用
[Authorize]
属性进入常规的
MVC
控制器操作,例如主页在授权时显示为它应该显示的状态,但是如果我进入
/api/Me
(默认内置的api控制器操作)或者我使用默认MVC Web api 2脚手架构建的任何需要授权的自定义api控制器操作,我会得到如下错误:

{"message":"Authorization has been denied for this request."}
这是当我在Microsoft Edge中尝试它时,我还没有在我正在构建的实际客户端代码上尝试它,这是一个
UWP
应用程序。我想我应该先在浏览器中进行测试,以确保一切正常

我开始看这篇文章:它似乎更倾向于
Ajax
请求和
spa
。我的目标是通过网络和
UWP
实现工作。我可能会把更多的时间放在
UWP
方面,而不是用ajax开发一个健壮的web应用程序,因为该应用程序将在intranet中运行并访问运行web api的intranet IIS服务器,所以我想在UWP中构建一个桌面客户端,并最终通过web api访问数据的Xamarin


我是否可以安全地假设,如果您使用的是像Edge这样的常规web浏览器,则当通过
[Authorize]
属性保护web Api控制器操作时,您无法访问这些操作,因为它不会在标题中发送访问令牌?

因此,您可以从UWP应用程序中创建以下两种方法,或者可以将它们封装在一个类中,您可以通过DI(您的选择)注入该类

或者,如果您使用的是持票人代币,那么您可以:

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer ", "string token goes here...");

我在这里发布了更多的补充信息,供那些可能正在解决这个问题的人参考,您希望从UWP或Xamarin这样的客户端访问MVC5/WebAPI 2,但需要使用Authorize属性锁定Web Api的区域

高级过程是,您不需要通过任何MVC控制器直接向/Token端点(或指定的任何端点)发送POST

首先,如果您想使用SSL进行开发,但尚未获得证书,请继续运行以下操作:

C:\Program Files (x86)\IIS Express>iisexpressadmincmd setupSslUrl -url:https://localhost:55970/ -UseSelfSigned
其中55970是本地网站的端口,我将在我的文本中提及

接下来要做的是确保覆盖客户端验证和资源授予方法上的ApplicationAuthProvider.cs,否则将遇到无效客户端或无效授予错误

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        UserManager<ApplicationUser> _userManager;
        ApplicationDbContext db = new ApplicationDbContext();
        _userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));
        try
        {

            ApplicationUser user = await _userManager.FindAsync(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);
        }
        catch (Exception ex)
        {
            string str = ex.ToString();
        }

        db.Dispose();
    }

    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        string clientId = "";
        string clientSecret = "";
        context.TryGetFormCredentials(out clientId, out clientSecret);

        List<string> validClients = new List<string>(){ "web","Alliance_UWP","Alliance_Xamarin","Alliance_Web" };
        if (validClients.Contains(clientId))
            context.Validated();
    }
public override异步任务GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext)
{
context.OwinContext.Response.Headers.Add(“访问控制允许来源”,新[]{“*”});
用户管理器(UserManager);;
ApplicationDbContext db=新的ApplicationDbContext();
_userManager=newusermanager(newuserstore(db));
尝试
{
ApplicationUser user=wait_userManager.FindAsync(context.UserName,context.Password);
if(user==null)
{
SetError(“无效的授权”,“用户名或密码不正确”);
返回;
}
var identity=newclaimsidentity(context.Options.AuthenticationType);
identity.AddClaim(新声明(“sub”,context.UserName));
identity.AddClaim(新声明(“角色”、“用户”));
上下文验证(身份);
}
捕获(例外情况除外)
{
string str=ex.ToString();
}
db.Dispose();
}
公共重写异步任务ValidateClientAuthentication(OAuthValidateClientAuthenticationContext)
{
字符串clientId=“”;
字符串clientSecret=“”;
TryGetFormCredentials(out clientId,out clientSecret);
List ValidClient=新列表(){“web”、“Alliance_UWP”、“Alliance_Xamarin”、“Alliance_web”};
if(validClients.Contains(clientId))
context.Validated();
}
您不需要像我在允许的客户端上那样冗长,只要“web”就可以了,您将在Http POST方法中以url编码的表单值、grant_type=“password”和用户名/密码的形式包含它。这是我编写的一个快速而肮脏的UWP客户端,它只接收用户名/密码,并通过绑定了Authorize属性的api访问我拥有的数据集。如果您不进行身份验证,您将得到一个授权错误,这正是我们想要的

这里需要注意的是,在我的客户端中,我过滤掉了自签名证书错误,因为我已经通过上述命令在IIS Express中设置了自签名证书

    Uri tokenUri = new Uri(@"https://localhost:55970/Token");
    // This is a test data set from my Web Api pulling data from 
    // Entity Framework and SQL Server protected by the Authorize attribute
    Uri testCasesUri = new Uri(@"https://localhost:55970/api/Cases");
    string accessToken = "";

    public MainPage()
    {
        this.InitializeComponent();
    }

    private async void btn_SubmitLogin_Click(object sender, RoutedEventArgs e)
    {
        string username = txt_User.Text;
        string password = txt_Password.Password;

        HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
        filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
        filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
        filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationFailure);
        HttpClient client = new HttpClient(filter);
        Dictionary<string, string> parameters = new Dictionary<string, string>();
        parameters.Add("client_id", "web");
        parameters.Add("grant_type", "password");
        parameters.Add("username", username);
        parameters.Add("password", password);
        try
        {
            HttpResponseMessage result = await client.PostAsync(tokenUri, new HttpFormUrlEncodedContent(parameters));
            string jsonResult = await result.Content.ReadAsStringAsync();
            // TokenResult is a custom model class for deserialization of the Token Endpoint
            // Be sure to include Newtonsoft.Json from NuGet
            var resultObject = JsonConvert.DeserializeObject<TokenResult>(jsonResult);
            accessToken = resultObject.AccessToken;

            // When setting the request for data from Web Api set the Authorization
            // header to Bearer and the token you retrieved
            client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
            result = await client.GetAsync(testCasesUri);
            jsonResult = await result.Content.ReadAsStringAsync();

        } catch(Exception ex)
        {
            string debugBreak = ex.ToString();
        }
uritokenuri=newuri(@)https://localhost:55970/Token");
//这是我的Web Api中的一个测试数据集,从中提取数据
//受Authorize属性保护的实体框架和SQL Server
Uri testCasesUri=新Uri(@“https://localhost:55970/api/Cases");
字符串accessToken=“”;
公共主页()
{
this.InitializeComponent();
}
私有异步无效btn\u SubmitLogin\u单击(对象发送方,路由目标)
{
字符串username=txt_User.Text;
字符串密码=txt_password.password;
HttpBaseProtocolFilter=新的HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationFailure);
HttpClient=新的HttpClient(过滤器);
字典参数=新字典();
添加(“客户端id”、“web”);
添加(“授权类型”、“密码”);
    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        UserManager<ApplicationUser> _userManager;
        ApplicationDbContext db = new ApplicationDbContext();
        _userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));
        try
        {

            ApplicationUser user = await _userManager.FindAsync(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);
        }
        catch (Exception ex)
        {
            string str = ex.ToString();
        }

        db.Dispose();
    }

    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        string clientId = "";
        string clientSecret = "";
        context.TryGetFormCredentials(out clientId, out clientSecret);

        List<string> validClients = new List<string>(){ "web","Alliance_UWP","Alliance_Xamarin","Alliance_Web" };
        if (validClients.Contains(clientId))
            context.Validated();
    }
    Uri tokenUri = new Uri(@"https://localhost:55970/Token");
    // This is a test data set from my Web Api pulling data from 
    // Entity Framework and SQL Server protected by the Authorize attribute
    Uri testCasesUri = new Uri(@"https://localhost:55970/api/Cases");
    string accessToken = "";

    public MainPage()
    {
        this.InitializeComponent();
    }

    private async void btn_SubmitLogin_Click(object sender, RoutedEventArgs e)
    {
        string username = txt_User.Text;
        string password = txt_Password.Password;

        HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
        filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
        filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
        filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationFailure);
        HttpClient client = new HttpClient(filter);
        Dictionary<string, string> parameters = new Dictionary<string, string>();
        parameters.Add("client_id", "web");
        parameters.Add("grant_type", "password");
        parameters.Add("username", username);
        parameters.Add("password", password);
        try
        {
            HttpResponseMessage result = await client.PostAsync(tokenUri, new HttpFormUrlEncodedContent(parameters));
            string jsonResult = await result.Content.ReadAsStringAsync();
            // TokenResult is a custom model class for deserialization of the Token Endpoint
            // Be sure to include Newtonsoft.Json from NuGet
            var resultObject = JsonConvert.DeserializeObject<TokenResult>(jsonResult);
            accessToken = resultObject.AccessToken;

            // When setting the request for data from Web Api set the Authorization
            // header to Bearer and the token you retrieved
            client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
            result = await client.GetAsync(testCasesUri);
            jsonResult = await result.Content.ReadAsStringAsync();

        } catch(Exception ex)
        {
            string debugBreak = ex.ToString();
        }