Spring security only for authorization. External authentication

12,249

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 :

  1. Spring By Example
  2. MK Young
  3. And SpringSource Site itself

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.

  1. 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.
  2. 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.
Share:
12,249
Tostis
Author by

Tostis

Updated on June 04, 2022

Comments

  • Tostis
    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.