开源地图服务geoserver源代码研究实践(用户登录与密码验证)
开源地图服务geoserver利用spring security进行用户验证和授权。
一、有关spring security。
SecurityContextHolder 负责存储安全上下文,保存用户信息,权限等等。
Authentication 认证信息类,身份信息、密码信息、细节、认证信息。
UserDetails 用户信息,包含用户的一些基本字段、密码、用户名等。
UserDetailsService 用户信息,是一个接口、一般可以重数据库中获取用户名、密码创建。
AuthenticationManager 认证管理类、通过实现该接口实现自定义认证。
AuthenticationProvider 认证提供者、是一个接口、一个真正的认证、一个是满足某种条件才认证。spring中提供了多种实现 类。
二、关于geoserver地图服务验证。
首先程序是从GeoServerApplication进入的,我们来看该类的方法init都做了哪些工作。从下面的代码中可以知道方法中创建了GeoServerSecurityManager。
/** Initialization override which sets up a locator for i18n resources. */
protected void init() {
// enable GeoServer custom resource locators
getResourceSettings().setUseMinifiedResources(false);
getResourceSettings().setResourceStreamLocator(new GeoServerResourceStreamLocator());
/*
* The order string resource loaders are added to IResourceSettings is of importance so we need to add any contributed loader prior to the
* standard ones so it takes precedence. Otherwise it won't be hit due to GeoServerStringResourceLoader never resolving to null but falling
* back to the default language
*/
List<IStringResourceLoader> alternateResourceLoaders =
getBeansOfType(IStringResourceLoader.class);
for (IStringResourceLoader loader : alternateResourceLoaders) {
LOGGER.info("Registering alternate resource loader: " + loader);
getResourceSettings().getStringResourceLoaders().add(loader);
}
getResourceSettings()
.getStringResourceLoaders()
.add(0, new GeoServerStringResourceLoader());
getDebugSettings().setAjaxDebugModeEnabled(false);
getApplicationSettings().setPageExpiredErrorPage(GeoServerExpiredPage.class);
// generates infinite redirections, commented out for the moment
// getSecuritySettings().setCryptFactory(GeoserverWicketEncrypterFactory.get());
// theoretically, this replaces the old GeoServerRequestEncodingStrategy
// by making the URLs encrypted at will
GeoServerSecurityManager securityManager = getBeanOfType(GeoServerSecurityManager.class);
setRootRequestMapper(
new DynamicCryptoMapper(getRootRequestMapper(), securityManager, this));
getRequestCycleListeners().add(new CallbackRequestCycleListener(this));
WebUIMode webUIMode = getGeoServer().getGlobal().getWebUIMode();
if (webUIMode == null) {
webUIMode = WebUIMode.DEFAULT;
}
switch (webUIMode) {
case DO_NOT_REDIRECT:
getRequestCycleSettings().setRenderStrategy(RenderStrategy.ONE_PASS_RENDER);
break;
case REDIRECT:
getRequestCycleSettings().setRenderStrategy(RenderStrategy.REDIRECT_TO_BUFFER);
break;
case DEFAULT:
getRequestCycleSettings()
.setRenderStrategy(
defaultIsRedirect
? RenderStrategy.REDIRECT_TO_BUFFER
: RenderStrategy.ONE_PASS_RENDER);
}
}
断点进入到GeoServerSecurityManager内,首先程序从实现spring的接口方法onApplicationEvent进入,GeoServerSecurityManager类定义了reload()方法。该方法大意是存储一个实例后,重新加载的配置将会改变。所以使用reload意为重新加载。
/**
* Reload the configuration which may have been updated in the meanwhile; after a restore as an
* instance.
*/
public void reload() {
try {
Resource masterPasswordInfo = security().get(MASTER_PASSWD_INFO_FILENAME);
if (masterPasswordInfo.getType() != Type.UNDEFINED) {
LOGGER.warning(
masterPasswordInfo.path()
+ " is a security risk. Please read this file and remove it afterward");
}
} catch (Exception e1) {
throw new RuntimeException(e1);
}
// migrate from old security config
try {
Version securityVersion = getSecurityVersion();
boolean migratedFrom21 = false;
if (securityVersion.compareTo(VERSION_2_2) < 0) {
migratedFrom21 = migrateFrom21();
}
if (securityVersion.compareTo(VERSION_2_3) < 0) {
removeErroneousAccessDeniedPage();
migrateFrom22(migratedFrom21);
}
if (securityVersion.compareTo(VERSION_2_4) < 0) {
migrateFrom23();
}
if (securityVersion.compareTo(VERSION_2_5) < 0) {
migrateFrom24();
}
if (securityVersion.compareTo(CURR_VERSION) < 0) {
writeCurrentVersion();
}
} catch (Exception e1) {
throw new RuntimeException(e1);
}
// read config and initialize... we do this now since we can be ensured that the spring
// context has been property initialized, and we can successfully look up security
// plugins
KeyStoreProvider keyStoreProvider = getKeyStoreProvider();
try {
// check for an outstanding masster password change
keyStoreProvider.commitMasterPasswordChange();
// check if there is an outstanding master password change in case of SPrin injection
init();
for (GeoServerSecurityProvider securityProvider :
GeoServerExtensions.extensions(GeoServerSecurityProvider.class)) {
securityProvider.init(this);
}
} catch (Exception e) {
throw new BeanCreationException("Error occured reading security configuration", e);
}
}
在GeoServerSecurityManager成员变量userGroupServices和roleServices定义了用户组和角色组。用于存储用户信息、角色信息。
/** cached user groups */
ConcurrentHashMap<String, GeoServerUserGroupService> userGroupServices =
new ConcurrentHashMap<String, GeoServerUserGroupService>();
/** cached role services */
ConcurrentHashMap<String, GeoServerRoleService> roleServices =
new ConcurrentHashMap<String, GeoServerRoleService>();
在的reload方法中调用了 migrateFrom21()方法,将创建一个带有方法initializeFromConfig的GeoServerSecurityService接回调。同时如果遇到在userGroupServices没有默认的用户名为admin,密码为geosever的用户,则userGroupServices将为创建该用户。该账户的目的用于用户登录后进行验证。我们来看一下migrateFrom21方法具体源代码。
boolean migrateFrom21() throws Exception {
if (role().getType() != Type.UNDEFINED) {
Resource oldUserFile = security().get("users.properties.old");
if (oldUserFile.getType() != Type.UNDEFINED) {
LOGGER.warning(oldUserFile.path() + " could be removed manually");
}
return false; // already migrated
}
LOGGER.info("Start security migration");
// master password configuration
MasterPasswordProviderConfig mpProviderConfig =
loadMasterPassswordProviderConfig("default");
if (mpProviderConfig == null) {
mpProviderConfig = new URLMasterPasswordProviderConfig();
mpProviderConfig.setName("default");
mpProviderConfig.setClassName(URLMasterPasswordProvider.class.getCanonicalName());
mpProviderConfig.setReadOnly(false);
((URLMasterPasswordProviderConfig) mpProviderConfig).setURL(new URL("file:passwd"));
((URLMasterPasswordProviderConfig) mpProviderConfig).setEncrypting(true);
saveMasterPasswordProviderConfig(mpProviderConfig, false);
// save out the default master password
MasterPasswordProvider mpProvider =
loadMasterPasswordProvider(mpProviderConfig.getName());
Resource propFile = security().get("users.properties");
Properties userprops = null;
if (propFile.getType() == Type.RESOURCE) userprops = Util.loadPropertyFile(propFile);
mpProvider.setMasterPassword(extractMasterPasswordForMigration(userprops));
}
MasterPasswordConfig mpConfig = new MasterPasswordConfig();
mpConfig.setProviderName(mpProviderConfig.getName());
saveMasterPasswordConfig(mpConfig);
// check for services.properties, create if necessary
Resource serviceFile = security().get("services.properties");
if (serviceFile.getType() == Type.UNDEFINED) {
org.geoserver.util.IOUtils.copy(
Util.class.getResourceAsStream("serviceTemplate.properties"),
serviceFile.out());
}
long checkInterval = 10000; // 10 secs
// check for the default user group service, create if necessary
GeoServerUserGroupService userGroupService =
loadUserGroupService(XMLUserGroupService.DEFAULT_NAME);
KeyStoreProvider keyStoreProvider = getKeyStoreProvider();
keyStoreProvider.reloadKeyStore();
keyStoreProvider.setUserGroupKey(
XMLUserGroupService.DEFAULT_NAME, randomPasswdProvider.getRandomPassword(32));
keyStoreProvider.storeKeyStore();
PasswordValidator validator = loadPasswordValidator(PasswordValidator.DEFAULT_NAME);
if (validator == null) {
// Policy allows any password except null, this is the default
// at before migration
PasswordPolicyConfig pwpconfig = new PasswordPolicyConfig();
pwpconfig.setName(PasswordValidator.DEFAULT_NAME);
pwpconfig.setClassName(PasswordValidatorImpl.class.getName());
pwpconfig.setMinLength(0);
savePasswordPolicy(pwpconfig);
validator = loadPasswordValidator(PasswordValidator.DEFAULT_NAME);
}
validator = loadPasswordValidator(PasswordValidator.MASTERPASSWORD_NAME);
if (validator == null) {
// Policy requires a minimum of 8 chars for the master password
PasswordPolicyConfig pwpconfig = new PasswordPolicyConfig();
pwpconfig.setName(PasswordValidator.MASTERPASSWORD_NAME);
pwpconfig.setClassName(PasswordValidatorImpl.class.getName());
pwpconfig.setMinLength(8);
savePasswordPolicy(pwpconfig);
validator = loadPasswordValidator(PasswordValidator.MASTERPASSWORD_NAME);
}
if (userGroupService == null) {
XMLUserGroupServiceConfig ugConfig = new XMLUserGroupServiceConfig();
ugConfig.setName(XMLUserGroupService.DEFAULT_NAME);
ugConfig.setClassName(XMLUserGroupService.class.getName());
ugConfig.setCheckInterval(checkInterval);
ugConfig.setFileName(XMLConstants.FILE_UR);
ugConfig.setValidating(true);
// start with weak encryption, plain passwords can be restored
ugConfig.setPasswordEncoderName(
loadPasswordEncoder(GeoServerPBEPasswordEncoder.class, null, false).getName());
ugConfig.setPasswordPolicyName(PasswordValidator.DEFAULT_NAME);
saveUserGroupService(ugConfig);
userGroupService = loadUserGroupService(XMLUserGroupService.DEFAULT_NAME);
}
// check for the default role service, create if necessary
GeoServerRoleService roleService = loadRoleService(XMLRoleService.DEFAULT_NAME);
if (roleService == null) {
XMLRoleServiceConfig gaConfig = new XMLRoleServiceConfig();
gaConfig.setName(XMLRoleService.DEFAULT_NAME);
gaConfig.setClassName(XMLRoleService.class.getName());
gaConfig.setCheckInterval(checkInterval);
gaConfig.setFileName(XMLConstants.FILE_RR);
gaConfig.setValidating(true);
gaConfig.setAdminRoleName(XMLRoleService.DEFAULT_LOCAL_ADMIN_ROLE);
gaConfig.setGroupAdminRoleName(XMLRoleService.DEFAULT_LOCAL_GROUP_ADMIN_ROLE);
saveRoleService(gaConfig);
roleService = loadRoleService(XMLRoleService.DEFAULT_NAME);
}
String filterName = GeoServerSecurityFilterChain.BASIC_AUTH_FILTER;
GeoServerSecurityFilter filter = loadFilter(filterName);
if (filter == null) {
BasicAuthenticationFilterConfig bfConfig = new BasicAuthenticationFilterConfig();
bfConfig.setName(filterName);
bfConfig.setClassName(GeoServerBasicAuthenticationFilter.class.getName());
bfConfig.setUseRememberMe(true);
saveFilter(bfConfig);
}
/*filterName = GeoServerSecurityFilterChain.BASIC_AUTH_NO_REMEMBER_ME_FILTER;
filter = loadFilter(filterName);
if (filter==null) {
BasicAuthenticationFilterConfig bfConfig = new BasicAuthenticationFilterConfig();
bfConfig.setClassName(GeoServerBasicAuthenticationFilter.class.getName());
bfConfig.setName(filterName);
bfConfig.setUseRememberMe(false);
saveFilter(bfConfig);
}*/
filterName = GeoServerSecurityFilterChain.FORM_LOGIN_FILTER;
filter = loadFilter(filterName);
if (filter == null) {
UsernamePasswordAuthenticationFilterConfig upConfig =
new UsernamePasswordAuthenticationFilterConfig();
upConfig.setClassName(GeoServerUserNamePasswordAuthenticationFilter.class.getName());
upConfig.setName(filterName);
upConfig.setUsernameParameterName(
UsernamePasswordAuthenticationFilterConfig.DEFAULT_USERNAME_PARAM);
upConfig.setPasswordParameterName(
UsernamePasswordAuthenticationFilterConfig.DEFAULT_PASSWORD_PARAM);
saveFilter(upConfig);
}
filterName = GeoServerSecurityFilterChain.SECURITY_CONTEXT_ASC_FILTER;
filter = loadFilter(filterName);
if (filter == null) {
SecurityContextPersistenceFilterConfig pConfig =
new SecurityContextPersistenceFilterConfig();
pConfig.setClassName(GeoServerSecurityContextPersistenceFilter.class.getName());
pConfig.setName(filterName);
pConfig.setAllowSessionCreation(true);
saveFilter(pConfig);
}
filterName = GeoServerSecurityFilterChain.SECURITY_CONTEXT_NO_ASC_FILTER;
filter = loadFilter(filterName);
if (filter == null) {
SecurityContextPersistenceFilterConfig pConfig =
new SecurityContextPersistenceFilterConfig();
pConfig.setClassName(GeoServerSecurityContextPersistenceFilter.class.getName());
pConfig.setName(filterName);
pConfig.setAllowSessionCreation(false);
saveFilter(pConfig);
}
filterName = GeoServerSecurityFilterChain.ANONYMOUS_FILTER;
filter = loadFilter(filterName);
if (filter == null) {
AnonymousAuthenticationFilterConfig aConfig = new AnonymousAuthenticationFilterConfig();
aConfig.setClassName(GeoServerAnonymousAuthenticationFilter.class.getName());
aConfig.setName(filterName);
saveFilter(aConfig);
}
filterName = GeoServerSecurityFilterChain.REMEMBER_ME_FILTER;
filter = loadFilter(filterName);
if (filter == null) {
RememberMeAuthenticationFilterConfig rConfig =
new RememberMeAuthenticationFilterConfig();
rConfig.setClassName(GeoServerRememberMeAuthenticationFilter.class.getName());
rConfig.setName(filterName);
saveFilter(rConfig);
}
filterName = GeoServerSecurityFilterChain.FILTER_SECURITY_INTERCEPTOR;
filter = loadFilter(filterName);
if (filter == null) {
SecurityInterceptorFilterConfig siConfig = new SecurityInterceptorFilterConfig();
siConfig.setClassName(GeoServerSecurityInterceptorFilter.class.getName());
siConfig.setName(filterName);
siConfig.setAllowIfAllAbstainDecisions(false);
siConfig.setSecurityMetadataSource("geoserverMetadataSource");
saveFilter(siConfig);
}
filterName = GeoServerSecurityFilterChain.FILTER_SECURITY_REST_INTERCEPTOR;
filter = loadFilter(filterName);
if (filter == null) {
SecurityInterceptorFilterConfig siConfig = new SecurityInterceptorFilterConfig();
siConfig.setClassName(GeoServerSecurityInterceptorFilter.class.getName());
siConfig.setName(filterName);
siConfig.setAllowIfAllAbstainDecisions(false);
siConfig.setSecurityMetadataSource("restFilterDefinitionMap");
saveFilter(siConfig);
}
filterName = GeoServerSecurityFilterChain.FORM_LOGOUT_FILTER;
filter = loadFilter(filterName);
if (filter == null) {
LogoutFilterConfig loConfig = new LogoutFilterConfig();
loConfig.setClassName(GeoServerLogoutFilter.class.getName());
loConfig.setName(filterName);
saveFilter(loConfig);
}
filterName = GeoServerSecurityFilterChain.DYNAMIC_EXCEPTION_TRANSLATION_FILTER;
filter = loadFilter(filterName);
if (filter == null) {
ExceptionTranslationFilterConfig bfConfig = new ExceptionTranslationFilterConfig();
bfConfig.setClassName(GeoServerExceptionTranslationFilter.class.getName());
bfConfig.setName(filterName);
bfConfig.setAuthenticationFilterName(null);
bfConfig.setAccessDeniedErrorPage("/accessDenied.jsp");
saveFilter(bfConfig);
}
filterName = GeoServerSecurityFilterChain.GUI_EXCEPTION_TRANSLATION_FILTER;
filter = loadFilter(filterName);
if (filter == null) {
ExceptionTranslationFilterConfig bfConfig = new ExceptionTranslationFilterConfig();
bfConfig.setClassName(GeoServerExceptionTranslationFilter.class.getName());
bfConfig.setName(filterName);
bfConfig.setAuthenticationFilterName(GeoServerSecurityFilterChain.FORM_LOGIN_FILTER);
bfConfig.setAccessDeniedErrorPage("/accessDenied.jsp");
saveFilter(bfConfig);
}
// check for the default auth provider, create if necessary
GeoServerAuthenticationProvider authProvider =
loadAuthenticationProvider(GeoServerAuthenticationProvider.DEFAULT_NAME);
if (authProvider == null) {
UsernamePasswordAuthenticationProviderConfig upAuthConfig =
new UsernamePasswordAuthenticationProviderConfig();
upAuthConfig.setName(GeoServerAuthenticationProvider.DEFAULT_NAME);
upAuthConfig.setClassName(UsernamePasswordAuthenticationProvider.class.getName());
upAuthConfig.setUserGroupServiceName(userGroupService.getName());
saveAuthenticationProvider(upAuthConfig);
authProvider = loadAuthenticationProvider(GeoServerAuthenticationProvider.DEFAULT_NAME);
}
// save the top level config
SecurityManagerConfig config = new SecurityManagerConfig();
config.setRoleServiceName(roleService.getName());
config.getAuthProviderNames().add(authProvider.getName());
config.setEncryptingUrlParams(false);
// start with weak encryption
config.setConfigPasswordEncrypterName(
loadPasswordEncoder(GeoServerPBEPasswordEncoder.class, true, false).getName());
// setup the default remember me service
RememberMeServicesConfig rememberMeConfig = new RememberMeServicesConfig();
rememberMeConfig.setClassName(GeoServerTokenBasedRememberMeServices.class.getName());
config.setRememberMeService(rememberMeConfig);
config.setFilterChain(GeoServerSecurityFilterChain.createInitialChain());
saveSecurityConfig(config);
// TODO: just call initializeFrom
userGroupService.setSecurityManager(this);
roleService.setSecurityManager(this);
// populate the user group and role service
GeoServerUserGroupStore userGroupStore = userGroupService.createStore();
GeoServerRoleStore roleStore = roleService.createStore();
// migrate from users.properties
Resource usersFile = security().get("users.properties");
if (usersFile.getType() == Type.RESOURCE) {
// load user.properties populate the services
Properties props = Util.loadPropertyFile(usersFile);
UserAttributeEditor configAttribEd = new UserAttributeEditor();
for (Iterator<Object> iter = props.keySet().iterator(); iter.hasNext(); ) {
// the attribute editors parses the list of strings into password, username and
// enabled
// flag
String username = (String) iter.next();
configAttribEd.setAsText(props.getProperty(username));
// if the parsing succeeded turn that into a user object
UserAttribute attr = (UserAttribute) configAttribEd.getValue();
if (attr != null) {
GeoServerUser user =
userGroupStore.createUserObject(
username, attr.getPassword(), attr.isEnabled());
userGroupStore.addUser(user);
for (GrantedAuthority auth : attr.getAuthorities()) {
String roleName =
GeoServerRole.ADMIN_ROLE.getAuthority().equals(auth.getAuthority())
? XMLRoleService.DEFAULT_LOCAL_ADMIN_ROLE
: auth.getAuthority();
GeoServerRole role = roleStore.getRoleByName(roleName);
if (role == null) {
role = roleStore.createRoleObject(roleName);
roleStore.addRole(role);
}
roleStore.associateRoleToUser(role, username);
}
}
}
} else {
// no user.properties, populate with default user and roles
if (userGroupService.getUserByUsername(GeoServerUser.ADMIN_USERNAME) == null) {
userGroupStore.addUser(GeoServerUser.createDefaultAdmin());
GeoServerRole localAdminRole =
roleStore.createRoleObject(XMLRoleService.DEFAULT_LOCAL_ADMIN_ROLE);
roleStore.addRole(localAdminRole);
roleStore.associateRoleToUser(localAdminRole, GeoServerUser.ADMIN_USERNAME);
}
}
// add the local group administrator role
if (roleStore.getRoleByName(XMLRoleService.DEFAULT_LOCAL_GROUP_ADMIN_ROLE) == null) {
roleStore.addRole(
roleStore.createRoleObject(XMLRoleService.DEFAULT_LOCAL_GROUP_ADMIN_ROLE));
}
// replace all occurrences of ROLE_ADMINISTRATOR in the property files
// TODO Justin, a little bit brute force, is this ok ?
for (String filename :
new String[] {"services.properties", "layers.properties", "rest.properties"}) {
Resource file = security().get(filename);
if (file.getType() == Type.UNDEFINED) {
continue;
}
List<String> lines = new ArrayList<String>();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.in()))) {
String line;
while ((line = reader.readLine()) != null) {
lines.add(
line.replace(
GeoServerRole.ADMIN_ROLE.getAuthority(),
XMLRoleService.DEFAULT_LOCAL_ADMIN_ROLE));
}
}
try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.out()))) {
for (String s : lines) {
writer.println(s);
}
}
}
// check for roles in services.properties but not in user.properties
serviceFile = security().get("services.properties");
if (serviceFile.getType() != Type.UNDEFINED) {
Properties props = Util.loadPropertyFile(serviceFile);
for (Entry<Object, Object> entry : props.entrySet()) {
StringTokenizer tokenizer = new StringTokenizer((String) entry.getValue(), ",");
while (tokenizer.hasMoreTokens()) {
String roleName = tokenizer.nextToken().trim();
if (roleName.length() > 0) {
if (roleStore.getRoleByName(roleName) == null) {
roleStore.addRole(roleStore.createRoleObject(roleName));
}
}
}
}
}
// check for roles in data.properties but not in user.properties
Resource dataFile = security().get("layers.properties");
if (dataFile.getType() == Type.RESOURCE) {
Properties props = Util.loadPropertyFile(dataFile);
for (Entry<Object, Object> entry : props.entrySet()) {
if ("mode".equals(entry.getKey().toString())) continue; // skip mode directive
StringTokenizer tokenizer = new StringTokenizer((String) entry.getValue(), ",");
while (tokenizer.hasMoreTokens()) {
String roleName = tokenizer.nextToken().trim();
if (roleName.length() > 0 && roleName.equals("*") == false) {
if (roleStore.getRoleByName(roleName) == null)
roleStore.addRole(roleStore.createRoleObject(roleName));
}
}
}
}
// persist the changes
roleStore.store();
userGroupStore.store();
// first part of migration finished, rename old file
if (usersFile.getType() != Type.UNDEFINED) {
Resource oldUserFile = dataDir.get(usersFile.path() + ".old");
usersFile.renameTo(oldUserFile);
LOGGER.info("Renamed " + usersFile.path() + " to " + oldUserFile.path());
}
LOGGER.info("End security migration");
return true;
}
/** migration from 2.2.x to 2.3.x return <code>true</code> if migration has taken place */
boolean migrateFrom22(boolean migratedFrom21) throws Exception {
String filterName = GeoServerSecurityFilterChain.ROLE_FILTER;
GeoServerSecurityFilter filter = loadFilter(filterName);
Resource logoutFilterDir =
filterRoot().get(GeoServerSecurityFilterChain.FORM_LOGOUT_FILTER);
Resource oldLogoutFilterConfig = logoutFilterDir.get("config.xml.2.2.x");
Resource oldSecManagerConfig = security().get("config.xml.2.2.x");
if (filter != null) {
if (oldLogoutFilterConfig.getType() == Type.RESOURCE)
LOGGER.warning(oldLogoutFilterConfig.path() + " could be removed manually");
if (oldSecManagerConfig.getType() == Type.RESOURCE)
LOGGER.warning(oldSecManagerConfig.path() + " could be removed manually");
return false; // already migrated
}
// add role filter
RoleFilterConfig rfConfig = new RoleFilterConfig();
rfConfig.setClassName(GeoServerRoleFilter.class.getName());
rfConfig.setName(filterName);
rfConfig.setHttpResponseHeaderAttrForIncludedRoles(
GeoServerRoleFilter.DEFAULT_HEADER_ATTRIBUTE);
rfConfig.setRoleConverterName(GeoServerRoleFilter.DEFAULT_ROLE_CONVERTER);
saveFilter(rfConfig);
// add ssl filter
SSLFilterConfig sslConfig = new SSLFilterConfig();
sslConfig.setClassName(GeoServerSSLFilter.class.getName());
sslConfig.setName(GeoServerSecurityFilterChain.SSL_FILTER);
sslConfig.setSslPort(443);
saveFilter(sslConfig);
// set redirect url after successful logout
if (!migratedFrom21)
org.geoserver.util.IOUtils.copy(
logoutFilterDir.get("config.xml").in(), oldLogoutFilterConfig.out());
LogoutFilterConfig loConfig =
(LogoutFilterConfig)
loadFilterConfig(GeoServerSecurityFilterChain.FORM_LOGOUT_FILTER);
loConfig.setRedirectURL(GeoServerLogoutFilter.URL_AFTER_LOGOUT);
saveFilter(loConfig);
if (!migratedFrom21)
org.geoserver.util.IOUtils.copy(
security().get("config.xml").in(), oldSecManagerConfig.out());
SecurityManagerConfig config = loadSecurityConfig();
for (RequestFilterChain chain : config.getFilterChain().getRequestChains()) {
if (chain.getFilterNames()
.contains(GeoServerSecurityFilterChain.SECURITY_CONTEXT_ASC_FILTER)) {
chain.setAllowSessionCreation(true);
chain.getFilterNames()
.remove(GeoServerSecurityFilterChain.SECURITY_CONTEXT_ASC_FILTER);
}
if (chain.getFilterNames()
.contains(GeoServerSecurityFilterChain.SECURITY_CONTEXT_NO_ASC_FILTER)) {
chain.setAllowSessionCreation(false);
chain.getFilterNames()
.remove(GeoServerSecurityFilterChain.SECURITY_CONTEXT_NO_ASC_FILTER);
}
// prepare web chain
if (GeoServerSecurityFilterChain.WEB_CHAIN_NAME.equals(chain.getName())) {
// replace exception translation filter
int index =
chain.getFilterNames()
.indexOf(
GeoServerSecurityFilterChain
.GUI_EXCEPTION_TRANSLATION_FILTER);
if (index != -1)
chain.getFilterNames()
.set(
index,
GeoServerSecurityFilterChain
.DYNAMIC_EXCEPTION_TRANSLATION_FILTER);
// inject form login filter if necessary
if (chain.getFilterNames().indexOf(GeoServerSecurityFilterChain.FORM_LOGIN_FILTER)
== -1) {
index =
chain.getFilterNames()
.indexOf(GeoServerSecurityFilterChain.ANONYMOUS_FILTER);
if (index == -1)
index =
chain.getFilterNames()
.indexOf(
GeoServerSecurityFilterChain
.FILTER_SECURITY_INTERCEPTOR);
if (index != -1)
chain.getFilterNames()
.add(index, GeoServerSecurityFilterChain.FORM_LOGIN_FILTER);
}
}
// remove dynamic translation filter
chain.getFilterNames()
.remove(GeoServerSecurityFilterChain.DYNAMIC_EXCEPTION_TRANSLATION_FILTER);
chain.getFilterNames().remove(GeoServerSecurityFilterChain.FILTER_SECURITY_INTERCEPTOR);
chain.getFilterNames()
.remove(GeoServerSecurityFilterChain.FILTER_SECURITY_REST_INTERCEPTOR);
}
// gui filter not needed any more
removeFilter(
loadFilterConfig(GeoServerSecurityFilterChain.GUI_EXCEPTION_TRANSLATION_FILTER));
saveSecurityConfig(config);
// load and store all filter configuration
// some filter configurations may have their class name as top level xml element in
// config.xml,
// the alias should be used instead, this was bug fixed during GSIP 82
if (!migratedFrom21) {
for (String fName : listFilters()) {
SecurityFilterConfig fConfig = loadFilterConfig(fName);
if (fConfig != null) saveFilter(fConfig);
}
}
return true;
}
初始为用户名和密码后,我们来看一下验证。geoserver使用spring的拦截器实现用户名密码登录。自定义拦截器bean配置在web目录下的core、src、main、java目录下的applicationContext中。我们来看一下配置文件。
<!-- login button -->
<bean id="geoserverFormLoginButton" class="org.geoserver.web.LoginFormInfo">
<property name="id" value="geoserverFormLoginButton" />
<property name="titleKey" value="login" />
<property name="descriptionKey" value="GeoServerBasePage.description" />
<property name="componentClass" value="org.geoserver.web.GeoServerBasePage" />
<property name="name" value="form" />
<property name="icon" value="img/icons/silk/door-in.png" />
<property name="filterClass" value="org.geoserver.security.filter.GeoServerUserNamePasswordAuthenticationFilter" />
<property name="include" value="include_login_form.html" />
<property name="loginPath" value="j_spring_security_check" />
</bean>
我们来看一下GeoServerUserNamePasswordAuthenticationFilter拦截器的定义。
public class GeoServerUserNamePasswordAuthenticationFilter extends GeoServerCompositeFilter
implements GeoServerAuthenticationFilter {
// public static final String URL_FOR_LOGIN = "/j_spring_security_check";
public static final String URL_LOGIN_SUCCCESS = "/web";
public static final String URL_LOGIN_FAILURE =
"/web/wicket/bookmarkable/org.geoserver.web.GeoServerLoginPage?error=true";
public static final String URL_LOGIN_FORM =
"/web/wicket/bookmarkable/org.geoserver.web.GeoServerLoginPage?error=false";
// public static final String URL_LOGIN_FORM="/admin/login.do";
private LoginUrlAuthenticationEntryPoint aep;
String[] pathInfos;
//https://www.cnblogs.com/lexiaofei/p/7018405.html?utm_source=itdadao&utm_medium=referral
@Override
public void initializeFromConfig(SecurityNamedServiceConfig config) throws IOException {
super.initializeFromConfig(config);
pathInfos = GeoServerSecurityFilterChain.FORM_LOGIN_CHAIN.split(",");
UsernamePasswordAuthenticationFilterConfig upConfig =
(UsernamePasswordAuthenticationFilterConfig) config;
aep = new LoginUrlAuthenticationEntryPoint(URL_LOGIN_FORM);
aep.setForceHttps(false);
try {
aep.afterPropertiesSet();
} catch (Exception e2) {
throw new IOException(e2);
}
RememberMeServices rms = securityManager.getRememberMeService();
// add login filter
UsernamePasswordAuthenticationFilter filter =
new UsernamePasswordAuthenticationFilter() {
@Override
protected boolean requiresAuthentication(
HttpServletRequest request, HttpServletResponse response) {
for (String pathInfo : pathInfos) {
if (getRequestPath(request).startsWith(pathInfo)) return true;
}
return false;
}
};
filter.setPasswordParameter(upConfig.getPasswordParameterName());
filter.setUsernameParameter(upConfig.getUsernameParameterName());
filter.setAuthenticationManager(getSecurityManager().authenticationManager());
filter.setRememberMeServices(rms);
GeoServerWebAuthenticationDetailsSource s = new GeoServerWebAuthenticationDetailsSource();
filter.setAuthenticationDetailsSource(s);
filter.setAllowSessionCreation(false);
// filter.setFilterProcessesUrl(URL_FOR_LOGIN);
SimpleUrlAuthenticationSuccessHandler successHandler =
new SimpleUrlAuthenticationSuccessHandler();
successHandler.setDefaultTargetUrl(URL_LOGIN_SUCCCESS);
filter.setAuthenticationSuccessHandler(successHandler);
SimpleUrlAuthenticationFailureHandler failureHandler =
new SimpleUrlAuthenticationFailureHandler();
// TODO, check this when using encrypting of URL parameters
failureHandler.setDefaultFailureUrl(URL_LOGIN_FAILURE);
filter.setAuthenticationFailureHandler(failureHandler);
// filter.afterPropertiesSet();
getNestedFilters().add(filter);
}
@Override
public AuthenticationEntryPoint getAuthenticationEntryPoint() {
return aep;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
req.setAttribute(GeoServerSecurityFilter.AUTHENTICATION_ENTRY_POINT_HEADER, aep);
super.doFilter(req, res, chain);
}
/** @see org.geoserver.security.filter.GeoServerAuthenticationFilter#applicableForHtml() */
@Override
public boolean applicableForHtml() {
return true;
}
/** @see org.geoserver.security.filter.GeoServerAuthenticationFilter#applicableForServices() */
@Override
public boolean applicableForServices() {
return false;
}
}
GeoServerUserNamePasswordAuthenticationFilter类实现了initializeFromConfig方法。配置了UsernamePasswordAuthenticationFilter相关参数,如setPasswordParameter设置密码参数、设置setUsernameParameter用户参数、设置认证管理类setAuthenticationManager、设置成功跳转setAuthenticationSuccessHandler等。
在上面的migrateFrom21方法中,最后还设置配置config,设置了用户名密码验证提供类。在用户名密码提供类UsernamePasswordAuthenticationProvider的实现接口中有配置config参数,利用该参数获取admin用户名的验证实例UserDetailsService。该UserDetailsService是我们在migrateFrom21方法中创建好的,UsernamePasswordAuthenticationProvider的成员变量DaoAuthenticationProvider利用setUserDetailsService方法设置该正确验证实例。
好了,做好了前期的创建正确UserDetailsService和获取前台接收的用户名和密码后,利用Spring Security中的相关类对用户进行验证。
更多内容,请关注公众号
转载自:https://blog.csdn.net/u010608964/article/details/84344748