/* * Copyright 2008-2009 MOPAS(Ministry of Public Administration and Security). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package egovframework.rte.fdl.security.userdetails.jdbc; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.sql.DataSource; import org.springframework.context.ApplicationContextException; import org.springframework.dao.DataAccessException; import org.springframework.security.GrantedAuthority; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.security.userdetails.hierarchicalroles.RoleHierarchy; import org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager; import egovframework.rte.fdl.security.userdetails.EgovUserDetails; import egovframework.rte.fdl.string.EgovObjectUtil; /** * 사용자계정 정보를 DB에서 관리할수 있도록 구현한 클래스 * <p> * <b>NOTE:</b> * org.springframework.security.userdetails * .jdbc.JdbcUserDetailsManager 를 확장하여 사용자 계정 정보를 DB에서 * 관리할 수 있도록 구현한 클래스이다. * @author 실행환경 개발팀 윤성종 * @since 2009.06.01 * @version 1.0 * @see <pre> * == 개정이력(Modification Information) == * * 수정일 수정자 수정내용 * ------- -------- --------------------------- * 2009.06.01 윤성종 최초 생성 * * </pre> */ public class EgovJdbcUserDetailsManager extends JdbcUserDetailsManager { private EgovUserDetails userDetails = null; private EgovUsersByUsernameMapping usersByUsernameMapping; private String mapClass; private RoleHierarchy roleHierarchy = null; /** * 사용자 테이블의 쿼리 조회 컬럼과 세션에서 사용할 사용자 VO와 메핑 할 클래스를 * 지정한다. * @param mapClass */ public void setMapClass(String mapClass) { this.mapClass = mapClass; } /** * Role Hierarchy를 지원한다. * (org.springframework.security * .userdetails.hierarchicalroles * .RoleHierarchyImpl) * @param roleHierarchy */ public void setRoleHierarchy(RoleHierarchy roleHierarchy) { this.roleHierarchy = roleHierarchy; } /* * (non-Javadoc) * @see * org.springframework.security.userdetails.jdbc * .JdbcUserDetailsManager#initDao() */ /** * JdbcUserDetailsManager 클래스 재정의 */ @Override protected void initDao() throws ApplicationContextException { super.initDao(); try { initMappingSqlQueries(); } catch (ClassNotFoundException e) { logger.error( "EgovJdbcUserDetailsManager.initDao.ClassNotFoundException : " + e.toString(), e); } catch (NoSuchMethodException e) { logger.error( "EgovJdbcUserDetailsManager.initDao.NoSuchMethodException : " + e.toString(), e); } catch (InstantiationException e) { logger.error( "EgovJdbcUserDetailsManager.initDao.InstantiationException : " + e.toString(), e); } catch (IllegalAccessException e) { logger.error( "EgovJdbcUserDetailsManager.initDao.IllegalAccessException : " + e.toString(), e); } catch (InvocationTargetException e) { logger.error( "EgovJdbcUserDetailsManager.initDao.InvocationTargetException : " + e.toString(), e); } catch (Exception e) { logger.error("EgovJdbcUserDetailsManager.initDao.Exception : " + e.toString(), e); } } /** * jdbc-user-service의 usersByUsernameQuery 사용자조회 * 쿼리와 authoritiesByUsernameQuery 권한조회 쿼리를 이용하여 정보를 * 저장한다. */ private void initMappingSqlQueries() throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException, ClassNotFoundException, Exception { logger.debug("## EgovJdbcUserDetailsManager query : " + getUsersByUsernameQuery()); setUsersByUsernameQuery(getUsersByUsernameQuery()); Class<?> clazz = EgovObjectUtil.loadClass(this.mapClass); Constructor<?> constructor = clazz.getConstructor(new Class[] {DataSource.class, String.class }); Object[] params = new Object[] {getDataSource(), getUsersByUsernameQuery() }; this.usersByUsernameMapping = (EgovUsersByUsernameMapping) constructor.newInstance(params); } /* * (non-Javadoc) * @see * org.springframework.security.userdetails.jdbc * .JdbcDaoImpl * #loadUsersByUsername(java.lang.String) */ /** * JdbcDaoImpl 클래스의 loadUsersByUsername 메소드 재정의 * 사용자명(또는 ID)로 EgovUserDetails의 정보를 조회하여 리스트 형식으로 * 저장한다. */ @Override protected List<String> loadUsersByUsername(String username) { return usersByUsernameMapping.execute(username); } /** * JdbcDaoImpl 클래스의 loadUsersByUsername 메소드 재정의 * 사용자명(또는 ID)로 EgovUserDetails의 정보를 조회한다. * @param username * @return * @throws UsernameNotFoundException * @throws DataAccessException */ @Override public EgovUserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { List<?> users = loadUsersByUsername(username); if (users.size() == 0) { throw new UsernameNotFoundException(messages.getMessage( "JdbcDaoImpl.notFound", new Object[] {username }, "Username {0} not found"), username); } Object obj = users.get(0); this.userDetails = (EgovUserDetails) obj; Set<String> dbAuthsSet = new HashSet<String>(); // if (enableAuthorities) { dbAuthsSet.addAll(loadUserAuthorities(this.userDetails.getUsername())); // } List<String> dbAuths = new ArrayList<String>(dbAuthsSet); addCustomAuthorities(this.userDetails.getUsername(), dbAuths); if (dbAuths.size() == 0) { throw new UsernameNotFoundException(messages.getMessage( "EgovJdbcUserDetailsManager.noAuthority", new Object[] {username }, "User {0} has no GrantedAuthority"), username); } GrantedAuthority[] arrayAuths = (GrantedAuthority[]) dbAuths.toArray(new GrantedAuthority[dbAuths .size()]); // RoleHierarchyImpl 에서 저장한 Role Hierarchy 정보가 // 저장된다. GrantedAuthority[] authorities = roleHierarchy.getReachableGrantedAuthorities(arrayAuths); // JdbcDaoImpl 클래스의 createUserDetails 메소드 재정의 return new EgovUserDetails(this.userDetails.getUsername(), this.userDetails.getPassword(), this.userDetails.isEnabled(), true, true, true, authorities, this.userDetails.getEgovUserVO()); } /** * 인증된 사용자 이름으로 사용자정보(EgovUserDetails)를 가져온다. * @return * @throws UsernameNotFoundException * @throws DataAccessException */ public EgovUserDetails getAuthenticatedUser() throws UsernameNotFoundException, DataAccessException { return loadUserByUsername(SecurityContextHolder.getContext() .getAuthentication().getName()); } }