We're using ABP 7.3
We'd like for all classes inheriting from the [project]AppServiceBase to be authorized by default so their methods are only available to users which are logged in. There are some exceptions (off course), in those cases we use the [AbpAllowAnonymous] attribute.
We could (of course) decorate every class with the [AbpAuthorize] attribute but that's asking for problems since someone might forget to do that (ask me how I know) and then that functionality is publicly available.
I tried putting the [AbpAuthorize] attribute on the [project]AppServiceBase (from which all xxxAppService class inherits) but the attribute doesn't get inherited by the subclass.
I then created a myAbpAuthorize attribute and put that on the [project]AppServiceBase, that works, now the subclasses have this attribute as well, but the authorization part doesn't work.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class MyAbpAuthorizeAttribute : AbpAuthorizeAttribute
{
}
Related
I wrote a class like this
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class AbilityTemplateAttribute {
}
It makes
Error CS0641 Attribute 'AttributeUsage' is only valid on classes derived from System.Attribute
How can I make my own Attribute work similarly, that is, does not allow to be attached to classes not inherited from a certain class?
The only option I know of to have similar behaviour with custom attribute is to write custom Roslyn analyzer. If your are ok going down this route here some documentation:
Getting Started Writing a Custom Analyzer & Code Fix
How to write a Roslyn Analyzer
Tutorial: Write your first analyzer and code fix
As following to this answer I have created an AuthorizeAttribute class in my projects default namespace. So that the compiler will automatically pick it up instead of MVC's standard one. But it picks System.Web.Mvc.Authorizeattribute.
If I include my projects namespace, which is using TestIdentitySample; then the following error was shown
'Authorize' is an ambiguous reference between 'System.Web.Mvc.Authorizeattribute' and 'ProjectDefaultNamespace'
Please be noted that I do not want to use fully qualified name or namespace alias or other Custome Attributes name.
My AuthorizeAttribute Class
namespace TestIdentitySample
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAuthenticated)
{
filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
}
I just want that the compiler will automatically pick it up instead of MVC's standard one if it is possible. Thanks in advance for any help.
You should rethink your approach of creating your own attribute with the same name. This is problematic for two reasons:
Readers of your code might think it's the built-in attribute and not your own. They might get a misconception about what your code does. This is especially important for the AuthorizeAttribute, since security is a usually a critical issue in a web application
You could run into naming conflicts. That's exactly what happended here.
You can resolve your issue in different ways:
Rename your attribute
A good solution - and the solution that I would recommend - would be to simply rename your custom attribute so that it's clear that it is yours and the naming conflict gets resolved.
Specify the namespace explicitly
If you want to keep the same name of the attribute, you can resolve the naming conflict by explicitly specifying your own namespace:
[ProjectDefaultNamespace.Authorize]
Use a namespace alias
You can also specify a namespace alias in your using list:
using MyAuthorizeAttribute = ProjectDefaultNamespace.AuthorizeAttribute;
And then apply it like:
[MyAuthorizeAttribute]
But then again, why not just giving it your own custom name? It will look the same in code, just without the additional complication of the alias.
I'm implementing claims based security in my .net 4.5 application. Lots of hoops to jump through, but it is basically working.
The only part I don't like is that I can't create my own attributes. ClaimsPrincipalPermissionAttribute is sealed. Why?
I'm always marking throughout my application such as:
[ClaimsPrincipalPermission(SecurityAction.Demand, Resource = "Foo", Operation = "Bar")]
And since I want my resource and operation strings to not get misspelled and be easily refactorable, I have created classes so I can do this:
[ClaimsPrincipalPermission(SecurityAction.Demand, Resource = Resources.Foo, Operation = Operations.Foo.Bar)]
(Note that since different resources may have different operations, the operations themselves are subclassed by resource.)
This all works fine and dandy, but it's a hell of a lot to type or copy/paste every time. I'd rather do something like:
[DemandPermission(Resources.Foo, Operations.Foo.Bar)]
I could create this attribute, but I would need to inherit from ClaimsPrincipalPermissionAttribute, which I can't because it's sealed. :(
Is there some other way to approach this? Perhaps I don't need to inherit, but can I register my own attribute type somehow so it works in all the same places?
ClaimsPrincipalPermissionAttribute derives from CodeAccessSecurityAttribute. It does almost nothing except implement CreatePermission() returning a new ClaimsPrincipalPermission based on the value of Resource and Operation that you pass in.
You could implement a new class deriving from CodeAccessSecurityAttribute (this is not sealed) that does what you want.
Using JustDecompile, you can see that the code in ClaimsPrincipalPermissionAttribute is simple. You could make your own attribute like this:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)]
public sealed class DemandPermissionAttribute : CodeAccessSecurityAttribute
{
public Operations Operation { get; set; }
public Resources Resource { get; set; }
public DemandPermissionAttribute(SecurityAction action = SecurityAction.Demand)
: base(action)
{
}
public override IPermission CreatePermission()
{
return new ClaimsPrincipalPermission(this.Resource.ToString(), this.Operation.ToString());
}
}
One important thing to note on this is that you must define your custom attribute in a separate assembly from the one that is referencing it, otherwise the framework will throw a TypeLoadException as described here
http://msdn.microsoft.com/en-us/library/vstudio/yaah0wb2.aspx
Also, note the use of the default value for the constructor parameter. You need to have a constructor that takes a SecurityAction parameter for the attribute to get instantiated by the framework. Maybe DemandPermission is a bad name in this case, because you can override the SecurityAction to be something other than SecurityAction.Demand.
ClaimsPrincipalPermissionAttribute is sealed. Why?
Eric Lippert talked about the commonness of sealed in Framework types, and since we are talking about code security, this bit is very important:
Every time you implement a method which takes an instance of an unsealed type, you MUST write that method to be robust in the face of potentially hostile instances of that type. You cannot rely upon any invariants which you know to be true of YOUR implementations, because some hostile web page might subclass your implementation, override the virtual methods to do stuff that messes up your logic, and passes it in. Every time I seal a class, I can write methods that use that class with the confidence that I know what that class does.
This is even more important in this case, ClaimsPrincipalPermissionAttribute is checked via IClaimsPrincipal an interface. So by making ClaimsPrincipalPermissionAttribute sealed, they allow any implementer of IClaimsPrincipal to not have to worry about hostile implementations. This is quite a savings, given this is all security related.
My immediate reaction is that that isn't a whole lot to write - and how often do you need to write it? If it is general to actions in your controller, place it on the controller - if is applicable to many controllers, create a ControllerBase with that attribute.
If your case is more special than that, I suppose you are forced to implement your own variety of that attribute.
I'm reading Pro C# 2010 and the .Net 4 Platform by Andrew Troelsen.
In Chapter 15 about Attributes exists a note:
Note: For security reasons, it is considered a .Net best practice to design all custom attributes as sealed.
The author doesn't explain why, can someone explain why?
CA1813: Avoid unsealed attributes:
The .NET Framework class library provides methods for retrieving
custom attributes. By default, these methods search the attribute
inheritance hierarchy; for example Attribute.GetCustomAttribute
searches for the specified attribute type, or any attribute type that
extends the specified attribute type. Sealing the attribute eliminates
the search through the inheritance hierarchy, and can improve
performance.
Ref: https://learn.microsoft.com/visualstudio/code-quality/ca1813-avoid-unsealed-attributes
Attributes are simply metadata discovered at runtime. As it is quoted, if someone else derives from your custom attribute class, by default .NET will find them too, which may imply a security risk if the derived attribute class is modifying the behavior of your original attribute in a way to you never intended to.
Even though performance is the prime reason to seal attribute classes, here is a formidable article dealing with its security side.
There is one more reason to seal attributes.
Consider the following attribute:
[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false)]
public class Attr1 : Attribute
{
}
Here you allow only single attribute decoration: AllowMultiple = false
Compiler won't allow this:
[Attr1]
[Attr1]
public class Foo
{
}
Later in your code you can safely call memberInfo.GetCustomAttribute() which will throw AmbiguousMatchException if more then one attribute of the given type was found.
Let's now inherit:
public class Attr2 : Attr1
{
}
Now compiler is silent.
[Attr1]
[Attr2]
public class Foo
{
}
So if later somebody inherits from your attribute and passes back to your code some entity marked with both attributes unexpected exception will be thrown.
Full example:
class Program
{
static void Main(params string[] args)
{
typeof(Foo).GetCustomAttribute<Attr1>();
}
[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class Attr1 : Attribute
{
}
public class Attr2 : Attr1
{
}
[Attr1]
[Attr2]
public class Foo
{
}
[Attr1]
public class Bar : Foo
{
}
}
Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries just says:
DO seal custom attribute classes, if possible. This makes the look-up for the attribute faster.
I didn't see anything about security in that section, but #Teoman Soygul makes a good point. So I'd agree with Mr. Troelsen.
I'm developing a serialization class that uses attributes on custom classes to decorate whether a property is a fixed length format or a delimited format. These two attributes should be mutually exclusive, meaning that the developer can either specify [FixedLength] or [Delimited] (with appropriate constructors) on a property, but not both. In order to reduce complexity and increase cleanliness, I don't want to combine the attributes and set a flag based on the format type, e.g. [Formatted(Formatter=Formatting.Delimited)]. Is it possible to restrict these attributes to be mutually exclusive to one another at design time? I'm aware how I can check for this scenerio at run-time.
You cannot do this in .NET. At most you can allow a single instance of the same attribute on a class, like in this example:
using System;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
class BaseAttribute : Attribute {
}
[Base]
[Base] // compiler error here
class DoubleBase {
}
But this behavior cannot be extended to derived classes, i.e. if you do this it compiles:
using System;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
class BaseAttribute : Attribute {
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
class Derived1Attribute : BaseAttribute {
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
class Derived2Attribute : BaseAttribute {
}
[Derived1]
[Derived2] // this one is ok
class DoubleDerived {
}
The best I can think of is that you could write something to check that there are no types with both attributes applied and use the check as a post-build step.