用户声明似乎正在沿管线的某个地方被替换 [英] User Claims seem to be getting replaced somewhere along the pipeline

查看:85
本文介绍了用户声明似乎正在沿管线的某个地方被替换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

**编辑:如果有人有任何线索可以更好地向我询问或告知您这个问题,请告诉我。

** If anyone has any clue how i can better ask or inform you guys about this problem please let me know.

因此,我正在创建自定义声明并尝试将它们添加到我的用户中。在添加请求之后,在管道中略微向下一行,我立即在User.Identity中看到了声明,但是当它到达我的Global.asax时,User.Identity丢失了我的所有声明,但其中一项丢失了。我还认为用户在同一时间正在从ClaimsPrinciapl更改为GenericPrincipal。我不知道我是否理解或很好地解释了这一点。甚至不确定所有要发布的代码是什么,但是我将在下面发布一些代码。

So I am creating custom claims and trying to add them to my user. I see the claims in the User.Identity right after I add them and slightly down the line in the pipeline but by the time it gets to my Global.asax the User.Identity has lost all but one of my claims. I also think the user is changing from a claimsPrinciapl to a GenericPrincipal during the same time. I dont know if I am understanding this or explaining this very well. Not even sure what all code to post but I will post some below.

这是我的用户经过身份验证,创建cookie和声明的地方。注意我一直在尝试很多东西,所以可能会有一些奇怪的代码:

This is where my user is Authenticated and cookies and claims are create. Note i have been trying a lot of stuff so this might have some weird code:

    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之后,我可以立即看到我的用户及其声明。 。

In the above code, I can see my user and his claims right after I set the HttpContext.User.

下面是我签出用户以确保成功的方法:

Below is just me checking out the User to make sure it was successful:

   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设置给用户时,声明消失了。

At one point the claims disappeared by the time I set c to the user.

我认为这可能很重要,因此下面是我创建Cookie和票证的地方:

And i figured this might be important so below is where i create my cookies and tickets:

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;
    }
}

我觉得需要向我提问获得正确的信息以寻求帮助。我只是迷路了,在这一点上,我的洞察力正在杀死我。在这一点上,任何见识或暗示或爱都将有所帮助。预先感谢。

I feel like questions will need to be asked of me to get the right info for help. I am just lost and at this point my tunnel vision is killing me. Any insight or hints or jsut some love at this point would help. Thanks in advance.

更新

这是我检查cookie是否在其中的地方仍然有效,如果仍然有效,请执行刷新。

This is where I check if cookie is still valid and perform a refresh if its still valid.

 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,因为那样会覆盖那里已经存在的内容。

Basically what I have is my AuthToken which holds me refresh token and a second cookie that holds me AccessToken. Those are created in the AuthenticateUserByService method which gets all that info from our webapi and is returned in response.AppUser. So I can't use forms.setauthcookie because that would overwrite what is already in there.

发生了什么的图像证明:

Image proof of whats going on:

推荐答案

正如我在评论中所说,要消化您发布的摘要相当困难,因此我将分解为较小的逻辑块。

As I said in my comment, it's rather tough to digest the snippets you have posted, So I'll break down into smaller logical chunks.

让我们开始使用身份验证服务类

身份验证服务调用客户端存储库并返回 User

Authentication Service calls the client repository and returns a User

 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中我们需要使用飞行前请求进行身份验证。

In the Global.asax we need to authenticate with pre-flight request.

      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;
                }
            }
        }

登录控制器:

        [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);

正如我说过的那样,这是一个天真的尝试,请考虑再增加一点安全性,但这是

As I've said this is a naïve attempt, please consider a little more security, but this is working sln I've quickly put together and I can access the claims.

已经看过您的代码,感觉您只是缺少添加用户的Claims。

Having looked at your code, it feels that your just missing adding the Claims of the user.

这篇关于用户声明似乎正在沿管线的某个地方被替换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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