tags:

views:

124

answers:

2

I would like to add integrated windows security to one of my views, is this possible?

On web-forms I would just find the file in IIS and add the file security features there, obv MVC being non-file based this doesnt seem to work.

The site is using Forms Auth - Trying to make this work for MVC http://beensoft.blogspot.com/2008/06/mixing-forms-and-windows-authentication.html

Thanks

+3  A: 

You can use security attributes on the Action methods called the AuthorizeAttribute.

For example,

[Authorize(Roles = "Domain Users")]
public ActionResult Create(FormCollection collection)

To then restrict access to links or such, or even hide them from users, we implemented an extension method called SecurityTrimmedActionLink which we mostly adapted/borrowed from http://www.inq.me/post/ASPNet-MVC-Extension-method-to-create-a-Security-Aware-HtmlActionLink.aspx.

public static string SecurityTrimmedActionLink(this HtmlHelper htmlHelper, string linkText, string action, object routeValues)
{
    if (IsAccessibleToUser(action, htmlHelper.ViewContext.Controller))
    {
        return htmlHelper.ActionLink(linkText, action, routeValues);
    }

    return string.Empty;
}

public static string SecurityTrimmedActionLink(this HtmlHelper htmlHelper, string linkText, string action)
{
    return SecurityTrimmedActionLink(htmlHelper, linkText, action, null);
}

private static bool IsAccessibleToUser(string action, ControllerBase controller)
{
    ArrayList controllerAttributes = new ArrayList(controller.GetType().GetCustomAttributes(typeof(AuthorizeAttribute), true));
    ArrayList actionAttributes = new ArrayList();
    MethodInfo[] methods = controller.GetType().GetMethods();
    foreach (MethodInfo method in methods)
    {
        object[] attributes = method.GetCustomAttributes(typeof(ActionNameAttribute), true);
        if ((attributes.Length == 0 && method.Name == action) || (attributes.Length > 0 && ((ActionNameAttribute)attributes[0]).Name == action))
        {
            actionAttributes.AddRange(method.GetCustomAttributes(typeof(AuthorizeAttribute), true));
        }
    }
    if (controllerAttributes.Count == 0 && actionAttributes.Count == 0)
        return true;

    IPrincipal principal = HttpContext.Current.User;
    string roles = "";
    string users = "";
    if (controllerAttributes.Count > 0)
    {
        AuthorizeAttribute attribute = controllerAttributes[0] as AuthorizeAttribute;
        roles += attribute.Roles;
        users += attribute.Users;
    }
    if (actionAttributes.Count > 0)
    {
        AuthorizeAttribute attribute = actionAttributes[0] as AuthorizeAttribute;
        roles += attribute.Roles;
        users += attribute.Users;
    }

    if (string.IsNullOrEmpty(roles) && string.IsNullOrEmpty(users) && principal.Identity.IsAuthenticated)
        return true;

    string[] roleArray = roles.Split(',');
    string[] usersArray = users.Split(',');
    foreach (string role in roleArray)
    {
        if (role == "*" || principal.IsInRole(role))
            return true;
    }
    foreach (string user in usersArray)
    {
        if (user == "*" || (principal.Identity.Name.Equals(user, StringComparison.InvariantCultureIgnoreCase)))
            return true;
    }
    return false;
}
J. Steen
Yea this is fine, but in our case we dont have set roles. What I am trying to do is add Integrated Windows Security to a couple of Views (The rest of the site is form auth) - http://msdn.microsoft.com/en-us/library/ms972958.aspx
Pino
Use can set Authorize(Users = "Pete User") as well... look up other examples of the use of AuthorizeAttribute. =)
J. Steen
You can even leave it at [Authorize] to let the method know you simply want an authorized user.
J. Steen
Thats all great, but its not helping in mixing the auth modes?
Pino
Try this article: http://www.15seconds.com/Issue/050203.htm
J. Steen
Might have a look at this, as well: http://blog.wekeroad.com/blog/aspnet-mvc-securing-your-controller-actions/
J. Steen
He says the site is using forms authentication. So the `Authorize` attribute won't help with Windows authentication.
çağdaş
http://mikehadlow.blogspot.com/2008/03/forms-authentication-with-mvc-framework.html
J. Steen
+1  A: 

Since the site is already using forms authentication, you won't be able to check the roles or names with the Authorize attribute on your controllers/actions. Because that will use the current provider (forms), instead of the Windows.

A quick and not-so-elegant solution would be having a function like the one below and checking against it before returning the view.

bool IsWindowsAuthenticated() {
    //the following classes are under System.Security.Principal
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(identity);
    return principal.Identity.IsAuthenticated;
}

Note that there might be a better way to do this. I'm just providing that example in case it might be useful.

çağdaş
Nice. I forgot I only used the HttpContext user principal in the method I posted. =)
J. Steen
@J. Steen, I was going to explain that in the comments but then I thought an answer would be better.
çağdaş
@çağdaş, Definitely. =)
J. Steen