in plugin-core/plugin/src/main/groovy/grails/plugin/springsecurity/SpringSecurityCoreGrailsPlugin.groovy [169:623]
Closure doWithSpring() {{ ->
ReflectionUtils.application = SpringSecurityUtils.application = grailsApplication
SpringSecurityUtils.resetSecurityConfig()
ConfigObject conf = SpringSecurityUtils.securityConfig
boolean printStatusMessages = (conf.printStatusMessages instanceof Boolean) ? conf.printStatusMessages : true
if (!conf || !conf.active) {
if (printStatusMessages) {
String message = '\n\nSpring Security is disabled, not loading\n\n'
log.info message
println message
}
return
}
log.trace 'doWithSpring'
if (printStatusMessages) {
String message = '\nConfiguring Spring Security Core ...'
log.info message
println message
}
if (log.traceEnabled) {
def sb = new StringBuilder('Spring Security configuration:\n')
def flatConf = conf.flatten()
for (key in flatConf.keySet().sort()) {
def value = flatConf[key]
sb << '\t' << key << ': '
if (value instanceof Closure) {
sb << '(closure)'
}
else {
try {
sb << value.toString() // eagerly convert to string to catch individual exceptions
}
catch (e) {
sb << '(an error occurred: ' << e.message << ')'
}
}
sb << '\n'
}
log.trace sb.toString()
}
Class beanTypeResolverClass = conf.beanTypeResolverClass ?: BeanTypeResolver
beanTypeResolver = beanTypeResolverClass.newInstance(conf, grailsApplication)
springSecurityBeanFactoryPostProcessor(classFor('springSecurityBeanFactoryPostProcessor', SpringSecurityBeanFactoryPostProcessor))
// configure the filter and optionally the listener
springSecurityFilterChainRegistrationBean(classFor('springSecurityFilterChainRegistrationBean', FilterRegistrationBean)) {
filter = ref('springSecurityFilterChain')
urlPatterns = ['/*']
dispatcherTypes = EnumSet.of(DispatcherType.ERROR, DispatcherType.REQUEST)
order = SecurityProperties.DEFAULT_FILTER_ORDER
}
if (conf.useHttpSessionEventPublisher) {
log.trace 'Configuring HttpSessionEventPublisher'
httpSessionEventPublisher(classFor('httpSessionEventPublisher', ServletListenerRegistrationBean), new HttpSessionEventPublisher())
}
createRefList.delegate = delegate
/** springSecurityFilterChain */
configureFilterChain.delegate = delegate
configureFilterChain conf
// securityRequestHolderFilter
securityRequestHolderFilter(classFor('securityRequestHolderFilter', SecurityRequestHolderFilter)) {
useHeaderCheckChannelSecurity = conf.secureChannel.useHeaderCheckChannelSecurity
secureHeaderName = conf.secureChannel.secureHeaderName // 'X-Forwarded-Proto'
secureHeaderValue = conf.secureChannel.secureHeaderValue // 'http'
insecureHeaderName = conf.secureChannel.insecureHeaderName // 'X-Forwarded-Proto'
insecureHeaderValue = conf.secureChannel.insecureHeaderValue // 'https'
portMapper = ref('portMapper')
portResolver = ref('portResolver')
}
// logout
configureLogout.delegate = delegate
configureLogout conf
/** securityContextRepository */
securityContextRepository(classFor('securityContextRepository', HttpSessionSecurityContextRepository)) {
allowSessionCreation = conf.scr.allowSessionCreation // true
disableUrlRewriting = conf.scr.disableUrlRewriting // true
springSecurityContextKey = conf.scr.springSecurityContextKey // SPRING_SECURITY_CONTEXT
trustResolver = ref('authenticationTrustResolver')
}
/** securityContextPersistenceFilter */
securityContextPersistenceFilter(classFor('securityContextPersistenceFilter', SecurityContextPersistenceFilter), ref('securityContextRepository')) {
forceEagerSessionCreation = conf.scpf.forceEagerSessionCreation // false
}
/** authenticationProcessingFilter */
configureAuthenticationProcessingFilter.delegate = delegate
configureAuthenticationProcessingFilter conf
/** securityContextHolderAwareRequestFilter */
securityContextHolderAwareRequestFilter(classFor('securityContextHolderAwareRequestFilter', SecurityContextHolderAwareRequestFilter)) {
authenticationEntryPoint = ref('authenticationEntryPoint')
authenticationManager = ref('authenticationManager')
logoutHandlers = ref('logoutHandlers')
trustResolver = ref('authenticationTrustResolver')
}
/** rememberMeAuthenticationFilter */
rememberMeAuthenticationFilter(classFor('rememberMeAuthenticationFilter', GrailsRememberMeAuthenticationFilter),
ref('authenticationManager'), ref('rememberMeServices'), ref('requestCache')) {
authenticationSuccessHandler = ref('authenticationSuccessHandler')
createSessionOnSuccess = conf.rememberMe.createSessionOnSuccess // true
}
userDetailsChecker(classFor('userDetailsChecker', AccountStatusUserDetailsChecker))
authoritiesMapper(classFor('authoritiesMapper', RoleHierarchyAuthoritiesMapper), ref('roleHierarchy'))
/** rememberMeServices */
if (conf.rememberMe.persistent) {
log.trace 'Configuring persistent remember-me'
rememberMeServices(classFor('rememberMeServices', PersistentTokenBasedRememberMeServices),
conf.rememberMe.key, ref('userDetailsService'), ref('tokenRepository')) {
cookieName = conf.rememberMe.cookieName
if (conf.rememberMe.cookieDomain) {
cookieDomain = conf.rememberMe.cookieDomain
}
alwaysRemember = conf.rememberMe.alwaysRemember
tokenValiditySeconds = conf.rememberMe.tokenValiditySeconds
parameter = conf.rememberMe.parameter
if (conf.rememberMe.useSecureCookie instanceof Boolean) {
useSecureCookie = conf.rememberMe.useSecureCookie // null
}
authenticationDetailsSource = ref('authenticationDetailsSource')
userDetailsChecker = ref('userDetailsChecker')
authoritiesMapper = ref('authoritiesMapper')
seriesLength = conf.rememberMe.persistentToken.seriesLength // 16
tokenLength = conf.rememberMe.persistentToken.tokenLength // 16
}
tokenRepository(classFor('tokenRepository', GormPersistentTokenRepository))
}
else {
log.trace 'Configuring non-persistent remember-me'
rememberMeServices(classFor('rememberMeServices', TokenBasedRememberMeServices), conf.rememberMe.key, ref('userDetailsService')) {
cookieName = conf.rememberMe.cookieName
if (conf.rememberMe.cookieDomain) {
cookieDomain = conf.rememberMe.cookieDomain
}
alwaysRemember = conf.rememberMe.alwaysRemember
tokenValiditySeconds = conf.rememberMe.tokenValiditySeconds
parameter = conf.rememberMe.parameter
if (conf.rememberMe.useSecureCookie instanceof Boolean) {
useSecureCookie = conf.rememberMe.useSecureCookie // null
}
authenticationDetailsSource = ref('authenticationDetailsSource')
userDetailsChecker = ref('userDetailsChecker')
authoritiesMapper = ref('authoritiesMapper')
}
// register a lightweight impl so there's a bean in either case
tokenRepository(classFor('tokenRepository', InMemoryTokenRepositoryImpl))
}
/** anonymousAuthenticationFilter */
anonymousAuthenticationFilter(classFor('anonymousAuthenticationFilter', GrailsAnonymousAuthenticationFilter)) {
authenticationDetailsSource = ref('authenticationDetailsSource')
key = conf.anon.key
}
throwableAnalyzer(classFor('throwableAnalyzer', DefaultThrowableAnalyzer))
/** exceptionTranslationFilter */
exceptionTranslationFilter(classFor('exceptionTranslationFilter', UpdateRequestContextHolderExceptionTranslationFilter),
ref('authenticationEntryPoint'), ref('requestCache')) {
accessDeniedHandler = ref('accessDeniedHandler')
authenticationTrustResolver = ref('authenticationTrustResolver')
throwableAnalyzer = ref('throwableAnalyzer')
}
accessDeniedHandler(classFor('accessDeniedHandler', AjaxAwareAccessDeniedHandler)) {
errorPage = conf.adh.errorPage == 'null' ? null : conf.adh.errorPage // '/login/denied' or 403
ajaxErrorPage = conf.adh.ajaxErrorPage
useForward = conf.adh.useForward
portResolver = ref('portResolver')
authenticationTrustResolver = ref('authenticationTrustResolver')
requestCache = ref('requestCache')
}
/** authenticationTrustResolver */
authenticationTrustResolver(classFor('authenticationTrustResolver', AuthenticationTrustResolverImpl)) {
anonymousClass = conf.atr.anonymousClass
rememberMeClass = conf.atr.rememberMeClass
}
// default 'authenticationEntryPoint'
authenticationEntryPoint(classFor('authenticationEntryPoint', AjaxAwareAuthenticationEntryPoint), conf.auth.loginFormUrl) { // '/login/auth'
ajaxLoginFormUrl = conf.auth.ajaxLoginFormUrl // '/login/authAjax'
forceHttps = conf.auth.forceHttps // false
useForward = conf.auth.useForward // false
portMapper = ref('portMapper')
portResolver = ref('portResolver')
redirectStrategy = ref('redirectStrategy')
}
/** filterInvocationInterceptor */
// TODO doc new
if (conf.afterInvocationManagerProviderNames) {
log.trace 'Configuring AfterInvocationProviderManager'
afterInvocationManager(classFor('afterInvocationManager', AfterInvocationProviderManager)) {
providers = [new NullAfterInvocationProvider()] // will be replaced in doWithApplicationContext
}
}
else {
// register a lightweight impl so there's a bean in either case
afterInvocationManager(classFor('afterInvocationManager', NullAfterInvocationManager))
}
filterInvocationInterceptor(classFor('filterInvocationInterceptor', FilterSecurityInterceptor)) {
authenticationManager = ref('authenticationManager')
accessDecisionManager = ref('accessDecisionManager')
securityMetadataSource = ref('objectDefinitionSource')
runAsManager = ref('runAsManager')
afterInvocationManager = ref('afterInvocationManager')
alwaysReauthenticate = conf.fii.alwaysReauthenticate // false
rejectPublicInvocations = conf.fii.rejectPublicInvocations // true
validateConfigAttributes = conf.fii.validateConfigAttributes // true
publishAuthorizationSuccess = conf.fii.publishAuthorizationSuccess // false
observeOncePerRequest = conf.fii.observeOncePerRequest // true
}
String securityConfigType = SpringSecurityUtils.securityConfigType
log.trace "Using security config type '{}'", securityConfigType
if (securityConfigType != 'Annotation' &&
securityConfigType != 'Requestmap' &&
securityConfigType != 'InterceptUrlMap') {
String message = """
ERROR: the 'securityConfigType' property must be one of
'Annotation', 'Requestmap', or 'InterceptUrlMap' or left unspecified
to default to 'Annotation'; setting value to 'Annotation'
"""
println message
log.warn message
securityConfigType = 'Annotation'
}
httpServletResponseExtension(classFor('httpServletResponseExtension', HttpServletResponseExtension)) // used to be responseMimeTypesApi
if (securityConfigType == 'Annotation') {
objectDefinitionSource(classFor('objectDefinitionSource', AnnotationFilterInvocationDefinition)) {
application = grailsApplication
grailsUrlConverter = ref('grailsUrlConverter')
httpServletResponseExtension = ref('httpServletResponseExtension')
if (conf.rejectIfNoRule instanceof Boolean) {
rejectIfNoRule = conf.rejectIfNoRule
}
}
}
else if (securityConfigType == 'Requestmap') {
objectDefinitionSource(classFor('objectDefinitionSource', RequestmapFilterInvocationDefinition)) {
if (conf.rejectIfNoRule instanceof Boolean) {
rejectIfNoRule = conf.rejectIfNoRule
}
}
}
else if (securityConfigType == 'InterceptUrlMap') {
objectDefinitionSource(classFor('objectDefinitionSource', InterceptUrlMapFilterInvocationDefinition)) {
if (conf.rejectIfNoRule instanceof Boolean) {
rejectIfNoRule = conf.rejectIfNoRule
}
}
}
webInvocationPrivilegeEvaluator(classFor('webInvocationPrivilegeEvaluator', GrailsWebInvocationPrivilegeEvaluator), ref('filterInvocationInterceptor'))
// voters
configureVoters.delegate = delegate
configureVoters conf
/** anonymousAuthenticationProvider */
anonymousAuthenticationProvider(classFor('anonymousAuthenticationProvider', GrailsAnonymousAuthenticationProvider))
/** rememberMeAuthenticationProvider */
rememberMeAuthenticationProvider(classFor('rememberMeAuthenticationProvider', RememberMeAuthenticationProvider), conf.rememberMe.key)
// authenticationManager
configureAuthenticationManager.delegate = delegate
configureAuthenticationManager conf
/** daoAuthenticationProvider */
preAuthenticationChecks(classFor('preAuthenticationChecks', DefaultPreAuthenticationChecks))
postAuthenticationChecks(classFor('postAuthenticationChecks', DefaultPostAuthenticationChecks))
daoAuthenticationProvider(classFor('daoAuthenticationProvider', DaoAuthenticationProvider)) {
userDetailsService = ref('userDetailsService')
passwordEncoder = ref('passwordEncoder')
userCache = ref('userCache')
preAuthenticationChecks = ref('preAuthenticationChecks')
postAuthenticationChecks = ref('postAuthenticationChecks')
authoritiesMapper = ref('authoritiesMapper')
hideUserNotFoundExceptions = conf.dao.hideUserNotFoundExceptions // true
}
/** passwordEncoder */
String algorithm = conf.password.algorithm
log.trace 'Using {} algorithm', algorithm
passwordEncoder(classFor('passwordEncoder', DelegatingPasswordEncoder), algorithm, idToPasswordEncoder(conf))
/** userDetailsService */
userDetailsService(classFor('userDetailsService', GormUserDetailsService)) {
grailsApplication = grailsApplication
}
/** authenticationUserDetailsService */
authenticationUserDetailsService(classFor('authenticationUserDetailsService', UserDetailsByNameServiceWrapper), ref('userDetailsService'))
// port mappings for channel security, etc.
portMapper(classFor('portMapper', PortMapperImpl)) {
portMappings = [(conf.portMapper.httpPort.toString()) : conf.portMapper.httpsPort.toString()] // 8080, 8443
}
portResolver(classFor('portResolver', PortResolverImpl)) {
portMapper = ref('portMapper')
}
// SecurityEventListener
if (conf.useSecurityEventListener) {
log.trace 'Configuring SecurityEventListener'
securityEventListener(classFor('authenticationEventPublisher', SecurityEventListener))
authenticationEventPublisher(classFor('authenticationEventPublisher', DefaultAuthenticationEventPublisher)) {
additionalExceptionMappings =
([(NoStackUsernameNotFoundException.name): AuthenticationFailureBadCredentialsEvent.name] as Properties)
}
}
else {
authenticationEventPublisher(classFor('authenticationEventPublisher', NullAuthenticationEventPublisher))
}
// Basic Auth
if (conf.useBasicAuth) {
log.trace 'Configuring Basic auth'
configureBasicAuth.delegate = delegate
configureBasicAuth conf
}
// Digest Auth
if (conf.useDigestAuth) {
log.trace 'Configuring Digest auth'
configureDigestAuth.delegate = delegate
configureDigestAuth conf
}
// Switch User
if (conf.useSwitchUserFilter) {
log.trace 'Configuring SwitchUserFilter'
// TODO doc new
switchUserAuthorityChanger(classFor('switchUserAuthorityChanger', NullSwitchUserAuthorityChanger))
switchUserProcessingFilter(classFor('switchUserProcessingFilter', SwitchUserFilter)) {
userDetailsService = ref('userDetailsService')
userDetailsChecker = ref('userDetailsChecker')
authenticationDetailsSource = ref('authenticationDetailsSource')
switchUserAuthorityChanger = ref('switchUserAuthorityChanger')
switchUserUrl = conf.switchUser.switchUserUrl // '/login/impersonate'
exitUserUrl = conf.switchUser.exitUserUrl // '/logout/impersonate'
usernameParameter = conf.switchUser.usernameParameter // 'username'
if (conf.switchUser.targetUrl) {
targetUrl = conf.switchUser.targetUrl
}
else {
successHandler = ref('authenticationSuccessHandler')
}
if (conf.switchUser.switchFailureUrl) {
switchFailureUrl = conf.switchUser.switchFailureUrl
}
else {
failureHandler = ref('authenticationFailureHandler')
}
if (conf.switchUser.switchUserMatcher) {
switchUserMatcher = conf.switchUser.switchUserMatcher
}
if (conf.switchUser.exitUserMatcher) {
exitUserMatcher = conf.switchUser.exitUserMatcher
}
}
}
// per-method run-as, defined here so it can be overridden
runAsManager(classFor('runAsManager', NullRunAsManager))
// X.509
if (conf.useX509) {
log.trace 'Configuring X.509'
configureX509.delegate = delegate
configureX509 conf
}
// channel (http/https) security
if (conf.secureChannel.definition) {
log.trace 'Configuring channel security'
configureChannelProcessingFilter.delegate = delegate
configureChannelProcessingFilter conf
}
// IP filter
if (conf.ipRestrictions) {
log.trace 'Configuring IP restrictions'
configureIpFilter.delegate = delegate
configureIpFilter conf
}
// user details cache
if (conf.cacheUsers) {
log.trace 'Configuring user cache'
userCache(classFor('userCache', SpringUserCacheFactoryBean)) {
cacheManager = ref('cacheManager')
cacheName = 'userCache'
}
cacheManager(classFor('cacheManager', JCacheCacheManager))
}
else {
userCache(classFor('userCache', NullUserCache))
}
/** loggerListener */
if (conf.registerLoggerListener) {
log.trace 'Register LoggerListener'
loggerListener(classFor('loggerListener', LoggerListener))
}
if (conf.debug.useFilter) {
log.trace 'Register DebugFilter'
securityDebugFilter(classFor('securityDebugFilter', DebugFilter), ref('springSecurityFilterChain'))
}
permissionEvaluator(classFor('permissionEvaluator', DenyAllPermissionEvaluator))
if (printStatusMessages) {
String message = '... finished configuring Spring Security Core\n'
log.info message
println message
}
formContentFilter(classFor('formContentFilter', FormContentFilter))
}}