I have several methods for a restful webservice with this signature
public #ResponseBody SomeObject someMethodSignature(Principal principal){
given that it's legacy code, is there a way to get other information from principal (Principal is an interface from java.security with only one useful method getName()) other than the name without the need to pass anything else to the method as parameter? Like permissions and stuff like that?
thanks
If you are using Spring Security as you say, then the Principal object should be an instance of Spring Security's Authentication interface. See the API Javadoc.
This means you can cast the principal and invoke the getAuthorities method on it, like so
((Authentication)principal).getAuthorities();
Note that other security-related methods of HttpServletRequest are also overridden, so you could also change your method to take a request object and invoke, for example the isUserInRole method if that would suit your requirements. This would avoid you having to add any dependency on Spring Security in your classes.
The Principal only carries the name (usualy the login returned by the Authentication infrastructure) there isn't much more info to get. However, you check the JAAS reference you will see that there are other classes that carry info like the AuthPermission that is used to hold names that identify stuff your Principal is authorized to use and, therefore, we use this to activate (typically) menu options.
The interface Principal doesn't contain many information, but implementations may. As in Tomcat and Weblogic, you can find some more interesting information.
Related
I have been reading a lot online/offline about where to put validation and business rules in general for domain driven design. What I could not understand is how can an entity provides methods that does validation and business rules without resorting to static methods or having a service? This is especially important for cases where the domain object does not need to be instantiate yet, but we need to validate a value that will eventually used to set the object's attribute.
I noticed blog postings such as http://lostechies.com/jimmybogard/2007/10/24/entity-validation-with-visitors-and-extension-methods/ relies on .NET's specific extension method, which is not available in programming languages such as Java. I personally don't like static methods are they cannot be overridden and hard to test.
Is there anyway I could do this without static methods or having to instantiate an unnecessary domain object just to use its validation and business rules methods. If not, does that mean domain driven design is very dependent on static methods?
Thanks
Use ValueObjects Not Entity.
In the registration case, a UserName value object could be introduced. Create a Username object when receiving the registration. Implement validation in the constructor of the UserName.
See this question and this presentation for more detail.
Edit1:
1.How to handle cases where different validation rules applied for different context. For example: The username must not have numbers for certain type of members, but it is required for other types of members?
Maybe different factory methods could do that. like UserName.forGoldenCardMember(...) or UserName.forPlainMember(...). Or make MemberType (a hierachy maybe) to validate UserName.
Another alternative solution is use AggregateFactory(AccountFactory in this case).
2.Is constructor the only place to put the validation code? I did read online about two points of view: an object must always be valid vs. not always. Both present good arguments, but any other approach?
I prefer valid approach personally. Passing an maybe invalid value object harms encapsulabilty.
Edit2:
Require
a) validation business rule based on context(different username rules for member types)
b) keep validating all business rules even if one of them fail
Stick with Single responsibility principle by using Value Object(MemberType this case).
AggregateFactory could be introduced to ease the application layer(coarser granularity).
class AccoutFactory {
Account registerWith(Username username, MemberType type, ....) {
List<String> errors = new ArrayList<String>();
errors.addAll(type.listErrorsWith(username));
errors.add(//other error report...
if (CollectionUtils.isEmpty(errors)) {
return new Account(username,....);
} else {
throw new CannotRegisterAccountException(errors);
}
}
}
Edit3:
For questions in the comments
a) Shouldn't the Username object be the one that has a method that returns the error like
the listErrorsWith()? After all, it is the username that has different rules for different member type?
We could check this question from another perspective: MemberTypes have different rules for username. This may replace if/else block in the Username.listErrosWith(String, MemeberType) with polymorphism;
b) If we have the method in the MemberType, the knowledge will not be encapsulated in the Username.Also, we are talking about making sure Username is always valid.
We could define the validity of Username without MemberType rules. Let’s say "hippoom#stackoverflow.com" is a valid username, it is a good candidate for GoldenCard member but not good for SilverCard member.
c) I still can't see how performing validation that returns a list of errors without getting the list from exception thrown by the constructor or static method. Both does not look ideal IMHO.
Yes, the signature of listErrorsWith():List looks weired, I'd rather use validate(username) with no returning value(throw exception when fails). But this will force the cilent to catch every validation step to run validations all at once.
If you decided to use DDD in your application you need to build more complex solution. I agree with #Hippoom, you shouldn't use Entity for this purpose.
I would suggest this solution:
DTO -> Service Layer (ValidationService -> Converter) -> Persistence Layer (Repository)
Some explanation:
When you received DTO from client side with all necessary parameters, you should validate it in you service layer (e.g. Use another service like ValidationService) which can throw exception if something wrong. If all Ok, you can create Entity from your DTO in Converter and persist it in Repository.
If you want flexible solution for ValidationService I'd suggest Drools
Does Spring Security Acl support class-level permissions? For example, let's suppose I have an Asset class, and I want to allow read permissions to all instances of the Asset class to any user with role ROLE_USER. As long as I could see, ObjectIdentityImpl only accepts object instances.
Thanks
The Spring Security ACL is not really handy for this. I would suggest you use a pre-authorize annotation instead:
#PreAuthorize("hasRole('ROLE_USER')")
public List<Asset> getAllAssets();
Make sure you have pre- and post-annotations enabled in your configuration.
The org.springframework.security.acls.model.ObjectIdentity is one of the core Spring Security ACL interfaces representing the identity of an individual domain object to secure. It imposes type and identifier properties. If you need class level permissions, you can use e.g. "Class" as a type and actual class name as an identifier (e.g. "Asset" or "my.package.Asset").
Depending on a concrete scenario, it may be also needed to implement org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy and org.springframework.security.acls.model.ObjectIdentityGenerator interfaces accordingly.
There's a lot of documentation on how to use jsp tags, aop, annotations, the application context, and all of these sorts of things... but how do I access the access control methods directly? What class do I need to create, if any? Is there hidden bean I need to be aware of? It doesn't seem like SecurityContextHolder is the right place to look.
What I'd like to do is something like this:
if(springSecurityObject.isAuthorized("hasAnyRole('DIRECTOR', 'ADMIN')")) {
// ... do something
}
Or even better:
if(springSecurityObject.hasAnyRole('DIRECTOR', 'ADMIN')) {
// ... do something
}
Thanks!
EDIT: It seems like the spring security people are using the granted authorities on the user object itself:
https://fisheye.springsource.org/browse/spring-security/taglibs/src/main/java/org/springframework/security/taglibs/authz/AbstractAuthorizeTag.java?r=fc399af136492c6c37cdddca6d44e5fe57f69680
I think it would probably have been helpful if they abstracted out a ton of this code and put it into a nice set of classes instead - something that both the tag libraries and actual users could use. They are private helper methods after all... a common smell that they should probably exist in some classes instead.
Since they are doing the plumbing manually, I guess I have to assume that what I want doesn't exist.
The only thing I can think of is invoking your UserDetailsService manually, calling getAuthorities() on the returned Authentication and then calling contains() or containsAll() on the returned collection.
So you'd have something like:
final UserDetails jimmyDetails = myDetailsService.loadUserByUsername("Jimmy");
final Collection<GrantedAuthority> jimmyAuthorities = jimmyDetails.getAuthorities();
// make it a Collection<String> by iterating and calling .getAuthority()
plainAuthorities.contains("ROLE_YOU_NEED_TO_CHECK_FOR");
Writing your own helper methods that do this would not be too hard, although I agree that having them in the API would be nice.
Does one can recommend me how to get list of aspects in alfresco using java web-service API.
Thank you.
It is not possible to get the list of aspects using web service client, you can however get the list of class definitions of aspects if you know their names.
Check DictionaryServiceSoapPort interface, there is a method named getClasses that can return an array of ClassDefinitions for the given types and aspects.
I don't know if it helps but instead of retrieving the list of aspects using web service, you can as well get the list of all types by calling Get Class Definitions web script. The url pattern is as follows.
http://localhost:8086/alfresco/service/api/classes/{className}
You can call the same web script without className, this time it will output all the classes in the dictionary as JSON, both the types and aspects (aspects are marked with "isAspect"=true).
This may be late for you, but you can use the DictionaryService (in case somebody else searches for this:
Alfresco Wiki says:
getClasses Get a list of type and
aspect definitions from the
dictionary.
ClassDefinition[]
getClasses(ClassPredicate types,
ClassPredicate aspects)
Parameters:
types - the predicate for controlling
the types returned, or null to return
all types aspects - the predicate for
controlling the aspects returned, or
null to return all aspects Return:
a list of class definitions that
relate to the requested types.
I have the following situation: my application's authorization mechanism is implemented using Spring security. The central class implements AccessDecisionManager and uses voters (each of which implements AccessDecisionVoter) to decide whether to grant access to some method or not. The algorithm that tallies the votes is custom:
public class PermissionManagerImpl extends AbstractAccessDecisionManager {
public void decide(
Authentication authentication,
Object object,
ConfigAttributeDefinition config) throws AccessDeniedException {
Iterator<?> iter = getDecisionVoters().iterator();
boolean wasDenied = false;
while (iter.hasNext()) {
AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
int result = voter.vote(authentication, object, config);
switch (result) {
// Some tallying calculations
}
}
if (wasDenied) {
throw new AccessDeniedException("Access is denied");
}
}
}
Upon denying an access to some method, the client of the application is interested in obtaining an informative exception that specifies exactly why the access is denied. This implies passing some information from voters to the decision manager. Unfortunately, the only information the standard AccessDecisionVoter passes back to the decision manager is one of the possible return values (ACCESS_GRANTED, ACCESS_ABSTAIN or ACCESS_DENIED).
What is the best way to do it?
Thanks.
Well, the AccesssDecisionVoter interface actually returns an int in this situation. Granted, the built-in voter implementations always only return one of the three constants you mentioned (and these are what the standard access decision managers check for), but then they don't really have anything extra to return - the RoleVoter for instance will deny access if and only if the principal doesn't have the required role.
Since you're using your own implementations both of the voters and the access decision manager, you have several options available as I see it:
Return other values of integers as some form of error code; treat ACCESS_GRANTED, ACCESS_ABSTAIN and ACCESS_DENIED as their typical values, but treat any other integer as "access denied" with an error code. Ideally have a lookup table of error codes available - essentially a poor man's enum.
Within your voter, return ACCESS_DENIED as usual, and set some publically accessible property (either on the voter object itself or perhaps some statically-accessible field) with the error reason. In your manager, if you get access denied from your custom voter, check the property to get the details.
As above, set an error property within the voter; but ensure that the instance of Authentication being passed in is one of your own custom subclasses that provides a good
location to set/retrieve this information.
Throw an AccessDeniedException (or suitable subclass) from within your voter itself. This is not ideal as it presupposes the logic in the access decision manager; but you could either let this bubble straight up, or if needed catch it within the manager (a custom subclass would definitely be good for this) and rethrow if access really is denied (something similar to what the ProviderManager class does with its lastException variable).
None of these sticks out as the obviously correct and elegant answer, but you should be able to get something workable from whichever one is most appropriate. Since there is no explicit support within the voter framework for communicating reasons (it's a straight boolean response fundamentally) I don't think you can do much better.
Thanks for people who answered.
I think I have found a quite elegant way to do what I wanted and still use the standard voters API. The 2nd parameter to the vote method of AccessDecisionVoter is the secured object. I can create a contract between the decision manager and the voters, that this object is of a specific class/interface that is a wrapper, through which the original secured object can be fetched and also additional information can be added by the voters that deny the access.
I saw a pattern like this in other frameworks as well. This solution has the following advantages over other possible solutions:
The voters can remain stateless, so they can be singletons
The standard interface of the AccessDecisionVoter is used and no new return values are added
The additional information is saved in an object that is discarded automatically because no one uses it after the AbstactDecisionManager's decide method, so no cleanup code is required
Cheers.
Can't you implement AccessDecisionManager directly, without using the voters? You can then throw an AccessDeniedException with the correct information. Maybe RoleVoters are not the right abstraction to use in your case.