在属性类中获取WCF端点http请求上下文

时间:2017-06-25 07:22:16

标签: c# wcf

我想在属性类中获取端点方法请求上下文。

所以,如果我有这个端点

[Auth]
[WebInvoke(UriTemplate ="/post",
           Method = "POST",
           ResponseFormat = WebMessageFormat.Json,
           RequestFormat = WebMessageFormat.Json)]
public string CreatePost(var data)

然后在课堂上

public class Auth : Attribute
{

    public bool IsAuthorised()
    {
        // get the request then add something to the endpoint context

1 个答案:

答案 0 :(得分:1)

请看下面的WCF声明。

[BasicHttpAuthorization(RequireSsl = true)]
[WebGet(UriTemplate = "")]
public IEnumerable Get()
{
 .....
}

因此BasicHttpAuthorization实施Attribute

[AttributeUsage(AttributeTargets.Method)]
public class BasicHttpAuthorizationAttribute : Attribute
{
    bool requireSsl = true;

    public bool RequireSsl
    {
        get { return requireSsl; }
        set { requireSsl = value; }
    }
}

现在您可以查看HttpOperationHandler的实现。

1)如果用户尚未通过身份验证或提供错误的凭据,我们会在OnHandle方法中返回HttpResponseException。我们将状态代码设置为401.这会创建功能,浏览器会要求输入用户名/密码,然后自动重新发送请求。

2)在ParseAuthHeader中,我们从请求中获取用户名和密码。然后,您可以以自己的方式使用此信息。例如,使用您自己的自定义成员资格提供程序。

3)如果用户可以访问此方法,则创建GenericPrincipal并将其分配给HttpContext.Current.User

public class BasicHttpAuthorizationOperationHandler : HttpOperationHandler
{

    BasicHttpAuthorizationAttribute basicHttpAuthorizationAttribute;

    public BasicHttpAuthorizationOperationHandler(BasicHttpAuthorizationAttribute authorizeAttribute)
        : base("response")
    {
        basicHttpAuthorizationAttribute = authorizeAttribute;
    }

    protected override HttpRequestMessage OnHandle(HttpRequestMessage input)
    {
        if (Authenticate(input))
        {
            return input;
        }
        else
        {
            var challengeMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized);
            challengeMessage.Headers.Add("WWW-Authenticate", "Basic");
            throw new HttpResponseException(challengeMessage);
        }
    }

    private bool Authenticate(HttpRequestMessage input)
    {
        if (basicHttpAuthorizationAttribute.RequireSsl && !HttpContext.Current.Request.IsSecureConnection && !HttpContext.Current.Request.IsLocal) return false;

        if (!HttpContext.Current.Request.Headers.AllKeys.Contains("Authorization")) return false;

        string authHeader =  HttpContext.Current.Request.Headers["Authorization"];

        IPrincipal principal;
        if (TryGetPrincipal(authHeader, out principal))
        {
            HttpContext.Current.User = principal;
            return true;
        }
        return false;
    }

    private bool TryGetPrincipal(string authHeader, out IPrincipal principal)
    {
        var creds = ParseAuthHeader(authHeader);
        if (creds != null)
        {
            if (TryGetPrincipal(creds[0], creds[1], out principal)) return true;
        }

        principal = null;
        return false;
    }

    private string[] ParseAuthHeader(string authHeader)
    {
        // Check this is a Basic Auth header
        if (authHeader == null || authHeader.Length == 0 || !authHeader.StartsWith("Basic")) return null;

        // Pull out the Credentials with are seperated by ':' and Base64 encoded
        string base64Credentials = authHeader.Substring(6);
        string[] credentials = Encoding.ASCII.GetString(Convert.FromBase64String(base64Credentials)).Split(new char[] { ':' });

        if (credentials.Length != 2 || string.IsNullOrEmpty(credentials[0]) || string.IsNullOrEmpty(credentials[0])) return null;

        // Okay this is the credentials
        return credentials;
    }

    private bool TryGetPrincipal(string userName, string password, out IPrincipal principal)
    {
        // this is the method that does the authentication
        // you can replace this with whatever logic you'd use, but proper separation would put the

        if (userName.Equals("test") && password.Equals("test"))
        {                
            principal = new GenericPrincipal(new GenericIdentity(userName), new string[] {"Admin", "User"});

            return true;
        }
        else
        {
            principal = null;
            return false;
        }
    }
}