spring security : Why can't we access Hibernate entitiy parameters in #PreAuthorize? - spring

I have the following interface method on which I am applying #PreAuthorize :
#PreAuthorize("doSomething(#user.id)")
void something(User user, List<User> accessList);
where User is a Hibernate entity object. It gives me an error :
org.springframework.expression.spel.SpelEvaluationException:
EL1007E:(pos 13): Field or property 'id' cannot be found on null at
org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:204)
There is no way that the user parameter is null, as if I remove the annotation, and inspect the value of user in the method that implements this interface method, there is a valid User object present there. Additionally, just before calling this method, I have made sure that the user object is correctly constructed.
I really can't figure out why would the user field be considered null by the SPEL parser

You can check with the debugger what's going on in MethodSecurityEvaluationContext, inside Object lookupVariable(String name) method:
#Override
public Object lookupVariable(String name) {
Object variable = super.lookupVariable(name);
if (variable != null) {
return variable;
}
if (!argumentsAdded) {
addArgumentsAsVariables();
argumentsAdded = true;
}
and so you can see what's really going on in the addArgumentsAsVariables() method as the convertion of method arguments to SPEL variables is implemented very clearly in Spring.

Spring Security has a better answer for this problem now:
http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#access-control-using-preauthorize-and-postauthorize
Basically, you can use the #P annotation or #Param annotation if you are using < JDK 8.

You can check LazyParamAwareEvaluationContext,inside loadArgsAsVariables() method, version 3.1.0.
The same key for different Entity, because of implementing interface.

I need to add something to this as the title indicates that we cannot access hibernate properties.
There are two editions of hasPermission, the loaded object and the serialized object. Here is some code from a test case:
#PreAuthorize("isAuthenticated() and hasPermission(#organization, 'edit')")
public long protectedMethod(Organization organization)
{
return organization.getId();
}
And for the latter here we see that we can infact access the id proprty of the organization (which is a hibernate entity):
#PreAuthorize("isAuthenticated() and hasPermission(#organization.getId(), 'organization', 'edit')")
public long protectedMethodSerializableEdtion(Organization organization)
{
return organization.getId();
}

Related

Session based validation in ServiceStack

I have some validation logic, which is based a user's session.
Сan I access the session from a class inherited from AbstractValidator?
Or is there another way to check RequestDTO based session?
For example I can use filters for that (and I can access the session via IRequest parameter req in overrided Execute method), but I don't know how to return the response from the class of the filter, bypassing the main method of the operation. If I will throw the Exception, the service will not work properly because RequestDTO declared outside of my project and it is not inherited from IReturn<> and does not contain a ResponseStatus field.
Thanks in advance for any help (and sorry for my English)
If your validator implements IRequiresRequest then it will injected with the current IRequest which you can use in your lambda expressions, e.g:
public class CustomValidator : AbstractValidator<Request>, IRequiresRequest
{
public IRequest Request { get; set; }
...
}

Obtaining handle to Collection/Array object in #PreFilter and #PostFilter in Spring Security

In Spring Security, #PreFilter and #PostFilter can be used to trim/prune the argument/return object and filterObject references each element in the object and is used to loop through the argument/return Collection/Array.
However, I need to get a handle to the actual Collection/Array as a whole and not specific elements in the context. Is there any way to do this?
The reason is that I am creating an externalized authorization service that is used by Spring Security to query and prune the collection/array and this service supports querying for multiple answers in a single question. Once I get a reference to the object as a whole, I can iterate though the elements myself to create this request to the externalized service.
Can this be done in Spring Security? I am implementing this as an custom express handler.
Assuming the return value is modifiable, you can use #PostAuthorize. For example:
#PostAuthorize("#mySecurityFilter.filter(authentication, returnObject)")
List<String> findAllMessages();
This assumes you created a Bean by the name of "mySecurityFilter" that looks something like this:
#Component
public class MySecurityFilter {
public boolean filter(Authentication authentication, List<String> domain) {
// submit to service and get back all allowed values
List<String> allowed = Arrays.asList("Hello");
Iterator<String> iValues = domain.iterator();
while(iValues.hasNext()) {
String value = iValues.next();
if(!allowed.contains(value)) {
iValues.remove();
}
}
return true;
}
}

Spring Ldaptemplate 2 add member to group

what is best way to add member in group using spring LdapTemplate.
I have successfully create user and remove user ex.
But I'm trying to add member then I'm facing issue.
Add Member Code:
public boolean addMemberToGroup(List<String> groupList, User user) {
boolean isAddedSuccessfully=false;
try{
for(int i=0;i<groupList.size();i++){
Name groupDn = buildGroupDn(groupList.get(i));
DirContextOperations ctx = ldapTemplate.lookupContext(groupDn);
ctx.addAttributeValue("member",buildPersonDn(user.getUid()));
ldapTemplate.update(ctx);
}
isAddedSuccessfully=true;
}
catch(Exception e){
isAddedSuccessfully=false;
}
return isAddedSuccessfully;
}
private Name buildGroupDn(String groupName) {
return LdapNameBuilder.newInstance("cn=groups").add("cn", groupName).build();
}
private Name buildPersonDn(String userID) {
return LdapNameBuilder.newInstance()
.add("uid", userID).add("cn", "users")
.build();
}
Exception Of addMemberToGroup: Class class org.springframework.ldap.core.DirContextAdapter must have a class level interface org.springframework.ldap.odm.annotations.Entry annotation.
please let me know what i am missing.
The updatemethod is intended for use with ODM annotated classes. When working with DirContextAdapter you should use the modifyAttributes method.
Though this is an old question, it's one I had too recently. For anyone coming here in the future, this question is similar to the one found at Spring Malformed 'member' attribute value. Putting together info from both questions, I found the solution to my problem, and share here what worked for me.
In addition to using the modifyAttributes method of the LdapTemplate class, it's also important to pass a String object as the second parameter of the addAttributeValue method of the DirContextOperations class when adding a member, rather than passing a Name object. The toString method called on the corresponding Name object does the trick.
Original code:
DirContextOperations ctx = ldapTemplate.lookupContext(groupDn);
ctx.addAttributeValue("member",buildPersonDn(user.getUid()));
ldapTemplate.update(ctx);
Try this instead:
DirContextOperations ctx = ldapTemplate.lookupContext(groupDn);
ctx.addAttributeValue("member",buildPersonDn(user.getUid()).toString());
ldapTemplate.modifyAttributes(ctx);

spring security - How can I modify the return object of #PostAuthorize in a custom SPEL method?

I wish to filter a collection returned by a service method. This filtering would involve calling another service method and hence I am not going for #PostFilter as it calls the SPEL expression inside the annotation for each element of the collection. Instead, I am using #PostAuthorize as follows :
#PostAuthorize("canAssignToUser(returnObject)")
List<UserInfo> getUsers(int userId);
In the canAssignToUser, I am trying to remove users from the return list passed to it. Apparently, this is a problem, and there is some restriction on modifying the returned list. How can I modify the returned list from a method using method-level annotations and without the SPEL expression being called for each element of the list.
The #PostAuthorize is used for evaluating a boolean value, so the interceptor does not pass the return value to the expression, (look here).
What's your method of removing the elements without checking every element? (like the #PostFilter does)
I think you don't have a choice, if you want to use Spring Security for the filtering
You can modify the returned object as you like. Even though the interceptor does not return the object you passed, it gets notified with the changes to the object. Eventually the returnedObject is modified. (Note: custom security method inside #PostAuthorize can only return boolean.)
public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
public CustomMethodSecurityExpressionRoot(Authentication authentication) {
super(authentication);
}
public boolean canAssignToUser(Object returnObject) {
// do modifications to returnObject
return true;
}
getUsers() method returns the modified list after evaluating#PostAuthorize("canAssignToUser(returnObject)") .

databinding,validate,exception in spring mvc3

I am using the spring mvc3,and I found that I am confused with the some concepts,so I make a summary, and post it here.
Data binding.
I use struct2 before where if I have a bean in the action(i..e,named 'Person'),then when the following url is requested:
http://localhost:8080/app/form?person.id=1&person.name=xxx&pet.name=yy
Then a new instance of Person will be created and the parameters '1' and 'xxx' will be populated to this instance.
And a new instance of Pet will be created,and the name 'yy' will be populated to this bean.
This is the only way for data binding in struct2:
You specify the beanname.property in your request.
Now in spring mvc3,I know one way to binding the data:
http://localhost:8080/app/form?id=1&name=xxx&other=yy
#RequestMapping('form')
public String form(Person person,BindingResult result){
//now I get the person
}
Even it work,but I have some questions:
1) I have three parameters in the request url "name",'pass','other',how does spring know which parameters should be populated to my bean(model).
2) how about if I want to bind parameters to more than one model like the example in struct2(both person and pet)?
Furthermore,what does the modelAttribute and commandName attribute in the spring tag "form" mean?
2. Validate
For bean(ignore the getter and setter in the example):
import javax.validation.constraints.NotNull;
public class Bean {
#NotNull(message="id can not be null")
private int id;
}
I use this controller:
#RequestMapping("val")
public #ResponseBody
String validate(#Valid Bean bean, BindingResult result) {
if (result.hasErrors()) {
return result.getAllErrors() + "";
} else
return "no error";
}
I found that only the 'NotEmpty' works.
Since if I use this url:
/val?name=xxx ==> no error !! // id is null now,why it does not has error?
3. The type conversion.
Take this url for example:
http://localhost:8080/app/form?id=1&name=xxx&other=yy
Obviously it will throw 'NumberFormatException' if I set the id to string value.
Then where to catch this exception? If in the controller,then I have to write so many try-catch block in each controller.
Furthermore,the the type conversion exception do not limited to only 'NumberFormatException',it may be 'dataformaterrorexception' and etc.
But they all belongs to the type conversion,how to handle the using a common solution?

Resources