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()"/>
Related
I am working on a Spring-MVC application in which I am using Spring-security for authentication and authorization. In one of the features, we are sending invitation to users to join the application. When the user clicks on the email link, I login the user from backend.
If there is an user who is already logged in, the session from old user is not removed. I have set in the XMl to create a newSession, but that is not helping either. The result is I have 2 users logged in the same browser. ANy ideas, Thank you.
security-application-context.xml code :
<security:http pattern="/resources/**" security="none"/>
<security:http create-session="ifRequired" use-expressions="true" auto-config="false" disable-url-rewriting="true">
<security:form-login login-page="/login" username-parameter="j_username" password-parameter="j_password"
login-processing-url="/j_spring_security_check" default-target-url="/canvaslisting"
always-use-default-target="false" authentication-failure-url="/login?error=auth"/>
<security:remember-me key="_spring_security_remember_me" user-service-ref="userDetailsService"
token-validity-seconds="1209600" data-source-ref="dataSource"/>
<security:logout delete-cookies="JSESSIONID" invalidate-session="true" logout-url="/j_spring_security_logout"/>
<security:intercept-url pattern="/**" requires-channel="https"/>
<security:port-mappings>
<security:port-mapping http="80" https="443"/>
</security:port-mappings>
<security:logout logout-url="/logout" logout-success-url="/" success-handler-ref="myLogoutHandler"/>
<security:session-management session-fixation-protection="migrateSession">
<security:concurrency-control session-registry-ref="sessionReg" max-sessions="5" expired-url="/login"/>
</security:session-management>
</security:http>
<beans:bean id="sessionReg" class="org.springframework.security.core.session.SessionRegistryImpl"/>
Controller code :
#RequestMapping(value = "/activatemembership/{token}")
public String activateMembershipForExistingUser(){
boolean val = this.groupMembersService.activateMembers(token,true);
}
Service layer code :
// Logout is true when clicked from email.
#Override
public boolean activateMembers(String token, boolean logout) {
try {
String[] parts = token.split(TOKEN_SEPARATOR);
String username = parts[0].toLowerCase();
Long groupAccountId = Long.valueOf(parts[2]);
GroupAccount groupAccount = this.groupAccountService.getGroupObjectOnlyById(groupAccountId);
Person person = this.personService.findPersonByUsername(username);
if(logout) {
Person loggedInUser = this.personService.getCurrentlyAuthenticatedUser();
if (!(loggedInUser == null)) {
loggedInUser.setOnlineStatus(null);
this.personService.directPersonUpdate(loggedInUser);
SecurityContextHolder.getContext().setAuthentication(null);
}
}
//Other service layer code
if(logout) {
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
Authentication authentication = new UsernamePasswordAuthenticationToken(person, null, authorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
Any ideas? Thank you.
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.
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
I´m developing an application with spring security authentication and MongoDB. The authentication method is working fine but only with ROLE_ADMIN. All methods that I need authentication for are annotated with:
#PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
When I try to authenticate with a user that has ROLE_USER I always get access declined error.
My spring security config is:
<security:global-method-security pre-post-annotations="enabled" />
<security:http auto-config="true" use-expressions="true">
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/logout" access="permitAll" />
<intercept-url pattern="/admin/**"
access="hasRole('ROLE_ADMIN') and hasRole('ROLE_USER')" />
<security:form-login login-page="/login" default-target-url="/admin/main"
authentication-failure-url="/accessdenied" />
<security:logout logout-success-url="/logout" />
<security:session-management>
<security:concurrency-control error-if-maximum-exceeded="true"
max-sessions="1"/>
</security:session-management>
</security:http>
If I use:
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN') and hasRole('ROLE_USER')" />
I get access denied for both ROLE_ADMIN and ROLE_USER.
If I use:
<intercept-url pattern="/admin/**" access="hasAnyRole('ROLE_ADMIN', 'ROLE_USER')" />
I can log in with a ROLE_ADMIN user but I can´t with ROLE_USER.
and in my LoginService I have:
public UserDetails loadUserByUsername(String email)
throws UsernameNotFoundException {
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
User user = getUserDetail(email);
userdetails = new org.springframework.security.core.userdetails.User(
user.getEmail(), user.getPwd(), enabled,
accountNonExpired, credentialsNonExpired, accountNonLocked,
getAuthorities(user.getIsAdmin()));
return userdetails;
}
public List<GrantedAuthority> getAuthorities(Integer role) {
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
if (role.intValue() == 0) {
authList.add(new SimpleGrantedAuthority("ROLE_USER"));
} else if (role.intValue() == 1) {
authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
System.out.println(authList);
return authList;
}
What am I missing?
When you have this kind of problem, please try first adding many System.out.println (or debug log) to see if your method is working, also change:
hasRole('ROLE_ADMIN') and hasRole('ROLE_USER')
for
hasRole('ROLE_ADMIN') or hasRole('ROLE_USER')
And check if the role.intValue() == 0 prints true with a sysout.
This
access="hasRole('ROLE_ADMIN') and hasRole('ROLE_USER')
means that both roles must be set the same time and sample code shows that it never happenes, because only one of two roles can be set.
It is different statement from hasAnyRole('ROLE_ADMIN', 'ROLE_USER') which should be true if at least one of these roles is set. Statment hasAnyRole is like or not and condition.
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.