I have a question regarding using Spring Security to protect against SQL injection. First of all, I know that use prepared statement can protect from any SQL injection. But In my project I want to show that use Spring Security could help to protect or mitigate against this kind of attack. what i did so far, i made connection using JDBC & Spring and I applied Spring Security and every thing is fine. My question is in my project i used two ways to protect against SQL injection. The first one is Santizing user input and the second one is using Spring Security. I could pass malicious input through Sanitizaing and I want to show that the role of spring security. for example, I pass this input:
TV' UNION SELECT credit_no From credit;--
In this case how I can tell Spring security that it doesnot give any users the credit number. By the way, I used method security level. Just I want to give me an easy way to analyze the user input to see If it has access to data which he asked such as credit.
I hope that clear
Well, your question is not 100% clear, and it may vary on your architecture, but pre post annotations can work well to grab user input.
You can create your own permission evaluator and check permission for pre authorization in your methods.
#PostFilter("hasPermission(filterObject, 'customoperation')")
public CreditCard getCreditCard(String userInput) {
//
}
and your hasPermission method (that you've read about in the link above) goes something like:
public boolean hasPermission(Authentication authentication,
Object target, Object permission) {
if ("customoperation".equals(permission)) {
//your logic here, returning true or false, filtering the object
}
return false;
}
You can also extend the expression handler to use custom functions. Check this answer.
Related
Here's my question: I'm writing a platform which I will be giving to the customers to implement their projects with. So in my platform I have created a SessionService in which I have methods like getCurrentSession, getAttribute, setAttribute, etc. Before spring-session my getCurrentMethod looked like this:
#Override
public HttpSession getCurrentSession() {
if (this.session == null) {
final ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
return attr.getRequest().getSession(true); // true == allow create
}
return this.session;
}
which worked perfectly fine, although it looks ugly and have no backing like redis. Now I want to migrate to spring-session and I was hoping to use the SessionRepository to find the current session of the user, however I can only see a getSession(String id) in there. I believe the id is stored in the cookie, so to use it I will probably have to pass the HttpServletRequest object from my controllers, to my facades, to the service layer which is very near the db layer. This looks like a very bad idea to me, so my question would be: is there any way to get the currentSession near the db layer? One way I would think is to write an interceptor that will be invoked the controllers, which will set the current session in the repository, or the service maybe? I'm just not sure this is the right way to go.
Obtaining the Session Id from Service Layer
You can use the RequestContextHolder to retrieve the session id, set attributes, and remove attributes.
The RequestContextHolder is typically setup using RequestContextListener or RequestContextFilter. Spring Session does NOT work with RequestContextListener because there is no way for Spring Session to wrap the request before the RequestContextListener is invoked.
Unfortunately, this means for Spring Boot applications, RequestContextHolder does not work out of the box. To work around it you can create a RequestContextFilter Bean. See spring-boot/gh-2637 for updates on this issue.
Should I be putting this in session?
Just because it is easy to put a lot of objects in session and it is stored in Redis does not mean it is the right thing to do.
Keep in mind that the entire session is retrieved on every request. So while Redis is fast, this can have a significant impact if there are lots of objects in session. Obviously the implementation can be optimized for your situation, but I think the concept of session generally holds this property.
A general rule of thumb is, "Do I need this object for over 95% of my requests?" (read this as almost all of my requests). If so, it may be a candidate for session. In most cases, the object should be security related if it fits this criteria.
Should I access session id from ThreadLocal in the service layer?
This is certainly open for debate as code is as much of an art as it is a science.
However, I'd argue that you should not be obtaining the session id from thread locale variables throughout your architecture. Doing this feels a bit like obtaining a "Person id" and obtaining the current "Person id" from the HttpServletRequest in a ThreadLocale. Instead, values should be obtained from the controller and passed into your service layer.
Your code does not need changing. It will return the Spring Session session object.
Though it is generally better to inject the HttpSession from the controller, or use session-scoped beans and #SessionAttribute than to have such a session service in the first place.
I am working with Spring Websocket (4.1.4 release) and using #SendToUser for sending messages to the current user. But I've a problem. Ours is a multi-tenant platform where username is not unique, instead a combination of username and tenant id is unique. The DefaultUserSessionRegistry keeps a map from username to a list of session ids:
private final ConcurrentMap<String, Set<String>> userSessionIds = new ConcurrentHashMap<String, Set<String>>();
which would not work in my scenario. So is there a way I can plugin my custom UserSessionRegistry implementation?
After a code search, the issue seems related to this line.
I found that this class is extended by WebSocketMessageBrokerConfigurationSupport, which is extended by a #Configuration class (DelegatingWebSocketMessageBrokerConfiguration), so you could try to extend it by yourself, like in this example:
https://github.com/arawn/overview-of-spring4/blob/master/src/main/java/jco/conference/oxquiz/WebSocketConfig.java
I had no time to verify this, but if your problem is only the UserSessionRegistry implementation, this could be the way of overriding that #Bean method.
Update:
After digging a bit more, I found the real entry point to the whole flow: search for the DefaultHandshakeHandler class, having the determineUser method (I cannot add more links because of my low score)
I am authenticating using LDAP, and everything works fine for users within a specific domain. But I'm having difficulty understanding how I can authenticate users that are under a second domain. My current configuration shown below specifies the first domain in the user-search-base. I removed that parameter, in hopes that it would search all domains, but that didn't work. I also tried specifying the domain as part of the user name when prompted, such as domain\user, but this didn't work either.
<security:authentication-manager alias="authenticationManager">
<security:ldap-authentication-provider
user-search-filter="(samaccountname={0})"
user-search-base="dc=domain,dc=company,dc=com"
user-context-mapper-ref="userContextMapper" >
</security:ldap-authentication-provider>
</security:authentication-manager>
<security:ldap-server
url="ldap://some.url.com:3000"
manager-dn="CN=USER1,OU=FacMgr,OU=FAC,OU=Exchange,dc=domain,dc=company,dc=com"
manager-password="xxxx"/>
Will I need to create a custom search, and if so, can someone provide an example in this context?
It appears as though you're using Active Directory, in which case I wonder why you're not using the more basic ActiveDirectoryLdapAuthenticationProvider class.
At any rate, you should be able to accomplish what you need by extending either LdapAuthenticationProvider or ActiveDirectoryLdapAuthenticationProvider, and passing the appropriate domain to the superclass' method.
Create a constructor which accepts two different LdapAuthenticator objects, and add a second 'try' statement in the doAuthentication method's catch (UsernameNotFoundException notFound) statement (after the check against bad credentials). Use whatever approach you like to get the getAuthenticator method to try the second authenticator if the first one fails.
This approach should work, but if both domains have a username of jsmith, but the user in question resides on the second, you may encounter problems -- that is, this is not a particularly good solution, but it is a solution.
To build this all up properly, use a custom authentication filter (extend the UsernamePasswordAuthenticationFilter), and have the LdapAuthenticationProvider.getAuthenticator() method identify the domain from the value passed by the filter (in your custom login form).
You may need different manager accounts, but this is hopefully enough for you to go on.
The trick to making this work is to use ActiveDirectoryLdapAuthenticationProvider. To do this, just make the following changes:
In resources.groovy:
// Domain 1
ldapAuthProvider1(ActiveDirectoryLdapAuthenticationProvider,
"mydomain.com",
"ldap://mydomain.com/"
)
// Domain 2
ldapAuthProvider2(ActiveDirectoryLdapAuthenticationProvider,
"mydomain2.com",
"ldap://mydomain2.com/"
)
In Config.groovy:
grails.plugin.springsecurity.providerNames = ['ldapAuthProvider1', 'ldapAuthProvider2']
This is all the code you need. You can pretty much remove all other grails.plugin.springsecurity.ldap.* settings in Config.groovy as they don't apply to this AD setup.
Documentation:
http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ldap-active-directory
in our new software project, we have the following requirement: A webpage shall show a set of data. This data shall be editable by some users (assigned to roles, i.e. manager), and only viewable by others. The tricky part is described by an example:
A User-page consists of address data and account information. The addess data shall be editable by the user and the manager and viewable by all users, while account information shall only be viewable by the actual user and the manager.
I have read a lot of information about SpringSecurity. It provides a very good framework to gran permissions on urls and methods and even domain classes. But what I need is field level ACLs. At least, that's what I think at the moment.
So, the question is: How to solve this problem using Grails?
Thanks a lot in advance,
Regards Daniel
Spring Security (Acegi Plugin) is definitely the way to go with Grails.
There is a taglib you can use that will allow a page to be different for different roles such as the following:
<g:ifUserHasRole roles="ROLE_ADMIN">
html code for extra fields
</g:ifUserHasRole>
Me, I'd encode it on the domain class, emulating the way GORM has you annotate the domain classes (static access = [field1: "ROLE_USER", field2: "ROLE_ADMIN,ROLE_USER"] as an example). Then build a method your controller could use to redact them for a given user. That method could use the domain class's annotations to decide how to redact it. Then, metaprogram it onto each of the domain classes the way plugins do.
Similarly, write the opposite method to restrict data bindings of params into the domain class, write your own data binding utility method, then metaprogram it onto each domain class as well.
Then you can just use instance.redact(user) or instance.bindData(params, user) to do what you want, and it's practically declarative syntax.
We have a similar situation and use both the ifUserHasRole tag in the gsp to drive the appropriate presentation and the we have a filter that enforces the rules based on the action being called. For example, on user controller we would only allow the management roles to call save action, or if the user.id is the same as the session.user.id. This seemed to be the best option for our situation.
What about creating an ACL class like this:
class ACL(val entry: Entry*) {
def isAccessAllowed(subject: String, permission: String): Boolean = ...
}
class Entry(val subject: String, val permission: String*)
usage:
new ACL(
new Entry("dave", "read", "write"),
new Entry("linda", "read")
)
(This example is in Scala, because I found it more expressive in this case, but it should be easy to transfer it to Groovy.)
You would then connect an ACL object with the object to be protected.
Does anybody have any links or advice on how to hook up validation that requires interacting with the database before updating or adding to the database? Every example I see shows how to validate properties e.g. "Is Required", "Is Email", "Is Numeric", etc, but how do you hook up validation for "Can't order out of stock item"? This xVal blog post touches on it but doesn't provide an example.
I've been following the NerdDinner tutorial which uses a Repository, but this is the bit I don't quite get... Say we had an OrderController with a Create method, and before creating an order we had to first check that the item is in stock. In the NerdDinner style the Controller uses the Repository to talk to the database, so how would our Order object (Model) be able to enforce this validation along with the property validation, as it can't talk to the database?
Thanks for any help
In the NerdDinner tutorial, you can checkout the IsVaild and then the GetRuleViolation methods. Based on your business and database rules, you could use these to check the data you have before you insert it. You could even create an IsValidForInsert Method to check any insert specific rules you need to enforce.
In NerdDinner, the GetRuleViolation allows you to retrieve the violated rules and bubble them up to the interface as you choose.
public bool IsValid
{
get { return (GetRuleViolations().Count() == 0); }
}
public IEnumerable<RuleViolation> GetRuleViolations()
{
if (CheckDbForViolation)
yield return new RuleViolation("Database Violation", "SomeField");
if (String.IsNullOrEmpty(Title))
yield return new RuleViolation("Title is required", "Title");
if (String.IsNullOrEmpty(Description))
yield return new RuleViolation("Description is required", "Description");
if (String.IsNullOrEmpty(HostedBy))
yield return new RuleViolation("HostedBy is required", "HostedBy");
... etc ...
yield break;
}
public bool CheckDbForViolation()
{
/// Do your database work here...
}
You could take this further and split database code into the repository. The CheckDbForViolation would call the repo for the info and then determine if there was a violation or not. In fact if you are using a repository, I think that would be the preferable way of doing it.
You do not really need any guidance from examples on how to do this. Ultimately you will have to be able to create such applications on your own which means being creative.
I've decided from the beginning do not use either built-in validation or membership API in order not to run into its limitations at some point of time.
For your situation: it's pretty much standard.
Imagine the execution flow as follows:
Post form
Validate input data format without talking to the database
If (2) is pass, then you validate the input from the point of business rules/data integrity. Here you talk to the database
If (3) passed then perform your operation whatever it is. If it somehow fails (maybe data integrity rules in the database prohibit the operation, say, you deleted a related object from the other browser window) then cancel it and notify the user of an operation error.
Try to keep controller methods as empty as possible. The validation and operation logic should reside in your models and business logic. The controller should basically attempt the one intended operation and based on the status returned just return one view or the other. Maybe a few more options, but not the whole load of checks for user roles, access rights, calling some web services etc. Keep it simple.
P.S. I sometimes get the impression that the built-in features intended to simplify simple things for majority of developers tend to create new barriers over the removed ones.
I would create an OrderService with a method PlaceOrder(Order order). The OrderService use the Repository to perform CRUD ops and to enforce business rules (stock check) and eventually thrown exception on rules violation you can catch and report to the user.