Identity Server 4 cookie设置无法正常工作

时间:2018-03-09 18:07:31

标签: c# asp.net identityserver4

我的任务是将mvc网站添加到使用Identity Server 4的现有web api项目中。目前,web api使用承载令牌对Android客户端进行身份验证。

我希望mvc网站使用包含持有人令牌的cookie。

我几天来一直在努力解决这个问题,我可以让网络客户端工作,或者安装客户端工作,但不能同时工作。如果我从AddAuthentication()中删除默认方案,该网站将按预期工作。但是这会导致android客户端不授权用户(HttpClient.User.Claims为null)。如果我添加默认方案,Android客户端将工作,但该网站将不会收到索赔。

有关如何使其发挥作用的任何想法?

Image showing no claims being picked up

这是我目前的设置:

 [HttpPost("Login")]
    [AllowAnonymous]
    public async Task<ActionResult> Login(LoginModel model)
    {
        if (!ModelState.IsValid)
            return View(model);

        string deviceId = Guid.NewGuid().ToString("N");
        string userString = deviceId + @"\" + _ctx.Company + @"\" + model.Username;
        var accessToken = await GenerateTokenAsync(userString, model.Password);

        if (accessToken != "invalid_grant")
        {
            JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
            JwtSecurityToken jwtToken = handler.ReadToken(accessToken) as JwtSecurityToken;
            jwtToken.Claims.ToList();
            var claimsIdentity = new ClaimsIdentity(jwtToken.Claims.ToList(), IdentityServerConstants.DefaultCookieAuthenticationScheme);
            var authProperties = new AuthenticationProperties
            {
                AllowRefresh = true,
                ExpiresUtc = DateTimeOffset.UtcNow.AddDays(1),
                IssuedUtc = DateTime.UtcNow
            };

            try
            {
                await HttpContext.SignInAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties);
            }
            catch (Exception e){}

            return RedirectToAction("Index", "Map");
        }
        else
        {
            model = new LoginModel();
            model.Exception = "Invalid username or password";
            return View("~/Views/Account/Login.cshtml", model);
        }
    }

    private async Task<string> GenerateTokenAsync(string username, string password)
    {
        var clientList = IdentityServerConfig.GetClients();
        Client client = clientList.FirstOrDefault();

        string tokenUrl = $"http://" + HttpContext.Request.Host.ToString() + "/connect/token";
        TokenClient tokenClient = new TokenClient(tokenUrl, client.ClientId, "secret");
        var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(username, password, client.AllowedScopes.FirstOrDefault());
        if (tokenResponse.IsError)
            return "invalid_grant";

        return tokenResponse.AccessToken;
    }

以下是用于登录网站部分的方法:

aspnet_isapi.dll

有关如何修复此问题或其他方法来处理此问题而无需修改Android客户端的任何想法?

1 个答案:

答案 0 :(得分:0)

我明白了。对于尝试此操作的任何人,您需要添加一个中间件来确定用于传入请求的方案:

# you need pandas library in my code but it's not the only possibility
import pandas as pd
from dateutil.parser import parse # for the date format

# your path
path_file_xl = "your\path\to\your\file.xlsx"
# Create a DataFrame (DF)
df = pd.read_excel(path_file_xl)

# Create the dictionnay
dict_data = {} # create an empty dictionary 
for index, row in df.iterrows():
    # If the subject not already in dict_data
    if int(row[0]) not in dict_data.keys():
        dict_data[int(row[0])] = {} # create the key
    # Add the new entry in the the dictionary linked to the subject
    dict_data[int(row[0])].update({ parse(row[1]): float(row[2]) })

# Create the table with average
table = [] #empty list to append data
for subject in dict_data.keys(): # for each subject in your dict_data
    # Calculate the average sum divided by length
    average_subject = sum(dict_data[subject].values())/len(dict_data[subject])
    table.append([subject, average_subject]) #append in the table

# create a DF with average data
df_out = pd.DataFrame(table)
# Rename and sort values
df_out = df_out.rename(columns={0: 'Subject', 1: 'average measurement'}).sort_values(['Subject'])
# write into a csv without the index of the DF
path_file_csv = "your\path\to\your\file.csv"
df_out.to_csv(path_file_csv, index = False)

您将在此处调用新的中间件:

 public class AuthSchemeMiddleware : IMiddleware
{
    public async Task InvokeAsync(HttpContext context, Func<Task> next)
    {
        var scheme = context.Request.Cookies.ContainsKey("idsrv.session")
            ? "Cookies" : "Bearer";

        var result = await context.AuthenticateAsync(scheme);
        if (result.Succeeded)
        {
            context.User = result.Principal;
        }
        await next();
    }
}

应该像这样添加身份验证:

 // use Authentication from IdentityServer4
 app.UseAuthentication();

 // Serve static files
 app.UseDefaultFiles();
 app.UseStaticFiles(new StaticFileOptions()
 {
     ContentTypeProvider = ContentTypeProviderFactory.GetContentTypeProvider()
 });

 app.UseMiddlewareFrom<AuthSchemeMiddleware>(container);
 app.UseMvcWithDefaultRoute();