C# 用户声明似乎在管道的某个地方被取代
**编辑:如果任何人有任何线索,我可以更好地询问或通知你们关于这个问题,请让我知道 因此,我正在创建自定义声明并尝试将它们添加到我的用户中。我在添加后立即在User.Identity中看到声明,并在管道中稍微向下移动,但当它到达my Global.asax时,User.Identity已丢失除一项声明之外的所有声明。我还认为,在同一时间内,用户正在从ClaimsPrincipal变为GenericPrincipal。我不知道我是否理解或解释得很好。甚至不知道所有的代码发布,但我会在下面发布一些 这是我的用户进行身份验证和创建cookie和声明的地方。注意,我已经尝试了很多东西,所以这可能有一些奇怪的代码:C# 用户声明似乎在管道的某个地方被取代,c#,asp.net-mvc,cookies,claims-based-identity,C#,Asp.net Mvc,Cookies,Claims Based Identity,**编辑:如果任何人有任何线索,我可以更好地询问或通知你们关于这个问题,请让我知道 因此,我正在创建自定义声明并尝试将它们添加到我的用户中。我在添加后立即在User.Identity中看到声明,并在管道中稍微向下移动,但当它到达my Global.asax时,User.Identity已丢失除一项声明之外的所有声明。我还认为,在同一时间内,用户正在从ClaimsPrincipal变为GenericPrincipal。我不知道我是否理解或解释得很好。甚至不知道所有的代码发布,但我会在下面发布一些
private AuthenticationResponse AuthenticateUserByService(string userName, string password, bool rememberMe)
{
Authenticator auth = new Authenticator(AppInfo.AuthServiceAddress, AppInfo.ClientId, AppInfo.Secret);
AppInfo.rememberMe = rememberMe;
AuthenticationResponse response = auth.Authenticate(userName, password);
if (response.IsError)
{
// MessageBox.Show(response.ErrorDescription);
return null;
}
if (response.AppUser == null)
{
//MessageBox.Show("No error or user! Unknown reason.");
return null;
}
var cookieHelper = new Helpers.CookieHelper();
//FormsAuthenticationTicket authtick = new FormsAuthenticationTicket(1, response.AppUser.Username, DateTime.Now, DateTime.Now.AddSeconds(response.AppUser.ExpiresIn *2), true, response.AppUser.RefreshToken);
var authtick = cookieHelper.CreateAuthTicket(response.AppUser, true);
var authCookie = cookieHelper.CreateAuthCookie(authtick);
Response.Cookies.Add(authCookie);
var tokenCookie = cookieHelper.CreateTokenCookie(response.AppUser, true);
Response.Cookies.Add(tokenCookie);
// If caching roles in userData field then extract
string[] roles = response.AppUser.Permissions.Select(x => x.PermissionName).ToArray(); // = authTicket.UserData.Split(new char[] { '|' });
// Create the IIdentity instance
IIdentity id = new FormsIdentity(authtick);
var newIdent = new ClaimsIdentity(id);
foreach (var item in roles)
{
newIdent.AddClaim(new Claim(ClaimTypes.Role, item));
}
ClaimsPrincipal cp = new ClaimsPrincipal(newIdent);
// Create the IPrinciple instance
IPrincipal principal = cp; //new GenericPrincipal(id, roles);
Thread.CurrentPrincipal = cp;
AppDomain.CurrentDomain.SetThreadPrincipal(cp);
// Set the context user
HttpContext.User = principal;
//IOwinContext context = Request.GetOwinContext();
//var authManager = context.Authentication;
//authManager.SignIn(newIdent);
this.AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = true }, newIdent);
return response;
在上面的代码中,我可以在设置HttpContext.user之后立即看到我的用户及其声明
下面是我正在检查用户以确保其成功:
private AppUser AuthenticateUser(string userName, string password, bool rememberMe)
{
//bool userAuthenticated = false;
AuthenticationResponse userAuthenticated = null;
bool success = false;
try
{
userAuthenticated = AuthenticateUserByService(userName, password, rememberMe);
var c = User.Identity;
success = !userAuthenticated.IsError;
}
catch { }
}
当我将c设置为用户时,声明一度消失了
我想这可能很重要,所以下面是我创建cookie和票据的地方:
internal class CookieHelper
{
internal FormsAuthenticationTicket CreateAuthTicket(AppUser appUser, bool isPersistent)
{
return new FormsAuthenticationTicket(
1,
appUser.Username,
DateTime.Now,
DateTime.Now.AddSeconds((appUser.ExpiresIn * 2)),
isPersistent,
appUser.RefreshToken == null ? "" : appUser.RefreshToken,
FormsAuthentication.FormsCookiePath);
}
internal HttpCookie CreateAuthCookie(FormsAuthenticationTicket authTicket)
{
// Encrypt the ticket.
string encAuthTicket = FormsAuthentication.Encrypt(authTicket);
// Create the cookie.
HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encAuthTicket);
authCookie.Expires = authTicket.Expiration;
return authCookie;
}
internal HttpCookie CreateTokenCookie(AppUser appUser, bool isPersistent)
{
// Create token ticket
FormsAuthenticationTicket tokenTicket = new FormsAuthenticationTicket(
1,
appUser.Username,
DateTime.Now,
DateTime.Now.AddSeconds(appUser.ExpiresIn),
isPersistent,
appUser.AccessToken);
// Encrypt the ticket.
string encTokenTicket = FormsAuthentication.Encrypt(tokenTicket);
// Create the cookie.
HttpCookie tokenCookie = new HttpCookie("Mellon", encTokenTicket);
tokenCookie.Secure = false;
tokenCookie.Name = "Mellon";
//tokenCookie.Path = Request.ApplicationPath;
tokenCookie.Expires = tokenTicket.Expiration;
return tokenCookie;
}
}
我觉得需要向我提问才能获得正确的帮助信息。我只是迷路了,在这一点上,我的隧道视力正在杀死我。在这一点上,任何洞察、暗示或爱都会有所帮助。提前谢谢
更新
在这里,我检查cookie是否仍然有效,如果它仍然有效,则执行刷新
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
HttpCookie tokenCookie = Request.Cookies["Mellon"];
if (authCookie == null)
{
FormsAuthentication.SignOut();
HttpContext.Current.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
return;
}
// Extract the forms authentication cookie
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (authTicket == null || authTicket.Expired)
{
FormsAuthentication.SignOut();
HttpContext.Current.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
return;
}
// Extract the forms authentication cookie
//FormsAuthenticationTicket newAuthTicket;
if (tokenCookie == null)
{
RefreshCookies(authTicket);
return;
}
else
{
FormsAuthenticationTicket tokenTicket = FormsAuthentication.Decrypt(tokenCookie.Value);
// If the access token is stil good, then continue on.
if (tokenTicket.Expired)
{
RefreshCookies(authTicket);
return;
}
}
var tick = (FormsIdentity)HttpContext.Current.User.Identity;
if (tick == null)
{
FormsAuthentication.SignOut();
HttpContext.Current.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
return;
}
if (authTicket.UserData != tick.Ticket.UserData) // .Ticket.UserData)
{
RefreshCookies(authTicket);
}
}
基本上我拥有的是我的AuthToken,它持有我的刷新令牌和第二个cookie,它持有我的AccessToken。这些是在AuthenticateUserByService方法中创建的,该方法从我们的webapi获取所有信息,并在response.AppUser中返回。因此,我不能使用forms.setauthcookie,因为这将覆盖其中已有的内容
正在发生的事情的图像证明:
正如我在评论中所说,要消化您发布的代码片段相当困难,因此我将分解为更小的逻辑块 让我们从一个
身份验证服务类开始:
身份验证服务调用客户端存储库
,并返回用户
public class AuthenticationService
{
IUserRepository _userRepo;
public AuthenticationService()
{
_userRepo = new UserRepository();
}
public User GetUser(string username, string password)
{
return _userRepo.FindByCredentials(username, password);
}
public User GetUserByUserName(string username)
{
return _userRepo.FindByUserName(username);
}
}
在Global.asax
中,我们需要通过飞行前请求进行身份验证
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
//Check the request for a cookie
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
//Decrypt the Auth Cookie vale
var ticket = FormsAuthentication.Decrypt(authCookie.Value);
//Instantiate Auth Service
var _authService = new AuthenticationService();
//Get user by encrypted name stored in ticket
var user = _authService.GetUserByUserName(ticket.Name);
if (user != null)
{
// Create a ClaimsIdentity with all the claims for this user.
Claim emailClaim = new Claim("Email", (!string.IsNullOrWhiteSpace(user.Email)) ? user.Email: "");
Claim AddressClaim = new Claim("Address", (!string.IsNullOrWhiteSpace(user.Address)) ? user.Address: "");
Claim userNameClaim = new Claim(ClaimTypes.Name, (!string.IsNullOrWhiteSpace(user.Username)) ? user.Username : "");
//Add claims to a collection of claims
List<Claim> claims = new List<Claim>
{
emailClaim ,
AddressClaim ,
userNameClaim
};
//Create forms Identity
FormsIdentity formsIdentity = new FormsIdentity(ticket);
//Create Claims Identity
ClaimsIdentity claimsIdentity = new ClaimsIdentity(formsIdentity);
//Add Claims
claimsIdentity.AddClaims(claims);
//Create Claims Principal
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
//Assign principal to current user
HttpContext.Current.User = claimsPrincipal;
}
}
}
正如我所说的,这是一个天真的尝试,请考虑多一点安全性,但这是工作SLN,我很快就放在一起,我可以访问索赔。
查看您的代码后,感觉您只是缺少添加用户声明。基本上发生的是,声明在my global.asax中被覆盖。到目前为止,我的解决方案是在我的global.asax中重建我的索赔 向声明中添加用户详细信息的逻辑在哪里?很抱歉,但你的意思是什么?不用担心,我会很快发布答案,但我会将其分解为更小的部分,这将是一个有效的解决方案。很难理解所贴的片段。现在我明白你的意思了,因为某种原因,它没有第一次点击。让我试试,我很快会给你回复。你在哪里能解决这个问题?我将把我的应用程序\u AuthenticateRequest方法添加到我的原始帖子中。你在这里所拥有的对我正在努力实现的目标不太管用。我会看看我是否能在上面更新更多关于原因的信息。请放心,这也可能有助于从其他人那里得到答案。是的,问的人越多,我就能更好地解释发生了什么。我对这个问题的理解不是很好,而且我的解释能力也很差。
[HttpPost]
[AllowAnonymous]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
var user = _authService.GetUser(model.UserName, model.password);
if (user != null)
{
FormsAuthentication.SetAuthCookie(model.UserName,model.RememberMe);
return Redirect(model.ReturnUrl); }
}
}
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);