Cannot use AccessDeniedHandler of spring security because of class extending throwable - java

I have an issue when trying to logging URI of endpoint when a user try to access a secured Resource.
I've created an instance of AccessDeniedHandler :
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
private final static Logger logger = Logger.getLogger(CustomAccessDeniedHandler.class);
#Override
public void handle(
HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException exc) throws IOException, ServletException {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
logger.warn("User: " + auth.getName()
+ " attempted to access the protected URL: "
+ request.getRequestURI());
}
}
}
But the handleMethod is never triggered and I don't understand why. In the project we have this class, and I suppose that it catch the exception before my AccessDeniedHandler, but I don't know o to deal with that.
#Provider
public class ExceptionMH extends Throwable implements ExceptionMapper<Exception> {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(ExceptionMH.class);
private void exceptionWarning(Exception e) {
logger.warn("[ExceptionMH] Warn: ", e);
}
private void exceptionError(Exception e) {
logger.error("[ExceptionMH] Error: ", e);
}
#Override
public Response toResponse(Exception exception) {
if (exception.getClass() == HttpRequestMethodNotSupportedException.class || exception.getClass() == NotFoundException.class) {
this.exceptionWarning(exception);
return Response.status(404).build();
} else if (exception.getClass() == CardException.class) {
this.exceptionWarning(exception);
return Response.status(200).build();
} else if (exception.getClass() == APIException.class) {
String msg = ((APIException) exception).getRawResponse();
logger.error("Facebook API exception: " + msg, exception);
return Response.status(500).entity(msg).build();
} else if (exception.getClass() == AccessDeniedException.class) {
this.exceptionError(exception);
return Response.status(401).entity("{ \"error\": \"" + exception.getMessage() + "\" }").build();
} else {
this.exceptionError(exception);
return Response.status(500).build();
}
}
}
What should I do to make AccessDeniedHandler triggered?
EDIT: Here's my configuration. The AccessDeniedHandler bean is declared and well added.
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<global-method-security pre-post-annotations="enabled" proxy-target-class="true"/>
<http entry-point-ref="authEntryPoint" create-session="never" >
<cors configuration-source-ref="corsSource"/>
<csrf disabled="true"/>
<custom-filter ref="authFilter" before="PRE_AUTH_FILTER"/>
<access-denied-handler ref="customAccessDeniedHandler"/>
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="daoAuthenticationProvider"/>
</authentication-manager>
<b:bean name="customAccessDeniedHandler"
class="io.markethero.security.CustomAccessDeniedHandler" />
<b:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<b:property name="userDetailsService" ref="userLoginService"/>
<b:property name="passwordEncoder" ref="customizePasswordEncoder"/>
</b:bean>
<b:bean id="customizePasswordEncoder" class="io.markethero.security.CustomizePasswordEncoder"/>
<b:bean id="authFilter" class="io.markethero.security.AuthFilter"/>
<b:bean id="authEntryPoint" class="io.markethero.security.AuthEntryPoint"/>
<b:bean id="corsSource" class="org.springframework.web.cors.UrlBasedCorsConfigurationSource">
<b:property name="corsConfigurations">
<util:map>
<b:entry key="/**">
<b:bean class="org.springframework.web.cors.CorsConfiguration">
<b:property name="allowCredentials" value="true"/>
<b:property name="allowedHeaders">
<util:list>
<b:value>Authorization</b:value>
<b:value>Content-Type</b:value>
</util:list>
</b:property>
<b:property name="exposedHeaders">
<b:list>
<b:value>Account-Locked</b:value>
<b:value>Account-Disabled</b:value>
<b:value>Bad-Credentials</b:value>
</b:list>
</b:property>
<b:property name="allowedMethods">
<util:list>
<b:value>POST</b:value>
<b:value>GET</b:value>
<b:value>PUT</b:value>
<b:value>DELETE</b:value>
<b:value>OPTIONS</b:value>
</util:list>
</b:property>
<b:property name="allowedOrigins" value="*"/>
</b:bean>
</b:entry>
</util:map>
</b:property>
</b:bean>
</b:beans>

It's hard to answer exactly without seeing your security configuration, but I suspect that you haven't registered the handler? Assuming that CustomAccessDeniedHandler is a bean called customAccessDeniedHandler, this should enable it.
#Configuration
public class WebSecurityConfig {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// all HttpSecurity configurations here
// add this
http.exceptionHandling().accessDeniedHandler(customAccessDeniedHandler);
return http.build();
}
}

Related

