How to call bean with #Autowiring from app context in security context - java

After a research, I still dont found a solution for this problem.
My aim is to validate user in Custom Authentication Provider using database but the #Autowiring always throw Null Pointer Exception.
Here my code:
Custom Authentication Provider:
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Autowired
private Validator iValidate;
#Override
public Authentication authenticate(Authentication auth) throws AuthenticationException{
if (iValidate.userNameCheck(auth.getName()) != "00") {
auth=null;
}
return auth:
}
#Override
public boolean supports(Class<?> auth) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(auth));
}
}
Validator.java:
#Component
public class Validator implements IsamSvc {
private StopWatch sw = new StopWatch();
#Autowired
private JdbcTemplate jdbcTemplate;
#Override
public String userNameCheck(String mercid, String caller) {
/////validating code/////
}
}
Spring Security XML:
<global-method-security pre-post-annotations="enabled" />
<http pattern="/resources/**" security="none" />
<http auto-config="false" use-expressions="true" disable-url-rewriting="true" >
<session-management session-fixation-protection="newSession" session-authentication-error-url="/login.do?sessionalreadyexist">
<concurrency-control max-sessions="1" expired-url="/login.do?expired" error-if-maximum-exceeded="true" />
</session-management>
<intercept-url pattern="/clearcache" access="permitAll()" />
<intercept-url pattern="/login.do" access="permitAll()" />
<intercept-url pattern="/**" access="isFullyAuthenticated()" />
<logout logout-success-url="/login.do?logout" delete-cookies="JSESSIONID" invalidate-session="true" />
<access-denied-handler error-page="/403" />
<form-login login-page='/login.do' login-processing-url="/login" default-target-url="/main" always-use-default-target="true" authentication-failure-url="/login.do?error" username-parameter="username" password-parameter="password" authentication-details-source-ref="CustomAuthInfoSource" /> -->
</http>
<authentication-manager>
<authentication-provider ref="CustomAuthenticationProvider" />
</authentication-manager>
<beans:bean id="CustomAuthenticationProvider" class="xx.xxx.xxxx.xxxxx.CustomAuthenticationProvider" />
beans.xml:
<beans:bean id="iValidate" class="xx.xxx.xxxx.xxxxx.Validator" scope="prototype" />
/////// Other beans ////////
when i call #Autowired private Validator iValidate; in #Controller class, it work normally,but in CustomAuthenticationProvider, it will return null ...
Any Solution?

annotate the CustomAuthenticationProvider with #Component annotation

Related

Spring Security custom authentication provider with custom login doesn't put error parameter to the request

I've read and applied the Creating a Custom Login tutorial for custom login page and also custom authentication provider to my project.
As far as I understand from the documentations, spring security handles the login error by putting a parameter to the url such as "login?error=blabla".
But in my situation, no matter what user enters except for the true credentials, no request parameters are shown. But normal logins (meaning true logins) works fine.
Is there something I miss ?
CustomAuthenticationProviderImpl.java
#Component
public class CustomAuthenticationProviderImpl implements UnalAuthenticationProvider {
#Autowired
private CustomUserDetailService customUserDetailService;
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
UserDetails user = null;
try{
user = (UserDetails) customUserDetailService.loadUserByUsername(username);
}
catch(UsernameNotFoundException ex){
System.out.println("User name not found");
throw ex;
}
if (user == null) {
throw new BadCredentialsException("Username not found.");
}
if (!password.equals(user.getPassword())) {
throw new BadCredentialsException("Wrong password.");
}
Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
return new UsernamePasswordAuthenticationToken(user, password, authorities);
}
public boolean supports(Class<?> arg0) {
return true;
}
}
spring-security-config.xml
<global-method-security pre-post-annotations="enabled" />
<http auto-config="true">
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/access-denied" access="permitAll" />
<intercept-url pattern="/admin**" access="hasRole('ADMIN')" />
<intercept-url pattern="/**" access="hasRole('USER')" />
<form-login login-page="/login" default-target-url="/main" always-use-default-target="true"/>
<logout logout-url="/logout" logout-success-url="/"/>
<headers>
<frame-options policy="SAMEORIGIN"/>
</headers>
<session-management>
<concurrency-control expired-url="/login" />
</session-management>
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customAuthenticationProviderImpl" />
</authentication-manager>
After giving some thought, I also decided to remove all intercept-url, thinking that might be a unintented redirection because of those... But it also didn't work.
At a first glance you miss a configuration parameter in your <form-login> section, namely the authentication-failure-url.
This is where you instruct Spring Security to redirect your failing login attempts.
Try to add it as follows:
<form-login login-page="/login" <!--other configurations--> authentication-failure-url="/login?error=true" />.
And, of course, take care of managing the error parameter in your custom login jsp.

Authentication is not working in spring

