我的任务是将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客户端的任何想法?
答案 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();