Authenticationmanager java config

What is the equivalent in java config of this XML authentication-manager config?
<authentication-manager alias="authenticationManager"> ... </authentication-manager>
What i need exactly is convert this xml config to java config :
`<security:authentication-manager alias="authenticationManagerLdap">
<security:authentication-provider ref="ldapActiveDirectoryAuthProvider"/>
</security:authentication-manager>
<bean id="ldapActiveDirectoryAuthProvider" class="ma.gov.adii.beans.AuthenticationAD">
<constructor-arg value="adii.gov.ma"/>
<constructor-arg value="ldap://addouane.adii.gov.ma:389/"/>
<property name="convertSubErrorCodesToExceptions" value="true" />
<property name="userDetailsContextMapper" ref="manageLoginService" />
</bean>`
My login clas is like this :
public class LoginMBean implements Serializable { #Autowired private AuthenticationManager authenticationManagerLdap;
Thanks
THE ANSWER IS LIKE THIS :
#Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
#Autowired
void registerProvider(AuthenticationManagerBuilder authLdap) {
authLdap.authenticationProvider(ldapActiveDirectoryAuthProvider());
}

WebSecurityConfig Java equivalent for spring LDAP authentication done with spring-security.xml

I implemented the LDAP authentication and authorization using Spring Security in my project. I configured the spring-security.xml and got it running. I am trying to do the same using Java (WebSecurityConfig.java). Can someone guide me on how to do this?
Here is my spring-security.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.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<!-- This is where we configure Spring-Security -->
<security:http auto-config="true" use-expressions="true" >
<security:intercept-url pattern="/main/common" access="hasRole('role.xyz.WebAdmin')"/>
<security:intercept-url pattern="/admincare" access="hasRole('role.xyz.WebAdmin')"/>
<security:form-login
login-page="/auth/login"
authentication-failure-url="/auth/login?error=true"
default-target-url="/main/common"/>
<security:logout
invalidate-session="true"
logout-success-url="/auth/login"
logout-url="/auth/logout"/>
</security:http>
<security:authentication-manager>
<security:authentication-provider ref="ldapAuthProvider" />
</security:authentication-manager>
<bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg name="authenticator">
<bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="ldapContext" />
<property name="userSearch">
<bean class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg name="searchBase" value="" />
<constructor-arg name="searchFilter" value="(&(uid={0})(objectclass=person)(ums-account-state=OK))" />
<constructor-arg name="contextSource" ref="ldapContext" />
</bean>
</property>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="com.gemalto.mobileid.service.UmsLdapAuthoritiesPopulator">
<constructor-arg ref="ldapContext"/>
</bean>
</constructor-arg>
</bean>
<security:ldap-server id="ldapContext" url="ldap://aaa:54389/dc=xxx.com" manager-dn="bbb" manager-password="ccc" />
</beans>
Now, if I want to do same in the JAVA style (in WebSecurityConfig.java) and get rid of the XML, how do I do? I am not so familiar with the APIs provided for this. I started it this way:
public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider("", "ldap://aaa:54389/dc=xxx.com");
provider.setConvertSubErrorCodesToExceptions(true);
provider.setUseAuthenticationRequestCredentials(true);
provider.setUseAuthenticationRequestCredentials(true);
return provider;
}
#Bean
public LoggerListener loggerListener() {
return new LoggerListener();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// Configuration for Redirects, Login-Page and stuff
http
.authorizeRequests()
.antMatchers("/admincare").authenticated()
.and()
.formLogin();
//.loginPage("/auth/login")
//.permitAll();
}
I am not sure how to set the rest of the parameters (as done in XML) in this Java code for the WebSecurityConfig. Any help would be really appreciated
Pls try this :-
#Bean
public BaseLdapPathContextSource contextSource() {
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource("ldap://aaa:54389/dc=xxx.com");
contextSource.setUserDn("bbb");
contextSource.setPassword("ccc");
return contextSource;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.contextSource(contextSource())
.and()
.ldapAuthoritiesPopulator(new UmsLdapAuthoritiesPopulator(contextSource()))
.and()
.userSearchBase("").userSearchFilter("(&(uid={0})(objectclass=person)(ums-account-state=OK))");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/main/common**","/admincare**").hasRole("role.xyz.WebAdmin")
.and().formLogin().loginPage("/auth/login").failureUrl("/auth/login?error=true").defaultSuccessUrl("/main/common")
.and().logout().invalidateHttpSession(true).logoutSuccessUrl("/auth/login").logoutUrl("/auth/logout");
}

