使用Asp.Net Web Api的JWT身份验证不起作用

时间:2018-11-14 08:46:52

标签: c# asp.net-web-api cookies jwt

对于我的应用程序,我使用JWT来验证我的用户。

我的两个课程:

internal class JwtAuthenticationAttribute : AuthorizeAttribute
{

    private const string CookieName = "jwt";

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        base.OnAuthorization(actionContext);
    }
    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        base.HandleUnauthorizedRequest(actionContext);
    }

    public override Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        return base.OnAuthorizationAsync(actionContext, cancellationToken);
    }

    protected override bool IsAuthorized(HttpActionContext httpContext)
    {
        var authToken = HttpContext.Current.Request.Cookies[CookieName];

        if (authToken == null)
        {
            return false;
        }

        var jwtValue = authToken.Value;
        var isValid = JwtManager.ValidateToken(jwtValue, HttpContext.Current.Request.UserHostName, HttpContext.Current.Request.UserAgent, out var userId, out var expireAt);
        if (!isValid) return false;

        isValid = HasRole(userId);
        //var ts = expireAt.Subtract(DateTime.UtcNow);
        //var limitTs = new TimeSpan(0, 0, 30, 0);
        //if (ts.TotalMilliseconds < 0)
        //{
         //   return false;
        //}
       /* else if (ts.TotalMilliseconds > 0 && ts < limitTs)
        {
            var token = JwtManager.GenerateToken(userId);
            var response = HttpContext.Current.Response;
            response.Cookies.Add(new HttpCookie(CookieName, token));
            var host = System.Web.HttpContext.Current.Request.UserHostAddress;
            var agent = System.Web.HttpContext.Current.Request.UserAgent;
            var service = new ServiceToken();
            service.Add(new Token(token, userId, host, agent));
        }*/
        return isValid;
    }

    private bool HasRole(Guid userId)
    {
        var serviceUser = new ServiceUser();
        var userRoles = serviceUser.GetRoles(userId).Select(x => x.Label).ToList();
        var res = true;
        var requiredRoles = Roles.Split(',');

        if (String.IsNullOrWhiteSpace(Roles) || requiredRoles.Length <= 0)
            return true;

        res = false;
        foreach (var role in requiredRoles)
        {
            if (userRoles.Contains(role))
            {
                res = true;
            }
        }

        return res;
    }

    protected Task<IPrincipal> AuthenticateJwtToken(string token)
    {
        var request = HttpContext.Current.Request;
        if (!JwtManager.ValidateToken(token, request.UserHostName, request.UserAgent, out var userId,
            out _)) return Task.FromResult<IPrincipal>(null);

        var claims = new List<Claim>
        {
            new Claim("Id", userId.ToString()),
        };

        var identity = new ClaimsIdentity(claims, "jwt");
        IPrincipal user = new ClaimsPrincipal(identity);

        return Task.FromResult(user);
    }
}

第二类:

public class JwtManager
{
    public const string Secret = ""; // your symmetric

    public static string GenerateToken(Guid userId, int expireMinutes = 20)
    {
        var symmetricKey = Convert.FromBase64String(Secret);
        var tokenHandler = new JwtSecurityTokenHandler();

        var now = DateTime.UtcNow;
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new[]
            {
                new Claim("Id", userId.ToString())
            }),
            Expires = DateTime.MaxValue,
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(symmetricKey), SecurityAlgorithms.HmacSha256Signature)
        };

        var stoken = tokenHandler.CreateToken(tokenDescriptor);
        var token = tokenHandler.WriteToken(stoken);

        return token;
    }

    public static ClaimsPrincipal GetPrincipal(string token, out DateTime expireAt)
    {
        expireAt = DateTime.MinValue;
        try
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var jwtToken = tokenHandler.ReadToken(token) as JwtSecurityToken;

            if (jwtToken == null)
                return null;

            var symmetricKey = Convert.FromBase64String(Secret);

            var validationParameters = new TokenValidationParameters()
            {
                RequireExpirationTime = false,
                ValidateIssuer = false,
                ValidateAudience = false,
                IssuerSigningKey = new SymmetricSecurityKey(symmetricKey)
            };

            SecurityToken securityToken;
            var principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken);
            expireAt = securityToken.ValidTo;
            return principal;
        }

        catch (Exception e)
        {
            //should write log
            return null;
        }
    }

    public static bool ValidateToken(string token, string host, string agent, out Guid userId, out DateTime expireAt)
    {
        userId = Guid.Empty;
        var simplePrinciple = JwtManager.GetPrincipal(token, out expireAt);
        if (simplePrinciple == null)
            return false;

        var identity = simplePrinciple.Identity as ClaimsIdentity;

        if (identity == null)
            return false;

        if (!identity.IsAuthenticated)
            return false;

        var idClaim = identity.FindFirst("Id");
        if (idClaim?.Value != null) userId = Guid.Parse(idClaim?.Value);

        if (userId == Guid.Empty)
            return false;

        // More validate to check whether username exists in system
        var serviceToken = new ServiceToken();
        return serviceToken.Exists(x => x.Value == token );
    }      
}

我在控制器上使用一个属性来确定哪个需要认证。

和这里的代码,我如何用我的jtw添加cookie:

    private string SetTokenForUser(Guid username)
    {
        string token = JwtManager.GenerateToken(username);
        string host = HttpContext.Current.Request.UserHostAddress;
        string agent = HttpContext.Current.Request.UserAgent;
        HttpContext.Current.Response.Cookies.Add(new HttpCookie(CookieName, token));
        var tokeNewn = new Token(token, username, host, agent);
        _serviceToken.Add(tokeNewn);
        return tokeNewn.Value;
    }

我的问题是,有时对于某些用户,当他们登录并在jwtcontroller上调用方法时,他们会收到未经授权的错误,即使当我删除cookie时,问题仍然存在。我在PC和手机上有问题。

我设置Cookie的方式好吗?

0 个答案:

没有答案