How can I develop a custom AuthorizeAttribute that accepts a login OR a token?

匆匆过客 提交于 2019-12-10 10:56:21

问题


In my MVC 5 application, I decorate my controllers as follows:

[Authorize]
public class Controller
{
  ..

However, one requirement I have is to use a token to authorize an action without going to the login screen. ie: http://{website}/Action?token={/* token for this user */}

Thus, how can I develop a custom AuthorizeAttribute that accepts a login (default behavior) OR a token (custom, required behavior)?

In other words, if I use http://{website}/Action, I would be redirected to the login screen (if I am not authorized), but if I use http://{website}/Action?token={/* token for this user */}, I would be authorized and redirected to said action.


[TokenAuthorize] class

public class TokenAuthorize : AuthorizeAttribute
{
    private const string SecureToken = "token";

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (Authorize(filterContext))
        {
            return;
        }

        HandleUnauthorizedRequest(filterContext);
    }

    private bool Authorize(AuthorizationContext actionContext)
    {
        try
        {
            HttpRequestBase request = actionContext.RequestContext.HttpContext.Request;
            string token = request.Params[SecureToken];

            return SecurityManager.IsTokenValid(token);
        }
        catch (Exception)
        {
            return false;
        }
    }
}

If I decorate my controllers with:

[Authorize]
[TokenAuthorize]
public class Controller
{
  ..

It is processed as Authorize AND TokenAuthorize(1). I need to develop a way to process such as Authorize OR TokenAuthorize


回答1:


How about decorating with only TokenAuthorize and then falling back to the default behavior if no token exists?

TokenAuthorize.cs

protected override bool AuthorizeCore(HttpContextBase httpContext)
{
    bool isTokenAuthorized = HasValidToken(...);
    if(isTokenAuthorized) return true;

    bool isDefaultAuthorized = base.AuthorizeCore(httpContext);
    if(isDefaultAuthorized) return true;

    return false;
}

MyController.cs

[TokenAuthorize]
public class MyController
{
    ...
}



回答2:


Shoe's answer led me on the right track.

I implemented his suggestion and did the following in my Authorize function:

private bool Authorize(AuthorizationContext actionContext)
{
    try
    {
        HttpContextBase context = actionContext.RequestContext.HttpContext;
        string token = context.Request.Params[SecurityToken];

        bool isTokenAuthorized = SecurityManager.IsTokenValid(token);
        if (isTokenAuthorized) return true;

        bool isDefaultAuthorized = AuthorizeCore(context);
        return isDefaultAuthorized;
    }
    catch (Exception)
    {
        return false;
    }
}

Decorating with just [TokenAuthorize], I can authorize an action via login (default) OR via token.




回答3:


Perfect Code: Validate token from DB

public class TokenAuthorize : AuthorizeAttribute
{
    string _connectionString;

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (Authorize(filterContext))
        {
            return;
        }

        HandleUnauthorizedRequest(filterContext);
    }


    protected bool Authorize(AuthorizationContext httpContext)
    {
        bool isTokenAuthorized = HasValidToken();
        if(isTokenAuthorized) return true;

        return false;
    }
    protected bool HasValidToken()
    {
        string token = string.Empty;
        token = HttpContext.Current.Request.Params["token"];
        _connectionString = WebConfigurationManager.ConnectionStrings["SqlConnectionString"].ConnectionString;
        SqlTransaction txn = null;
        using (SqlConnection conn = new SqlConnection(_connectionString))
        {
            conn.Open();
            txn = conn.BeginTransaction();
            List<SqlParameter> parameters = new List<SqlParameter>();
            SqlParameter parameter = new SqlParameter();
            parameters.Add(new SqlParameter("@token", token));

            parameter = new SqlParameter("@return_ops", 0);
            parameter.Direction = ParameterDirection.Output;
            parameters.Add(parameter);

            SqlHelper.ExecuteNonQuery(txn, CommandType.StoredProcedure, "[master_LoggedInUsers]", parameters.ToArray());

            int result = Convert.ToInt32(parameters[1].Value);

            if (result <= 0)
            {
                return false;
            }
            else return true;
        }
    }
}

[TokenAuthorize] public class MasterController : Controller {}



来源:https://stackoverflow.com/questions/35184229/how-can-i-develop-a-custom-authorizeattribute-that-accepts-a-login-or-a-token

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!