Spring OAuth2 "Full authentication is required to access this resource"

I'm trying to use Spring OAuth2 for my rest app.
But looks like I made a mistake and I can find where I did it.
The flow should be:
1. get token from /oauth/token with username and password
2. make request to /security with provided token
MethodSecurityConfig:
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
#Autowired
private SecurityConfiguration securityConfig;
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
OAuth2ServerConfig:
#Configuration
public class OAuth2ServerConfig {
private static final String RESOURCE_ID = "nessnity";
#Configuration
#Order(10)
protected static class UiResourceConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers().antMatchers("/security")
.and()
.authorizeRequests()
.antMatchers("/security").access("hasRole('USER')");
}
}
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers().antMatchers("/security/")
.and()
.authorizeRequests()
.antMatchers("/security").access("#oauth2.hasScope('read')");
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Autowired
private TokenStore tokenStore;
#Autowired
private UserApprovalHandler userApprovalHandler;
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("my-client")
.resourceIds(RESOURCE_ID)
.authorizedGrantTypes("client_credentials")
.authorities("ROLE_CLIENT")
.scopes("read")
.secret("password")
.accessTokenValiditySeconds(60);
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore)
.userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.realm("sparklr2/client");
}
}
protected static class Stuff {
#Autowired
private ClientDetailsService clientDetailsService;
#Autowired
private TokenStore tokenStore;
#Bean
public ApprovalStore approvalStore() throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
#Bean
#Lazy
#Scope(proxyMode=ScopedProxyMode.TARGET_CLASS)
public SparklrUserApprovalHandler userApprovalHandler() throws Exception {
SparklrUserApprovalHandler handler = new SparklrUserApprovalHandler();
handler.setApprovalStore(approvalStore());
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
handler.setUseApprovalStore(true);
return handler;
}
}
}
SecurityConfiguration:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("root")
.password("password")
.roles("USER");
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/oauth/uncache_approvals", "/oauth/cache_approvals");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER");
}
}
Problem: when I tried to get token
curl --user root:password --data "grant_type=client_credentials" http://localhost:8080/oauth/token
I got message:
{"error":"invalid_client","error_description":"Bad client
credentials"}
The second question is how to pass username/password in the url params like /oauth/token?username=root&password=password ?
Thanks.
UPDATE
I decided to start from scratch and use xml configuration.
The following configuration works perfect:
<?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:oauth="http://www.springframework.org/schema/security/oauth2"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY"/>
<anonymous enabled="false"/>
<http-basic entry-point-ref="clientAuthenticationEntryPoint"/>
<custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER"/>
<access-denied-handler ref="oauthAccessDeniedHandler"/>
</http>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService"/>
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails"/>
</bean>
<bean id="clientDetails" class="com.nessnity.api.security.OAuthClienDetailsService">
<property name="id" value="testuser"/>
<property name="secretKey" value="secret" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client"/>
<property name="typeName" value="Basic"/>
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/>
<oauth:authorization-server
client-details-service-ref="clientDetails"
token-services-ref="tokenServices">
<oauth:authorization-code/>
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials/>
<oauth:password authentication-manager-ref="userAuthenticationManager"/>
</oauth:authorization-server>
<authentication-manager id="userAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider ref="customUserAuthenticationProvider">
</authentication-provider>
</authentication-manager>
<bean id="customUserAuthenticationProvider"
class="com.nessnity.api.security.OAuthUserAuthenticationProvider">
</bean>
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore"/>
<property name="supportRefreshToken" value="true"/>
<property name="accessTokenValiditySeconds" value="900000000"/>
<property name="clientDetailsService" ref="clientDetails"/>
</bean>
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore"/>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
</bean>
<http pattern="/resources/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false"/>
<intercept-url pattern="/resources/**" method="GET"/>
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER"/>
<access-denied-handler ref="oauthAccessDeniedHandler"/>
</http>
<oauth:resource-server id="resourceServerFilter"
resource-id="springsec" token-services-ref="tokenServices"/>
</beans>
I have faced similar for me it worked after doing the following change
In your AuthorizationServerConfiguration class replace
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.realm("sparklr2/client");
}
with the below code
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
//oauthServer.realm("sparklr2/client");
oauthServer.allowFormAuthenticationForClients();
}
and request should like
/oauth/token?grant_type=password&scope=read+write&client_id=yourclientId&client_secret=secret&username=userName&password=pwd
In your access token request you are using client credentials grant type. OAuth spec says that in case of client_credentials grant type you need to provide base64 encoded client_id:client_secret as Basic Authorization header.
For example if your client_id is google and client_secret is x23r-ss56-rfg8-6yt6, then you need to add these string as google:x23r-ss56-rfg8-6yt6, encode it using Base64 encoder and make request as
curl --header "Authorization: Basic <base64 encoded_string>" --data "grant_type=client_credentials" http://localhost:8080/oauth/token

