I'm some what lost as to why spring isn't enforcing the #Secured("ROLE_USER") on my service interface. My controllers are established using annotations.
An example of my service Interface
public interface MyServiceManager {
#Secured("ROLE_USER")
public void delete(int cid);
#RolesAllowed({"ROLE_USER"})
public Contact getContact(int contactId);
}
my security-context:
<global-method-security secured-annotations="enabled" jsr250-annotations="enabled">
</global-method-security>
<http auto-config="true" >
<intercept-url pattern="/secure/**" access="ROLE_SUPERVISOR" />
<intercept-url pattern="/addcontact**" access="IS_AUTHENTICATED_REMEMBERED" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<concurrent-session-control max-sessions="1"
exception-if-maximum-exceeded="true"/>
<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1"/>
<logout logout-success-url="/welcome.do" logout-url="/logout"/>
</http>
<authentication-provider>
<password-encoder hash="md5"/>
<user-service>
<user name="rod" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
</user-service>
</authentication-provider>
Do you have the statement
<global-method-security secured-annotations="enabled" jsr250-annotations="enabled" />
in the same configuration file as the one you defined the MyServiceManager bean? I had the same problem until I turned on debug for org.springframework, and noticed that spring security was only applied on the same file as the ones where global-method-security was defined in.
In my case, the exact location of this statement:
<global-method-security secured-annotations="enabled" >
proved to be very important. Make sure that you put it after you declare which classes should be scanned and used as controllers.
<context:component-scan base-package="com.test.controller" />
This is the way to make sure that the #Secured annotations will also get into the game
After doing more research on this problem I came to the following conclusion/solution. I'm not sure if it's 100% correct..but it works.
I put all of my configuration in the dispatcher-servlet.xml file. So instead of having a disptacher-servlet.xml and application-context.xml. The dispatcher-servlet.xml is loaded by the application (contextConfigLocation). Within the dispatcher-servlet.xml I import my security-context.xml and datasource-context.xml. Afer that, everything works.
I had this same problem. Using the information from Kent Lai's reply here, I was able to fix it.
I put the <global-method-security> element in my app-servlet.xml but kept the security definitions separate in security.xml, where web.xml has contextConfigLocation for app-servlet.xml and security.xml.
Works like a charm now!
Try putting the annotations on the implementation class instead of the interface and see if that works. I ended up doing that on a recent project because I was also using the #Transactional attribute on my service layer, and the Spring docs recommend putting those on the class and not the interface. I don't know if the same issue might apply to #Secured, but I wanted to keep the annotations in the same place. See the Spring Docs
Regarding Kent Lai's answer...that is a good idea...make sure that your security config file is actually being included by Spring.
Did you use something like this in your web.xml
<servlet>
<servlet-name>name</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/webmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
I'm not sure why, but if I use the DispatcherServlet I was not able to enforce Security annotations
I had this same problem.
After I added:
<context:annotation-config />
in my spring-security.xml file it disappeared.
Hope this will help someone :)
Related
I am facing this problem...
I have the spring security filter
on my web.xml
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I am using spring security and I have this at my springSecurity-applicationContext.xml
<http
authentication-manager-ref="myAuthManager"
access-decision-manager-ref="accessDecisionManager"
entry-point-ref="authenticationEntryPoint"
create-session="ifRequired"
access-denied-page="/unauthorized">
<custom-filter ref="myPreAuthenticatedFilter" position="PRE_AUTH_FILTER"/>
<logout logout-success-url="/page/home"/>
<anonymous key="anonymous"/>
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/method/do" access="IS_AUTHENTICATED_ANONYMOUSLY()"/>
</http>
So, at myPreAuthenticationFilter I have a filter that extends of AbstractPreAuthenticatedProcessingFilter
I am trying to execute /method/do with a DELETE or a POST without success.
I am wondering what would be the best way to do it?
For some reason when I put a break point on myPreAuthenticationFilter at doFilter and make the request with DELETE nothing happens, only when I do the GET.
I want that endpoint to have no security.
I made this and worked
<http pattern="/method/do" security="none"/>
Not sure why this works and others dont or where I should look for.
Any idea?
The errors I get are Forbidden
If using spring-security 4 or above, csrf filter is enabled by default and it actually blocks any POST, PUT or DELETE requests which do not include de csrf token.
If you are not sending the csrf token in any of this kind of requests, you should make a test just disabling it configuring <csrf disabled="true"/> in your secured <http> section in your security xml, this way:
<http
authentication-manager-ref="myAuthManager"
access-decision-manager-ref="accessDecisionManager"
entry-point-ref="authenticationEntryPoint"
create-session="ifRequired"
access-denied-page="/unauthorized">
<custom-filter ref="myPreAuthenticatedFilter" position="PRE_AUTH_FILTER"/>
<logout logout-success-url="/page/home"/>
<anonymous key="anonymous"/>
<intercept-url pattern="/method/do" access="IS_AUTHENTICATED_ANONYMOUSLY()"/>
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<csrf disabled="true"/>
</http>
Edit
I have just realized that the order of the intercept-url should be just the opposite, starting from the most specific and ending with the most generic (I have already modified in the sample configuration I suggested)
In your case, it does not affect the behaviour given that both mappings have same access policy, but it should be this way.
I want to define access for some pages for user who has one of following roles (ROLE1 or ROLE2)
I'm trying to configure this in my spring security xml file as following:
<security:http entry-point-ref="restAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security" use-expressions="true">
<!-- skipped configuration -->
<security:intercept-url pattern="/rest/api/myUrl*" access="hasRole('ROLE1') or hasRole('ROLE2')" />
<!-- skipped configuration -->
</security:http>
I've tried various ways like:
access="hasRole('ROLE1, ROLE2')"
access="hasRole('ROLE1', 'ROLE2')"
access="hasAnyRole('[ROLE1', 'ROLE2]')"
etc
but nothing seems to be working.
I'm keep getting exception
java.lang.IllegalArgumentException: Unsupported configuration attributes:
or
java.lang.IllegalArgumentException: Failed to parse expression 'hasAnyRole(['ROLE1', 'ROLE2'])'
how should it be configured?
Thanks
How try with , separate. See doc here and here.
<security:intercept-url pattern="/rest/api/myUrl*" access="ROLE1,ROLE2"/>
OR
hasAnyRole('ROLE1','ROLE2')
The problem was that I configured custom access-decision-manager-ref="accessDecisionManager"
and didn't pass one of the voters.
Solved by adding org.springframework.security.web.access.expression.WebExpressionVoter to accessDecisionManager bean.
what is the use of auto-config=true in spring security.
In which scenario we should use this.
what is the actual use of using auto-config=true ?
auto-config="true" is equivalent to:
<http>
<form-login />
<http-basic />
<logout />
</http>
so it gives you a very basic security configuration to boot.
Source: https://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-auto-config
auto-config='true' means
for the intercept-url pattern the spring security provides the default login screen
This is one of the cases where we use auto-config = true:
<http auto-config='true'>
<intercept-url pattern="/**" access="ROLE_USER" />
</http>
This declaration means we want all URLs within our application to be secured, requiring the role ROLE_USER to access them. The element is the parent for all web-related namespace functionality. The element defines a pattern which is matched against the URLs of incoming requests using an ant path style syntax
Spring Security Reference:
"Use of this attribute is not recommended. Use explicit configuration elements instead to avoid confusion."
Source: https://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/html5/#nsa-http-attributes
I am trying to get my spring + hibernate + spring-security and tiles2 - "HelloWorld" application to work, following this guide (its in german unfortunately).
My problem is that I get a "404" error message when logging into my application. Redirection to the login page works as intended, but I can't reach "http://localhost:8080/App/j_spring_security_check" when I hit the login button.
My web.xml looks this way:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/defs/applicationContext.xml
/WEB-INF/defs/applicationContext-security.xml
</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
and applicationContext-security.xml file looks this way ...
<http use-expressions="true">
<intercept-url pattern="/index.html" access="permitAll" />
<intercept-url pattern="/timeout.html" access="permitAll" />
<intercept-url pattern="/redirect.html" access="permitAll" />
<intercept-url pattern="/media/**" access="permitAll" />
<intercept-url pattern="/includes/**" access="permitAll" />
<intercept-url pattern="/office/**" access="hasRole('ROLE_USER')" />
<intercept-url pattern="/office/admin/**" access="hasRole('ROLE_ADMIN')" />
<form-login login-page="/index.html"
authentication-failure-url="/index.html?login_error=1"
default-target-url='/office/kunden.html'
always-use-default-target='true'
/>
<logout logout-success-url="/index.html" />
<remember-me />
<session-management invalid-session-url="/index.html">
<concurrency-control max-sessions="2" error-if-maximum-exceeded="true" />
</session-management>
</http>
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="mysqldataSource"
authorities-by-username-query="select username, authority from benutzer where username = ?"
users-by-username-query="select username, password, enabled from benutzer where username = ?"/>
</authentication-provider>
</authentication-manager>
The database connection seems to be O.K.
I would be very glad if someone could give me a hint on that, because I already did a lot of googling, but didn't find a solution yet.
I use spring 3.1 and tomcat 7.0.23
I would check two things:
Request dispatch
Spring-security config
To check request dispatch just make sure that your application is accessible in the servlet container in the first place. Meaning, you have mentioned http://localhost:8080/App/j_spring_security_check. Is your application accessible under that URL? Does http://localhost:8080/App show proper content (HTTP 200)?
Also make sure that dispatcher servlet is configured properly. In tutorial you have provided, there is this section:
<!-- Spring Hauptteil -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
If you have not provided it in your web.xml, then your request might not even be dispatched properly before it ends up being examined via spring-security.
If this doesn't help you, try this.
Following documentation, the minimal configuration should be enough to check if your setup is correct. If you have followed tutorial, you might make some minor mistake (typeo, for instance) that will cause spring-security not to launch properly. Then it is easy to skip some error info in logger output.
I suggest you do the following.
Change your applicationContext-security.xml to support minimal configuration provided in documentation.
Launch the application and go to http://localhost:8080/App/j_spring_security_check
If you get proper response - try modifying config until you are done.
Point to learn
What DelegatingFilterProxy (defined in web.xml) really does is delegating request to some other filter managed by Spring's IoC. This filter is being defined in applicationContext-security via security namespace. If this won't work for some reason, the filter will not be initialized, and you may end up in seeing http 404 regardless the fact, that the rest of application starts properly.
Uffff, lots of text ;)
Your configuration looks ok. One thing that can case the 404 is if the default-target-url='/office/kunden.html' points to an controller or view that does not exist.
Check that the url /office/kunden.html works -- therefore deactivate the security stuff (just add <security:intercept-url pattern="/**" access="permitAll" />) and try it.
An other thing that may goes wrong, is that the tutorial is for spring 3.0 but not spring 3.0. I would not expect that this is the cause, but give it a try and downgrade.
For those people who face the same symptoms, but for a different situation, those who are behind a load balancer which does SSL offloading, the following answer might put you in the right direction. I had a similar problem and it turned out that the incoming request was handled correct, however as a response spring security sends a redirect to an absolute URL which is defined by the default-target-url attribute (starting with http instead of https)
<security:form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true" />
Now the client browser tries to open the redirected location on http, fails on the loadbalancer (which only accepts https traffic) and reports a 404 NOT FOUND
We solved this problem by adding the following mod_header directive for all incoming requests on port 443 (https) in the load balancer:
RequestHeader set X-Forwarded-Proto "https"
The will add an extra header. If you run an application server like Jetty, it will recognize this header and translate the incoming request. (see http://www.gossamer-threads.com/lists/apache/users/407272)
I'd like to use Spring with Java configuration, but almost all examples are writte in XML and I don't know how to translate them to Java. Look at these examples from Spring Security 3:
<http auto-config='true'>
<intercept-url pattern="/**" access="ROLE_USER" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="bob" password="bobspassword" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
<password-encoder hash="sha">
<salt-source user-property="username"/>
</password-encoder>
How could this translated to Java config? Or, more generally, how can I translate Spring XML config to Java? There is a little section about Java confing in the Spring reference but it is not that helpful.
Follow the JavaConfig project documentation.
This is probably more simple than you think. Spring isn't doing any magic. The XML config parser just creates bean definitions and registers them with the bean factory. You can do the same by creating a DefaultListableBeanFactory and registering your bean definitions with it. The main mistake here is to think "gee, I'll just create the beans and put them in the app context". This approach doesn't work because Spring creates beans lazily and the API is built around the idea of a factory that gets called when necessary, not a factory which does all the work at startup.
Here is some example code. Note that this sample needs a lot more lines of code but by defining your own helper methods, you should be able to break this down to something which should be on par with XML.
Also check the source for the Spring unit tests for examples.
You can't translate XML configurations with custom namespaces (such as http://www.springframework.org/schema/security). However, you can mix XML configurations with Java-based using #ImportResource