/* ====================================================================
*
* Copyright (C) 2015 GeoSolutions S.A.S.
* http://www.geo-solutions.it
*
* GPLv3 + Classpath exception
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.
*
* ====================================================================
*
* This software consists of voluntary contributions made by developers
* of GeoSolutions. For more information on GeoSolutions, please see
* <http://www.geo-solutions.it/>.
*
*/
package it.geosolutions.geostore.services.rest.security;
import it.geosolutions.geostore.core.model.User;
import it.geosolutions.geostore.core.model.enums.Role;
import it.geosolutions.geostore.core.security.UserMapper;
import it.geosolutions.geostore.services.UserService;
import it.geosolutions.geostore.services.exception.BadRequestServiceEx;
import it.geosolutions.geostore.services.exception.NotFoundServiceEx;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.web.filter.GenericFilterBean;
/**
* Base class for GeoStore authentication filters (based on
* Spring Security filters).
* Includes basic functionalities for authentication based on
* external services, like:
* - automatic user creation / enabling
* - mapping of attributes on user creation
*
* @author Mauro Bartolomeoli
*
*/
public abstract class GeoStoreAuthenticationFilter extends GenericFilterBean {
private final static Logger LOGGER = Logger.getLogger(GeoStoreAuthenticationFilter.class);
public static final String USER_NOT_FOUND_MSG = "User not found. Please check your credentials";
@Autowired
protected UserService userService;
private boolean autoCreateUser = false;
private boolean enableAutoCreatedUsers = true;
private UserMapper userMapper;
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
if(req instanceof HttpServletRequest) {
authenticate((HttpServletRequest) req);
}
chain.doFilter(req, resp);
}
protected abstract void authenticate(HttpServletRequest req);
/**
* Helper method that creates an Authentication object for the given
* userName and raw (service retrieved) user details object.
*
* If autoCreateUser is true, creates unexisting users, before returning the
* authentication object.
*
* @param userName
* @param rawUser
* @return
*/
protected Authentication createAuthenticationForUser(String userName, String credentials, Object rawUser) {
User user = null;
try {
user = userService.get(userName);
} catch (NotFoundServiceEx e) {
if(autoCreateUser) {
try {
user = createUser(userName, credentials, rawUser);
} catch (BadRequestServiceEx e1) {
LOGGER.error("Error creating user for " + userName, e);
} catch (NotFoundServiceEx e1) {
LOGGER.error("Error creating user for " + userName, e);
}
} else {
LOGGER.error("User not found: " + userName, e);
}
}
return createAuthenticationForUser(user);
}
/**
* Creates a new user with the given
* userName and raw (service retrieved) user details object.
*
* It uses the configured UserMapper to populate user attributes.
*
* The user is assigned the USER role and no groups.
*
* @param userName
* @param rawUser
* @return
* @throws BadRequestServiceEx
* @throws NotFoundServiceEx
*/
protected User createUser(String userName, String credentials, Object rawUser) throws BadRequestServiceEx, NotFoundServiceEx {
User user = new User();
user.setName(userName);
user.setNewPassword(credentials);
user.setEnabled(enableAutoCreatedUsers);
Role role = Role.USER;
user.setRole(role);
user.setGroups(Collections.EMPTY_SET);
if(userMapper != null) {
userMapper.mapUser(rawUser, user);
}
if (userService != null) {
userService.insert(user);
}
return user;
}
/**
* Helper method that creates an Authentication object for the given user,
* populating GrantedAuthority instances.
*
* @param user
* @return
*/
protected Authentication createAuthenticationForUser(User user) {
if (user != null) {
String role = user.getRole().toString();
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new GrantedAuthorityImpl("ROLE_" + role));
return new UsernamePasswordAuthenticationToken(user, user.getPassword(), authorities);
} else {
LOGGER.error(USER_NOT_FOUND_MSG);
return null;
}
}
public void setUserService(UserService userService) {
this.userService = userService;
}
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
public void setAutoCreateUser(boolean autoCreateUser) {
this.autoCreateUser = autoCreateUser;
}
public void setEnableAutoCreatedUsers(boolean enableAutoCreatedUsers) {
this.enableAutoCreatedUsers = enableAutoCreatedUsers;
}
}