Spring security only for authorization. External authentication
Solution 1
implement a service that holds the user information.
@Service
public class UserAuthenticationInfoService {
private final Map<String, UserInfo> infos = new HashMap<String, UserInfo>();
public void addUserInfo(UserInfo userInfo){
infos.put(userInfo.getUsername(), userInfo);
}
public UserInfo getUserInfo(String username) {
return infos.get(username);
}
}
your controllers populates the UserAuthenticationInfoService service with the user information which you receive from your external application.
then implement a custom UserDetailsService to acces these information.
public class CustomerUserDetailsService implements UserDetailsService {
@Autowired
private UserAuthenticationInfoService service;
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {
UserInfo info = service.getUserInfo(userName);
return new User(info.getUsername(), info.getPassword(), info.getAuthorities());
}
}
and setup spring security context to use this UserDetailsService (you'll find it in the spring security documentation)
Solution 2
There are lots of tuts out there for the same, just need to google properly.
Anyway the best i have found till date (for almost all spring tuts) is Krams and here's the one for basic spring security.
http://krams915.blogspot.com/2010/12/spring-security-mvc-integration_18.html
For Implementing UserDetailService here's the link
http://krams915.blogspot.in/2012/01/spring-security-31-implement_5023.html
Some others are :
EDIT
This is how my own application does the authentication (Please note that i dont use external authentication, I simpply get details from DB but i guess it should not be much of an issue).
My security-context.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<global-method-security pre-post-annotations="enabled" jsr250-annotations="enabled" secured-annotations="enabled">
</global-method-security>
<http use-expressions="true">
<intercept-url pattern="/favicon.ico" access="permitAll" />
<intercept-url pattern="/static/**" access="permitAll"/>
<intercept-url pattern="/login.jsp*" access="permitAll"/>
<intercept-url pattern="/Admin/**" access="hasAnyRole('ROLE_SUPER_USER')"/>
<intercept-url pattern="/**" access="hasAnyRole('ROLE_USER','ROLE_SUPER_USER','ROLE_ADMIN'"/>
<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1" />
<http-basic/>
<logout logout-success-url="/login.jsp"/>
<remember-me user-service-ref="loginService" /
</http>
<authentication-manager>
<authentication-provider user-service-ref="loginService">
<password-encoder hash="md5"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="loginService" class="com.indyaah.service.LoginService">
</beans:bean>
<beans:bean id="authService" class="com.indyaah.service.AuthService" />
</beans:beans>
Now as you see i have specified a bean named loginService
as my authentication provider which is a bean for class com.indyaah.service.LoginService
.
The code for the same is : Pl Note I have truncated unnecessary code
package com.indyaah.service;
..
@Service
public class LoginService implements UserDetailsService {
....
/**
* Implementation for custom spring security UserDetailsService
*/
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {
logger.debug("Inside get member by username");
if (userName != null) {
Member memberVO = memberMapper.getMemberByUsername(userName);
if (memberVO != null) {
ArrayList<String> authList = memberRolesMapper.getMemberRoles(memberVO.getMemberId());
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (String role : authList) {
System.out.println(role);
authorities.add(new GrantedAuthorityImpl(role.toString()));
}
if (memberVO.getEnabled()) {
User user = new User(memberVO.getUserName(), memberVO.getPassword(), true, true, true, true, authorities);
return user;
} else {
logger.error("User with login: " + userName + " not Enabled in database. Authentication failed for user ");
throw new UsernameNotFoundException("User Not Enabled");
}
} else {
logger.error("User with login: " + userName + " not found in database. Authentication failed for user ");
throw new UsernameNotFoundException("user not found in database");
}
} else {
logger.error("No User specified in the login ");
throw new UsernameNotFoundException("No username specified");
}
}
}
Note 2 things over here.
- I get the user details (in my case from DB, yours may be diff.) and put it under a new
org.springframework.security.core.userdetails.User
object which is then returned by the method to spring security. - Also the authorities, (which I load separately from DB as per my DB architecture, again your scenario may vary) and pass it to spring security via same User object.
Tostis
Updated on June 04, 2022Comments
-
Tostis about 2 years
As title says, i'm developing a web application that receives user authentication infos from an external application. A spring controller of my app gets user info and stores it in session. I want to authenticate this user inside Spring Security and then use his roles to grant/deny access to urls like
<intercept-url pattern="/myprotectedpage*" access="hasRole('rightrole')" />
I read some tutorials speaking about PRE_AUTH_FILTER and UserDetailsService but i can't get the point. What is the application lifecycle of Spring Security? Which classes are involved? I need some full working samples.