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
Related
I have the following configuration in my spring security xml file. When I try to authenticate I get the following message but cannot proceed.
INFO: Ignoring PartialResultException
I am aware that spring's documentation states that you can set ignorePartialResultException to true but this property seems to be in the LdapTemplate class which may require additional coding. I would like to accomplish all of this through bean configuration as I am not interested in role mapping.
<authentication-manager>
<authentication-provider ref="activeDirectoryAuthProvider" />
</authentication-manager>
<beans:bean id="activeDirectoryAuthProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<beans:constructor-arg value="mydomain.com" />
<beans:constructor-arg value=" ldap://mydomain.com:389" />
</beans:bean>
After digging around we found out that our role mapping was blocking the authentication. We were in fact hitting AD but Spring was trying to map a group name to a role that didn't exist within our system. Once we did that we were good to go.
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 have created a web service in my machine. Its URL is
http://localhost:8080/aaa/test?wsdl
I want to enable one feature to it. As soon as the user enters the url in browser, it should ask for the credentials. Can it be done in web services.
If yes, can some one guide how to achieve it.
Thanks.
If you're already using Spring, you can easily apply basic authentication to a specific URL pattern with Spring Security. In your applicationContext.xml, just add:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
<!-- HTTP basic authentication in Spring Security -->
<http>
<intercept-url pattern="/*wsdl?" access="ROLE_USER" />
<http-basic />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="someUser" password="somePassword" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
Example taken from Mkyong's Spring Security HTTP Basic Authentication Example.
If you'd like to lookup users in a database, you'd need to use a different authentication provider. The Spring Security reference mentions data-source-ref if you'd like to query the standard Spring Security user data tables. If you've already got your own structure, you might be interested in using user-service-ref instead, in which you can lookup the users yourself.
<authentication-manager>
<authentication-provider user-service-ref='myUserDetailsService'/>
</authentication-manager>
<beans:bean id="myUserDetailsService"
class="mypackage.MyUserDetailsService">
<beans:property name="dataSource" ref="dataSource"/>
</beans:bean>
And code mypackage.MyUserDetailsService extending JdbcDaoImpl and implementing UserDetailsService.
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 :)