I am a newbie to spring-security.I have a issue with #Autowired annotation.
Below is my spring-security.xml file:
<http pattern="/login" security="none" />
<http pattern="/signup" security="none" />
<http pattern="/views/**" security="none" />
<http pattern="/createUser" security="none" />
<http pattern="/practice" security="none" />
<http use-expressions="true" authentication-manager-ref="authenticationManager">
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<form-login login-page="/login" default-target-url="/home"
authentication-failure-url="/login" username-parameter="username"
password-parameter="password" login-processing-url="/j_spring_security_check" />
<logout logout-success-url="/login" invalidate-session="true"
logout-url="/j_spring_security_logout" delete-cookies="JSESSIONID" />
<session-management invalid-session-url="/login">
<concurrency-control max-sessions="1"
expired-url="/login" />
</session-management>
</http>
<authentication-manager id="authenticationManager">
<authentication-provider user-service-ref="userDetailsService" />
</authentication-manager>
<beans:bean id="userDetailsService" class="com.practice.service.UserDetailsServiceImpl" />
<beans:bean name="
passwordEncoder "
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
This is my spring-servlet.xml configuration:
<context:annotation-config/>
<context:component-scan base-package="com.practice" />
<mvc:resources mapping="/views/**" location="/views/" />
<mvc:annotation-driven />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations"
value="classpath:com/practice/resources/database.properties"></property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:com/practice/resources/hibernate.cfg.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
I would request for signup page, and after filling the necessary details , it hits my controller , where i save the user in the database, then i authenticate the user, in the request against the one which i stored in the database. I followed this stackoverflow post for guidance.
The strange thing is the autowiring is not happening in the class, where i implement the UserDetailsService interface :
#Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
PasswordEncoder passwordEncoder;
#Autowired
UserService userService;
#Override
public UserDetails loadUserByUsername(String arg0)
throws UsernameNotFoundException {
System.out.println("ddfddd");
return null;
}}
Whereas autowiring is taking place in other service classes , where i autowired the same fields as mentioned above !!
The same thing happens when i do a login , and when i debugged , the fields are null ! and also in the classes where i wrote my CustomAuthenticationProvider !
Any suggestion ?? If there is any mistake in my configuration do correct me.
Update
I am getting the following error,
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.practice.service.UserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
when i remove #Service annotation and when i add context:annotation-config
If you have defined a UserService bean with an #Component annotation, which is picked up by the component scan in spring-servlet.xml, then the problem could be, that spring-servlet.xml is a child application context from spring-security.xml. In that case, beans from the security context aren't able to access any beans from the child context, only the other way round. So you have to make sure, that all required beans are accessible from the spring-security.xml context (e.g. by specifying all beans explicitly or by moving the annotation-config and component-scan elements in the spring-security.xml context).
Related
I have the following spring security xml file, which has authentication and authorization configuration. The problem here is the authentication works fine but the authorization is not kicking off, its not even retrieving role. I have worked on similar kind of scenario earlier but had no problems. The only difference was I was using spring 3 that time now this is with spring 4. Any thing that I am missing here or something I am doing wrong.
<security:authentication-manager alias="preAuthManager">
<security:authentication-provider ref="preAuthProvider" />
</security:authentication-manager>
<bean id="preAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="frfPreAuthUserDetailsService" />
</bean>
<bean id="frfPreAuthProcessingFilter" class="*.*.*.ws.infra.FRFPreAuthenticatedProcessingFilter">
<property name="authenticationManager" ref="preAuthManager" />
<property name="stripDomain" value="true" />
<property name="toLowerCase" value="true" />
</bean>
<bean id="preAuthEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<bean id="frfPreAuthUserDetailsService" class="*.*.*.ws.infra.FRFPreAuthenticatedUserDeatilsService">
<!-- Configure the Role Service ... 1) InMemoryRoleRetriever 2) Arrow2RoleRetriver; This configuration is shown below...-->
<property name="roleService" ref="arrow2RoleServiceImpl" />
</bean>
<bean id="arrow2RoleServiceImpl" class="*.*.*.ws.arrowrest.ArrowRoleRetriever">
<constructor-arg index="0" value="${arrow.rest.endPoint}" />
<constructor-arg index="1" value="authorized-function-names" />
<constructor-arg>
<map>
<entry key="CallerName" value="${arrow.appName}"></entry>
<entry key="ApplicationName" value="${arrow.appName}"></entry>
</map>
</constructor-arg>
</bean>
<!-- <global-method-security pre-post-annotations="enabled"/> -->
<security:global-method-security secured-annotations="enabled"/>
<security:http pattern="/WEB-INF/jsp/access_denied.jsp" security="none"/>
<security:http pattern = "/app/*" create-session="never" use-expressions="false" auto-config="false" entry-point-ref="preAuthEntryPoint"
authentication-manager-ref="preAuthManager"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<security:custom-filter ref="frfPreAuthProcessingFilter" before="PRE_AUTH_FILTER" />
<security:intercept-url pattern="/app/3a4/rules" method="GET" access="ROLE_ADMIN"/>
</security:http>
<!-- Allows access if principal has the proper granted authority -->
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://www.springframework.org/schema/beans">
<constructor-arg>
<list>
<bean class="org.springframework.security.access.vote.RoleVoter" />
</list>
</constructor-arg>
<property name="allowIfAllAbstainDecisions" value="false" />
</bean>
I'm trying to follow this example about Spring Security and adapt it to my needs but I'm having troubles with its configuration
I have a LoginService that looks like this:
// This example does not make sense of course but I'm just
// trying to make it work with #PreAuthorize("hasRole('ROLE_ADMIN')")
// and see an exception or something that lets me know that
// it is actually working ..
public class LoginService {
private final static Logger LOGGER = Logger.getLogger(LoginService.class.getName());
private AdministratorRepository administratorRepository;
public LoginService(DSLContext ctx) {
this.administratorRepository = new AdministratorRepository(ctx);
}
#Transactional
#PreAuthorize("hasRole('ROLE_ADMIN')")
public void login(String userId, String password) {
LOGGER.debug("Login for " + userId);
this.administratorRepository.login(userId, password);
}
}
and I am already initalizing this class in my applicationContext-jooq.xml like this:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/mz_db" />
<property name="username" value="postgres" />
<property name="password" value="1234" />
</bean>
<!-- Configure Spring's transaction manager to use a DataSource -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Configure jOOQ's TransactionProvider as a proxy to Spring's transaction manager -->
<bean id="transactionProvider"
class="com.mz.server.web.SpringTransactionProvider">
</bean>
<!-- Configure jOOQ's ConnectionProvider to use Spring's TransactionAwareDataSourceProxy,
which can dynamically discover the transaction context -->
<bean id="transactionAwareDataSource"
class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg ref="dataSource" />
</bean>
<bean class="org.jooq.impl.DataSourceConnectionProvider" name="connectionProvider">
<constructor-arg ref="transactionAwareDataSource" />
</bean>
<!-- Configure the DSL object, optionally overriding jOOQ Exceptions with Spring Exceptions -->
<bean id="dsl" class="org.jooq.impl.DefaultDSLContext">
<constructor-arg ref="config" />
</bean>
<!-- Invoking an internal, package-private constructor for the example
Implement your own Configuration for more reliable behaviour -->
<bean class="org.jooq.impl.DefaultConfiguration" name="config">
<property name="SQLDialect"><value type="org.jooq.SQLDialect">POSTGRES_9_4</value></property>
<property name="connectionProvider" ref="connectionProvider" />
<property name="transactionProvider" ref="transactionProvider" />
</bean>
<!-- BEGIN Services -->
<bean id="loginService" class="com.mz.server.web.service.LoginService">
<constructor-arg>
<ref bean="dsl" />
</constructor-arg>
</bean>
<!-- END Services -->
My problem is that I want loginService to be managed by Spring Security as well. This is my applicationContext-security.xml:
<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-4.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">
<global-method-security pre-post-annotations="enabled" secured-annotations="enabled" />
<http auto-config="true" >
<intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
</http>
<authentication-manager >
<authentication-provider>
<user-service>
<user name="admin" password="admin" authorities="ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
<!-- <beans:bean name="loginService" class="com.mz.server.web.service.LoginService"/> -->
</beans:beans>
If I comment out
<beans:bean name="loginService" class="com.mz.server.web.service.LoginService"/>
I'm getting the error that there's no default constructor - which is true since this class is 1. Already instantiated and 2. Requires a DSLContext object as constructor parameter.
If I let it commented out just nothing happens. No exception of warning is shown. #PreAuthorize appears to be getting ignored ..
How can I resolve this issue?
You can add constructor injection into your XML configuration for the LoginService. Do you autowire DSLContext, too?
This line in your XML is invoking the default constructor:
<beans:bean name="loginService" class="com.mz.server.web.service.LoginService"/>
If you want to do constructor injection of the DSLContext it'd look like this:
<bean name="loginService" class="com.mz.server.web.service.LoginService">
<constructor-arg ref="dslContext"/>
</bean>
This assumes that the bean factory also has a bean for your DSLContext.
You can also try going all annotation or XML configuration, but not mixing and matching.
I have been working on jaas ldap authentication of an application. For the development purpose I am using tomcat to deploy the application. When I am deploying the application in tomcat , system is successfully authenticating the user by authenticating the user credentials against a ldap server and authorizing the user by fetching roles from database.
But my problem is when I deploying the application in web sphere server, I am encountering an exception
"unable to find LoginModule class: com.enterprise.security.ldap.TrivialLoginModule"
I have not included any trivial module in my application
But my application is running fine in tomcat.
For my authentication module following classes are defined:
CustomAuthenticationProvider.java
DummyRoleGranter.java
JaasLdapLogin.java
The configuration file is
ldap.jaas.config
Could someone please help me in identifying what I am missing for the Web Sphere Server.
My spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:security="http://www.springframework.org/schema/security"
xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
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.xsd">
<bean id="userDetailsService" class="com.work.application.service.UserDetailsService" />
<security:authentication-manager alias="authenticationmanager">
<security:authentication-provider ref="customauthProvider" />
</security:authentication-manager>
<security:http pattern="/resources/**" security="none" />
<security:http pattern="/login*" security="none" />
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/**" access="isAuthenticated()" />
<security:form-login login-page="/login" authentication-failure-url="/loginfailed" default-target-url="/index"/>
<security:logout invalidate-session="true" delete-cookies="JSESSIONID" logout-success-url="/login" logout-url="/j_spring_security_logout"/>
<security:session-management session-fixation-protection="newSession">
<security:concurrency-control max-sessions="1" expired-url="/loginfailed" error-if-maximum-exceeded="false"/>
</security:session-management>
<security:csrf />
</security:http>
<bean id="csrfFilter" class="org.springframework.security.web.csrf.CsrfFilter">
<constructor-arg>
<bean
class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository">
<property name="headerName" value="X-SECURITY" />
</bean>
</constructor-arg>
</bean>
<bean id="customauthProvider" class="com.work.application.authprovider.CustomAuthenticationProvider">
<constructor-arg name="delegate" ref="jaasAuthProvider" />
<property name="userDetailsService" ref="userDetailsService" />
</bean>
<bean id="jaasAuthProvider" class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
<property name="loginConfig" value="classpath:ldap.jaas.config" />
<property name="authorityGranters">
<list>
<bean class="com.work.application.authprovider.DummyRoleGranter" />
</list>
</property>
<property name="loginContextName" value="LDAPLogin" />
<property name="callbackHandlers">
<list>
<bean class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler" />
<bean class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler" />
</list>
</property>
</bean>
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/login"/>
<constructor-arg>
<list>
<bean class="org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler">
<constructor-arg>
<list>
<value>JSESSIONID</value>
</list>
</constructor-arg>
</bean>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
</beans>
ldap.jaas.config
LDAPLogin
{
com.work.application.authprovider.JaasLdapLogin Sufficient
contextProvider="com.sun.jndi.ldap.LdapCtxFactory"
providerURL="ldap://aeiou:389/dc=app,dc=off,dc=net"
providerURL_2="ldap://aeiou3:389/dc=app,dc=off,dc=net"
providerURL_3="ldap://aeiou2:389/dc=app,dc=off,dc=net"
authenticationMode="simple"
providerURL_3="ldap://ABCDEFGH:389/"
providerURL_2="ldap://ABCDEFGI:389/"
principalPattern="cn={0},cn=Users,dc=app,dc=off,dc=net"
;
};
Got the work around. Since Websphere is not recognizing the config file so instead of using the JaasAuthenticationProvider I used DefaultJaasAuthenticationProvider and injected the configuration in the AppConfigurationEntry Map. It's working fine in websphere now.
I had a working configuration with ConcurrentSessionControlStrategy and my own sessionRegistry implementation. I upgraded to spring security 3.2.4 and had to change ConcurrentSessionControlStrategy to ConcurrentSessionControlAuthenticationStrategy. and now it seems that the sessionRegistry isn't connected meaning ConcurrentSessionControlAuthenticationStrategy.onAuthenticaton doesn't enter the sessionRegistry.registerNewSession. What to de?
my configuration xml:
<security:http use-expressions="true" auto-config="false"
entry-point-ref="loginUrlAuthenticationEntryPoint">
<security:intercept-url pattern="/**"
access="isAuthenticated()" />
<security:custom-filter position="FORM_LOGIN_FILTER"
ref="twoFactorAuthenticationFilter" />
<security:logout logout-url="/player/logout"
logout-success-url="/demo/player/logoutSuccess" />
<security:session-management>
<security:concurrency-control
max-sessions="1" session-registry-ref="clusteredSessionRegistryImpl"
error-if-maximum-exceeded="false" />
</security:session-management>
</security:http>
<bean
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
<constructor-arg ref="clusteredSessionRegistryImpl" />
<property name="maximumSessions" value="1" />
</bean>
<bean id="loginUrlAuthenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/demo/player/login?login_error=true" />
</bean>
<bean id="twoFactorAuthenticationFilter" class="com.XXX.filter.TwoFactorAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationFailureHandler" ref="failureHandler" />
<property name="authenticationSuccessHandler" ref="playerAuthenticationSuccessHandler" />
<property name="postOnly" value="true" />
</bean>
<bean id="failureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login?login_error=true" />
</bean>
<bean id="bCryptPasswordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
ref="authenticationProvider">
</security:authentication-provider>
</security:authentication-manager>
</beans>
Seems I'm late with the answer, but any way..
The functionality of ConcurrentSessionControlStrategy is exactly split between three Strategies now - ConcurrentSessionControlAuthenticationStrategy, SessionFixationProtectionStrategy and RegisterSessionAuthenticationStrategy.
To have a right substitute, you should use CompositeSessionAuthenticationStrategy adding these three delegates in mentioned order.
So, afraid, ConcurrentSessionControlAuthenticationStrategy is wrongly mentioned in deprecation comment as a substitute of ConcurrentSessionControlStrategy. It at least requires availability of RegisterSessionAuthenticationStrategy to maintain SessionRegistry. Otherwise, SessionRegistry remains empty, and the "substitute" always reports "ok".
I guess, the approach is changed to make it more flexible having several handlers as delegates instead of one (using CompositeSessionAuthenticationStrategy, you can have any number of SessionAuthenticationStrategy's doing independent :) things).
I need to get the username and password for the logged user to use these credentials to reconnect to another product.
Here is my SecurityContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
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.1.xsd">
<security:http auto-config="false" use-expressions="true"
access-denied-page="/app/accessDenied">
<security:intercept-url pattern="/login"
access="permitAll" />
<security:intercept-url pattern="/pages/home.xhtml"
access="isAuthenticated() and hasAnyRole('ROLE_ARCH_ADMIN','ROLE_ARCH_Data_ENTRY','ROLE_ARCH_VIEWER','ROLE_ARCH_SUPER_VIEWER','ROLE_ARCH_MANAGER')" />
<security:intercept-url pattern="/pages/realtyDoc/realtyDoc.xhtml"
access="isAuthenticated() and hasAnyRole('ROLE_ARCH_ADMIN','ROLE_ARCH_DATA_ENTRY','ROLE_ARCH_VIEWER','ROLE_ARCH_SUPER_VIEWER','ROLE_ARCH_MANAGER')" />
<security:form-login login-page="/login1.xhtml"
login-processing-url="/processLogin" authentication-failure-url="/login1.xhtml?faces-redirect=true"
authentication-success-handler-ref="successHandler" />
<security:logout invalidate-session="true" logout-url="/j_spring_security_logout"
logout-success-url="/login1.xhtml" />
</security:http>
<bean id="contextSource"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://PDA-FNTEST:389/" />
<property name="userDn" value="user#PD.LOCAL" />
<property name="password" value="password" />
</bean>
<bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value="DC=PD,DC=LOCAL" />
<constructor-arg index="1" value="(sAMAccountName={0})" />
<constructor-arg index="2" ref="contextSource" />
</bean>
<bean id="bindAuthenticator"
class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="contextSource" />
<property name="userSearch" ref="userSearch" />
</bean>
<bean id="ldapAuthoritiesPopulator"
class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="contextSource" />
<constructor-arg value="OU=ARCH_USERS_OU,DC=PD,DC=LOCAL" />
</bean>
<bean id="ldapAuthProvider"
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg index="0" ref="bindAuthenticator" />
<constructor-arg index="1" ref="ldapAuthoritiesPopulator" />
</bean>
<security:authentication-manager erase-credentials="false" >
<security:authentication-provider
ref="ldapAuthProvider" />
</security:authentication-manager>
<bean id="successHandler" class="com.eblacorp.archive.security.LoginSuccessHandler">
<property name="userAccessService" ref="userAccessService" />
</bean>
<bean id="loginFailuerHandler" class="com.eblacorp.archive.security.LoginFailuerHandler" />
</beans>
When I use this code to print username and password, the password shows as null.
UserDetails user = (UserDetails) SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
System.out.println("username: " + user.getUsername());
System.out.println("password: " + user.getPassword());
I set erase-credentials="false" in authentication manager as:
<security:authentication-manager erase-credentials="false" >
<security:authentication-provider
ref="ldapAuthProvider" />
</security:authentication-manager>
To get password value use getCredentials().
Object getCredentials()
The credentials that prove the principal is correct. This is usually a password, but could be anything relevant to the AuthenticationManager. Callers are expected to populate the credentials.
Returns:
the credentials that prove the identity of the Principal