I am quite new in spring security. I want to use spring security features. I am using following code.
my security.xml look like this
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/css/**" filters="none" />
<intercept-url pattern="/sign/**" access="isAnonymous()"/>
<!-- <intercept-url pattern="/signin" access="ROLE_USER" /> -->
<intercept-url pattern="/singout" access="permitAll" />
<intercept-url pattern="/accessdenied" access="permitAll" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<form-login login-page="/signin" default-target-url="/home" authentication-failure-url="/signin" />
<logout logout-success-url="/logout" />
</http>
<authentication-manager>
<authentication-provider user-service-ref="userLoginService">
<password-encoder hash="plaintext"/>
<!-- <user-service> -->
<!-- <user name="mkyong" password="123456" authorities="ROLE_USER" /> -->
<!-- </user-service> -->
</authentication-provider>
</authentication-manager>
User Login service code looks like this.....
public class UserLoginService implements UserDetailsService {
#Autowired
IDaoSupport loginDao;
public void setLoginDao(IDaoSupport loginDao) {
this.loginDao = loginDao;
}
public Collection<? extends GrantedAuthority> getAuthorities(Integer role) {
List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(role));
return authList;
}
public List<String> getRoles(Integer role) {
List<String> roles = new ArrayList<String>();
if (role.intValue() == 1) {
roles.add("ROLE_MODERATOR");
roles.add("ROLE_ADMIN");
roles.add("ROLE_USER");
} else if (role.intValue() == 2) {
roles.add("ROLE_MODERATOR");
}
return roles;
}
public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (String role : roles) {
authorities.add(new SimpleGrantedAuthority(role));
}
return authorities;
}
#Override
public UserDetails loadUserByUsername(String email)
throws UsernameNotFoundException {
Person person = loginDao.findByProp(Person.class, "loginId", email);
return new User(person.getLoginId(), person.getPassword(), getAuthorities(1));
}
}
web.xml looks like this....
<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>
But when i using this code i am getting following code.
.service() for servlet [rrank] in context with path [/sample] threw exception [Filter execution threw an exception] with root cause
java.lang.NoSuchMethodError: org.springframework.security.authentication.AnonymousAuthenticationToken.<init>(Ljava/lang/String;Ljava/lang/Object;Ljava/util/List;)V
at org.
can some body tell me whats wrong in this code.
Spring framework lib version doesn't match with your spring security lib version.
you can choose the matching version from MAVEN REPOSITARY SPRING SECURITY
good luck

Spring security - different SALTs at user creation and login time

I am facing again the same problem with Spring Security: "password does not match stored value".
I import 4 accounts in my graph (I'm using SpringData/Neo4J) with my custom GraphPopulator class and try to log in with one ("fbiville"/"s3cret").
The authentication is configured as follows:
<beans:bean id="encoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder">
<beans:constructor-arg value="******" />
</beans:bean>
<beans:bean id="userService" class="com.lateralthoughts.devinlove.service.LoginService" />
<authentication-manager>
<authentication-provider user-service-ref="userService">
<password-encoder ref="encoder" />
</authentication-provider>
</authentication-manager>
And the class in charge of persisting accounts is partially based on a custom SpringData repository implementation:
class PersonRepositoryImpl implements PersonRepositoryCustom {
private final PasswordEncoder passwordEncoder;
private final Neo4jOperations template;
#Autowired
public PersonRepositoryImpl(PasswordEncoder passwordEncoder,
Neo4jOperations template) {
this.passwordEncoder = passwordEncoder;
this.template = template;
}
#Override
#Transactional
public void persist(Person person) {
person.setPassword(passwordEncoder.encode(person.getPassword()));
template.save(person);
}
}
Finally, the login process is configured as follows:
<http auto-config='true' use-expressions='true' realm="devinlove: love is just another algorithm">
<form-login login-page="/login"
default-target-url="/"
authentication-failure-url="/login" />
<intercept-url pattern="/login" access="isAnonymous()" />
<intercept-url pattern="/**" access="hasRole('USER')" />
</http>
I debugged the StandardPasswordEncoder at account creation and user login attempt, and I noticed the salts don't match, which obviously leads to an authentication error.
You can clone the repository if you wanna reproduce the problem.
Thanks in advance !
Rolf
You need to use org.springframework.security.authentication.encoding.PasswordEncoder implementation, rather then org.springframework.security.crypto.password.PasswordEncoder.
So you can simply use as the follows:
<authentication-manager>
<authentication-provider user-service-ref="userService">
<password-encoder hash="sha" base64="true">
<!--Single salt - the very same as you are using in `encoder` instance-->
<salt-source system-wide="********"/>
</password-encoder>
</authentication-provider>
</authentication-manager>
Note, that this will work properly with #Autowired properties, though there shouldn't be #Qualifier and beans have to be represented only once.
It exposes implementation of such interfaces: org.springframework.security.authentication.encoding.PasswordEncoder and org.springframework.security.authentication.dao.SaltSource.
So in your particular case it would look like as follows:
class PersonRepositoryImpl implements PersonRepositoryCustom {
private final PasswordEncoder passwordEncoder;
private final Neo4jOperations template;
#Autowired
public PersonRepositoryImpl(PasswordEncoder passwordEncoder,
SaltSource saltSource
Neo4jOperations template) {
this.passwordEncoder = passwordEncoder;
this.saltSource = saltSource;
this.template = template;
}
#Override
#Transactional
public void persist(Person person) {
person.setPassword(passwordEncoder.encode(person.getPassword(), saltSource));
template.save(person);
}
}

How to redirect logged in user to homepage using Spring and Ldap

I am using Spring and Ldap for user authentication , Now I want to redirect the user to homepage when user is already logged in , I tried few solutions that I read through google but no luck. Here is my configuration code ...
Spring-Security.xml
<security:http auto-config="true" use-expressions="true"
access-denied-page="/denied" access-decision-manager-ref="accessDecisionManager"
disable-url-rewriting="true">
<security:remember-me key="_spring_security_remember_me"
token-validity-seconds="864000" token-repository-ref="tokenRepository" />
<security:intercept-url pattern="/login/login"
access="permitAll" />
<security:intercept-url pattern="/resources/**"
access="permitAll" />
<security:intercept-url pattern="/member/*"
access="permitAll" />
<security:intercept-url pattern="user/admin/admin"
access="hasRole('ROLE_ADMIN')" />
<security:intercept-url pattern="/user/user"
access="hasRole('ROLE_USERS')" />
<security:form-login login-page="/login/login"
authentication-failure-url="/login/login?error=true"
default-target-url="/checking" />
<security:logout invalidate-session="true"
logout-success-url="/login/login" logout-url="/login/logout" />
<security:custom-filter ref="captchaCaptureFilter"
before="FORM_LOGIN_FILTER" />
<!-- <security:custom-filter ref="captchaVerifierFilter" after="FORM_LOGIN_FILTER"
/> -->
<!-- <security:session-management
invalid-session-url="/logout.html">
<security:concurrency-control
max-sessions="1" error-if-maximum-exceeded="true" />
</security:session-management>
<security:session-management
session-authentication-strategy-ref="sas" /> -->
</security:http>
My Login Controller
public class LoginController {
#Autowired
private User user;
#Autowired
SecurityContextAccessor securityContextAccessor;
#RequestMapping(value = "login/login", method = RequestMethod.GET)
public String getLogindata(
#RequestParam(value = "error", required = false) String error,
Model model) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
model.addAttribute("error", error);
if (securityContextAccessor.isCurrentAuthenticationAnonymous() && auth.getPrincipal() == null) {
return "login/login";
} else {
return "redirect:/member/user";
}
}
}
auth.getName() always gives me anonymous user even if I am already logged in....
You should write your target redirection to the home page,
after successfully login in to the default-target-url in spring-security.xml, instead of default-target-url="/checking" .
I am not sure what are you trying to achieve in /login/login Controller ?
If you only want to redirect user, after successfully login to the /member/user , you should write:
<security:form-login login-page="/login"
always-use-default-target='true'
default-target-url="/member/user"
authentication-failure-url="/login/login?error=true"
/>
And login Controller should look like this:
#RequestMapping(value="/login", method = RequestMethod.GET)
public String login(ModelMap model) {
return "login";
}
If your authentication provider is OK and correct , Spring security will redirect you automatically to the /member/user after successfully login.

UserDetailsService Not Getting Called

I have this Spring XML:
<!-- Configure the authentication -->
<security:http auto-config="true" use-expressions="true">
<security:form-login login-page="/login"
authentication-failure-url="/login?error=true"
default-target-url="/index" />
<security:logout invalidate-session="true"
logout-success-url="/login"
logout-url="/logout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="testUDS" />
</security:authentication-manager>
<bean id="testUDS" class="net.safecycle.services.security.TestUserDetailService" />
My UserDetailsService implementation looks like this:
public class TestUserDetailService implements UserDetailsService {
public UserDetails loadUserByUsername
(
String username
) throws UsernameNotFoundException {
System.out.println ("loadUserByUsername (" + username + ")");
Collection<GrantedAuthority> authorities;
authorities = new LinkedList<GrantedAuthority> ();
authorities.add (new GrantedAuthorityImpl ("Admin"));
UserDetails ud = new User (username,
"ca",
true,
true,
true,
true,
authorities);
return ud;
}
}
When I log in with any username and the password 'ca', I should see the print statement at the top of my loadUserByUsername, but I do not. What is most perplexing is that I have used this code in another project with no problem. Is there anything I am missing, a copy mistake I'm hoping?
Here is my code from my xml file. Only missing thing is the allias.. try to add alias="authenticationManager" maybe it will help.
<beans:bean id="CustomUserDetailsService"
class="com.dennis.ehospital.hibernate.security.CustomUserDetailsService" />
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="CustomUserDetailsService" />
</authentication-manager>
Try to specify which resources are protected
<security:intercept-url pattern="/**" access="isAuthenticated()"/>

Categories