BadCredentialsException is spring-security

continue my projects I encountered a problem in the authorization for accounts in Spring setsurity
- Problems in the query to the database, all the settings are correct, the database is created at the start of the project, there is no error in debug but at login message pops up in the log:
(UserAuthentication.java:authenticate:56) tradeManager.DAO.Impl.CustomHibernateDaoSupport.find(CustomHibernateDaoSupport.java:60)
tradeManager.service.authentication.UserAuthentication.authenticate(UserAuthentication.java:45)
...
Authentication request failed: org.springframework.security.authentication.BadCredentialsException:
User does not exists!
I added few catches to get precise exception and got new NullPointerException
17:52:34.280:WARN::/tradeManager/j_spring_security_check
java.lang.NullPointerException
at tradeManager.DAO.Impl.CustomHibernateDaoSupport.find(CustomHibernateDaoSupport.java:60)
at tradeManager.service.authentication.UserAuthentication.authenticate(UserAuthentication.java:48)
Can someone explain me what i'm doing wrong? Please help me.
here's the code affected by the query:
#Service("userAuthentication")
public class UserAuthentication implements AuthenticationManager {
protected static Logger userAccessLogger = Logger.getLogger("userAccessLog");
private UserDAO userDAO = new UserDAOImpl();
private Md5PasswordEncoder passwordEncoder = new Md5PasswordEncoder();
public Authentication authenticate(Authentication auth)
throws UsernameNotFoundException {
User user = null;
/*
* Init a database user object
*/
try {
// Retrieve user details from database
//user = userDAO.find(auth.getName());
List<User> list = userDAO.findAllByParam("username", auth.getName());
user = (list.isEmpty()) ? null : list.get(0);
} catch (Exception e) {
StackTraceElement[] stack = e.getStackTrace();
String exception = "";
for (StackTraceElement s : stack) {
exception = exception + s.toString() + "\n\t\t";
}
userAccessLogger.error(exception);
throw new BadCredentialsException("\n\tUser " + auth.getName() + " does not exists!\n");
}
/*
* Compare passwords
* Make sure to encode the password first before comparing
*/
if (user != null) {
if (passwordEncoder.isPasswordValid(user.getPassword(), (String) auth.getCredentials(), null)) {
throw new BadCredentialsException("\n\tWrong password!\n");
}
}
/*
* main logic of authentication manager
* Username and password must be the same to authenticate
*/
if (auth.getName().equals(auth.getCredentials())) {
throw new BadCredentialsException("Entered username and password are the same!");
} else {
assert user != null;
return new UsernamePasswordAuthenticationToken(
auth.getName(),
auth.getCredentials(),
getAuthorities(user.getAccess()));
}
}
/*
* Retrieves the correct ROLE type depending on the access level
*/
public Collection<GrantedAuthority> getAuthorities(Integer access) {
// Create a list of grants for this user
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);
userAccessLogger.debug("Grant ROLE_USER to this user");
authList.add(new SimpleGrantedAuthority("ROLE_USER"));
if (access.compareTo(1) == 0) {
authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
userAccessLogger.debug("Grant ROLE_ADMIN to this user");
}
// Return list of granted authorities
return authList;
}
here is CustomHibernateDaoSupport:
public class CustomHibernateDaoSupport<T> implements DAO<T> {
protected static Logger daoSupportLogger = Logger.getLogger("daoSupportLog");
private Class<T> clazz;
private SessionFactory sessionFactory;
public CustomHibernateDaoSupport(Class<T> clazz) {
this.clazz = clazz;
}
#Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private SessionFactory getSessionFactory() {
return sessionFactory;
}
#Override
#Transactional
public void save(T entity) {
getSessionFactory().getCurrentSession().save(entity);
}
#Override
#Transactional
public void update(T entity) {
getSessionFactory().getCurrentSession().update(entity);
}
#Override
#Transactional
public void delete(Serializable key) {
Object entity = getSessionFactory().getCurrentSession().get(clazz, key);
if (entity != null) {
getSessionFactory().getCurrentSession().delete(entity);
}
}
#Override
#Transactional
public T find(Serializable key) {
return (T) getSessionFactory().getCurrentSession().get(clazz, key);
}
#Override
#Transactional
public List<T> findAll() {
return getSessionFactory().getCurrentSession().createCriteria(clazz).list();
}
#Override
#Transactional
public List<T> findAllByParam(final String paramName, final Object paramValue) {
return getSessionFactory().getCurrentSession().createCriteria(clazz)
.add(Restrictions.eq(paramName, paramValue))
.list();
}
}
the security settings are like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- excluded from Security
<security:http pattern="/resources/*" security="none" />-->
<!-- Configuration of Spring-Security. Set to false to assign custom filters -->
<security:http auto-config="false" use-expressions="true" access-denied-page="/crimea/auth/denied"
entry-point-ref="authenticationEntryPoint" >
<security:logout invalidate-session="true"
logout-success-url="/crimea/auth/login"
delete-cookies="SPRING_SECURITY_REMEMBER_ME_COOKIE"
logout-url="/crimea/auth/logout"/>
<security:intercept-url pattern="/crimea/auth/login" access="permitAll"/>
<security:intercept-url pattern="/crimea/main/admin" access="hasRole('ROLE_ADMIN')"/>
<security:intercept-url pattern="/crimea/main/common" access="hasRole('ROLE_ADMIN','ROLE_USER')"/>
<security:custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER"/>
</security:http>
<!-- Custom filter for username and password -->
<bean id="authenticationFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"
p:authenticationManager-ref="userAuthentication"
p:authenticationFailureHandler-ref="customAuthenticationFailureHandler"
p:authenticationSuccessHandler-ref="customAuthenticationSuccessHandler"
p:postOnly="false" />
<!-- Custom authentication manager. !!! Username and password must not be the same !!! -->
<bean id="userAuthentication" class="tradeManager.service.authentication.UserAuthentication" />
<!-- default failure URL -->
<bean id="customAuthenticationFailureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"
p:defaultFailureUrl="/crimea/auth/login?error=true" />
<!-- default target URL -->
<bean id="customAuthenticationSuccessHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler"
p:defaultTargetUrl="/crimea/main/common" />
<!-- The AuthenticationEntryPoint -->
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"
p:loginFormUrl="/crimea/auth/login" />
<!-- Spring Security autowire the parent property -->
<security:authentication-manager/>
</beans>
I'm not showing User model becouse it standart. Acess is managed by Integer var:
/**
* Access level.
* 1 = Admin role
* 2 = Regular role
*/
#Column(name = "Access", nullable = false)
private Integer access;
Ок, didn't get any helpful answer, so tried my best. First of all, this line got my attention:
<security:intercept-url pattern="/crimea/main/common" access="hasRole('ROLE_ADMIN','ROLE_USER')"
I changed it to:
<security:intercept-url pattern="/crimea/main/common" access="hasRole('ROLE_USER')"
OK, I did more and changed query to username and I writed direct access, from:
list = userDAO.findAllByParam("from username",auth.getName());
to:
list = getSessionFactory().getCurrentSession().createCriteria(User.class)
.add(Restrictions.eq("username", auth.getName())).list();
and added the authentication session attributes to the class and start working He = ((
So, can anyone explain to me why my CustomHibernateDaoSupport class does not work??
OK. I solved my problem ))
First of all? I changed location of #Repository("employeeDAOImpl")annotation.
I changed SQL driver to com.jolbox.bonecp.BoneCPDataSource
naw my datasourse config loks likr this:
<!-- for database, imports the properties from database.properties -->
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="idleConnectionTestPeriod" value="60"/>
<property name="idleMaxAge" value="240"/>
<property name="maxConnectionsPerPartition" value="30"/>
<property name="minConnectionsPerPartition" value="10"/>
<property name="partitionCount" value="3"/>
<property name="acquireIncrement" value="5"/>
<property name="statementsCacheSize" value="100"/>
<property name="releaseHelperThreads" value="3"/>
</bean>
changed Spring shema to:
<tx:annotation-driven transaction-manager="transactionManager"/>
<mvc:annotation-driven />
in UserAuthentication class I added chek for NullPointer
if (entity == null) {
throw new BadCredentialsException("User does not exists!");
}
added to pom.xml maven dep. for new sql driver:
<dependency>
<groupId>com.jolbox</groupId>
<artifactId>bonecp</artifactId>
<version>0.8.0-rc1</version>
</dependency>
So My Authentication is working perfect naw =))
I solved my problem
First, I changed the location of #Repository("employeeDAOImpl")annotation.
I changed SQL driver to com.jolbox.bonecp.BoneCPDataSource
now my datasourse config looks like this:
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="idleConnectionTestPeriod" value="60"/>
<property name="idleMaxAge" value="240"/>
<property name="maxConnectionsPerPartition" value="30"/>
<property name="minConnectionsPerPartition" value="10"/>
<property name="partitionCount" value="3"/>
<property name="acquireIncrement" value="5"/>
<property name="statementsCacheSize" value="100"/>
<property name="releaseHelperThreads" value="3"/>
</bean>
changed Spring schema to:
<tx:annotation-driven transaction-manager="transactionManager"/>
<mvc:annotation-driven />
in UserAuthentication class I added check for a null
if (entity == null) {
throw new BadCredentialsException("User does not exists!");
}
added to pom.xml maven dep. for new sql driver:
com.jolbox
bonecp
0.8.0-rc1
So my authentication is working perfect now =))

Custom Authentication Provider on Spring Security 2 userDetailsService issue

I had Spring Security 2.0.5 on my webApp, using a default Provider. Now requirements have changed and I need a CustomAuthenticationProvider in order to change Authentication way.
This is my AuthenticationProvider
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Autowired
private ParamsProperties paramsProperties;
#SuppressWarnings("unchecked")
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
//Check username and passwd
String user = (String) authentication.getPrincipal();
String pass = (String) authentication.getCredentials();
if(StringUtils.isBlank(user) || StringUtils.isBlank(pass) ){
throw new BadCredentialsException("Incorrect username/password");
}
//Create SSO
SingleSignOnService service = new SingleSignOnService(paramsProperties.getServicesServer());
try {
//Check logged
service.setUsername(authentication.getName());
service.setPassword(authentication.getCredentials().toString());
ClientResponse response = service.call();
String result = response.getEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
Map<String,Object> map = mapper.readValue(result, new TypeReference<Map<String,Object>>() {} );
//Read code
String code = (String)map.get("code");
log.debug(" ** [Authenticate] Result: " + code );
for (String s : (List<String>)map.get( "messages" ) ) {
log.debug(" [Authenticate] Message: " + s );
}
if ( code.equals( "SESSION_CREATED" ) || code.equals( "SESSION_UPDATED" ) || code.equals( "SESSION_VERIFIED" ) ) {
UsernamePasswordAuthenticationToken tokenSSO = LoginHelper.getuserSringTokenFromAuthService(map);
return tokenSSO;
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
throw new AuthenticationServiceException( e.getMessage() );
}
}
public boolean supports(Class authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
And this is my security.xml
<http>
<form-login default-target-url ="/Login.html" always-use-default-target="true" login-page="/Login.html" login-processing-url="/j_spring_security_check"
authentication-failure-url="/Login.html" />
<http-basic />
<logout logout-success-url="/Login.html" />
</http>
<beans:bean id="myPasswordEncryptor"
class="com.mycomp.comunes.server.spring.core.MyPasswordEncoder" lazy-init="true">
<beans:constructor-arg>
<beans:bean class="org.jasypt.util.password.ConfigurablePasswordEncryptor" />
</beans:constructor-arg>
<beans:constructor-arg ref="paramsProperties" />
</beans:bean>
<beans:bean id="passwordEncoder"
class="org.jasypt.spring.security2.PasswordEncoder" lazy-init="true">
<beans:property name="passwordEncryptor">
<beans:ref bean="myPasswordEncryptor" />
</beans:property>
</beans:bean>
<beans:bean id="authenticationProvider"
class="com.mycomp.comunes.server.spring.manager.autenticacion.CustomAuthenticationProvider">
</beans:bean>
<authentication-provider user-service-ref='authenticationProvider'>
<password-encoder ref="passwordEncoder" />
</authentication-provider>
But when deploying, I get the following:
Caused by: java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy112 implementing org.springframework.security.providers.AuthenticationProvider,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.security.userdetails.UserDetailsService] for property 'userDetailsService': no matching editors or conversion strategy found
Can anyone help?
You refer to the authenticationProvider bean as a user service, which it is not.
<authentication-provider user-service-ref='authenticationProvider'>
With this old version of the framework, I can only guess that the way to use a custom auth provider is correctly described here.
Needless to say that it would be highly recommended to upgrade, if for nothing else, then just in order to get support easier.

Categories