我有几个Grails应用程序在生产中运行,并通过spring-security和“Grails CAS插件”与CAS服务器(CAS 3.3.5)连接。这些应用程序由版本1.3.7到2.2.4的各种版本的Grails支持
我正在将其中一个移至2.4.4,我从未结束身份验证问题。在练习结束时,我有臭名昭着的说法:“这个网页有一个重定向循环”(在Chrome中)。在服务器端,我有通常的(!)错误:
ERROR [org.jasig.cas.web.ServiceValidateController] - <TicketException
generating ticket for: [callbackUrl:
https://casclient.mydomain.com:9043/testCas/secure/receptor]>
org.jasig.cas.ticket.InvalidTicketException
at org.jasig.cas.CentralAuthenticationServiceImpl.delegateTicketGrantingTicket(CentralAuthenticationServiceImpl.java:268)
以下是我为重现问题所采取的所有步骤:
grails create-app testCas
grails create-controller showSecure
在控制器中添加动作showSecurePage grails generate-views
将此添加到UrlMappings
class UrlMappings {
static mappings = {
"/showSecure" {
controller = "showSecure"
action = [ GET: "showSecurePage" ]
}
"/"(view:"/index")
"500"(view:'/error')
}
}
此时如果我启动应用程序,我可以毫无问题地访问“showSecurePage”页面。让我们继续并安装“CAS插件”。
在BuildConfig.groovy的“插件”片段中添加字符串:
compile ":spring-security-core:2.0-RC4"
compile ":spring-security-cas:2.0-RC1"
和“dependencies”片段:
mavenRepo 'http://repo.spring.io/milestone'
执行grails clean
和grails compile
。
运行:grails s2-quickstart testCas User Role
Config.groovy
已修改,必须“调整”。
由于我们不使用注释,因此我将s2-quickstart(staticRules)添加的条目替换为:
grails.plugin.springsecurity.rejectIfNoRule = true
grails.plugin.springsecurity.securityConfigType = "InterceptUrlMap"
grails.plugin.springsecurity.interceptUrlMap = [
'/': ['permitAll'],
'/index': ['permitAll'],
'/index.gsp': ['permitAll'],
'/**/js/**': ['permitAll'],
'/**/css/**': ['permitAll'],
'/**/images/**': ['permitAll'],
'/**/favicon.ico': ['permitAll'],
'/login/**': ['permitAll'],
'/logout/**': ['permitAll'],
'/secure/receptor': ['permitAll'],
'/showSecure/**': ['isFullyAuthenticated()'],
'/finance/**': ['ROLE_FINANCE', 'isFullyAuthenticated()']
]
注意:我按照19710841
中的说明将“permitAll”添加到“/ secure / receptor”最后我们添加了CAS配置。如文档中所述,必须定义所有列出的参数:
grails.serverURL = "http://casclient.mydomain.com:9080/testCas"
grails.serverSecureURL = "https://casclient.mydomain.com:9043/testCas"
grails.plugin.springsecurity.useCAS = true
grails.plugin.springsecurity.cas.active = true
grails.plugin.springsecurity.cas.serverUrlPrefix = 'https://casserver.mydomain.com:10443/sso'
grails.plugin.springsecurity.cas.serverUrlEncoding = 'UTF-8'
grails.plugin.springsecurity.cas.loginUri = '/login'
grails.plugin.springsecurity.cas.sendRenew = false
grails.plugin.springsecurity.cas.serviceUrl = "${grails.serverURL}/secure/security_check"
grails.plugin.springsecurity.cas.key ='authentication_provider'
grails.plugin.springsecurity.cas.artifactParameter = 'ticket'
grails.plugin.springsecurity.cas.serviceParameter = 'service'
grails.plugin.springsecurity.cas.filterProcessesUrl = '/secure/security_check'
grails.plugin.springsecurity.cas.proxyCallbackUrl = "${grails.serverSecureURL}/secure/receptor"
grails.plugin.springsecurity.cas.proxyReceptorUrl = '/secure/receptor'
grails.plugin.springsecurity.cas.useSingleSignOut = true
grails.plugin.springsecurity.logoutURL = "${grails.plugin.springsecurity.cas.serverUrlPrefix}/logout"
grails.plugin.springsecurity.logout.afterLogoutUrl = "${grails.plugin.springsecurity.cas.serverUrlPrefix}/logout?url=${grails.serverURL}"
注意:如果在grails.plugin.springsecurity.cas.proxyCallbackUrl
中我将链接定义为“http”而不是“https”,我将在CAS服务器端有一个循环,其中包含“错误凭据”消息。添加安全链接时,此错误消失。
现在访问安全页面,我看到了常用的CAS登录信息。如果我正确登录,我会在CAS日志中看到“重定向循环”错误:
-------------------------2015-03-31 13:33:33,736 ERROR
[org.jasig.cas.web.ServiceValidateController] - <TicketException
generating ticket for: [callbackUrl:
https://casclient.mydomain.com:9043/testCas/secure/receptor]>
org.jasig.cas.ticket.InvalidTicketException
at org.jasig.cas.CentralAuthenticationServiceImpl.delegateTicketGrantingTicket(CentralAuthenticationServiceImpl.java:268)
at org.jasig.cas.web.ServiceValidateController.handleRequestInternal(ServiceValidateController.java:126)
编辑:更多信息。 在启用各种调试的详细输出中,我意识到存在对ROLE_ANONYMOUS的连续引用。嫌疑人认为问题不是认证,而是授权。确实这是问题所在。如果我修改Config.groovy:
'/showSecure/**': ['ROLE_USER', 'isFullyAuthenticated()'],
我实现了在resources.groovy中定义的(现在)服务:
// Place your Spring DSL code here
beans = {
userDetailsService(EsoUserDetailsService)
}
问题消失了。 我有另外一个。 如果在EsoUserDetailsService中,我尝试以这种方式从数据库中检索角色:
User.withTransaction { status ->
User user = User.findByUsername(username)
if (!user) throw new UsernameNotFoundException('User not found', username)
def authorities = user.authorities.collect { new GrantedAuthorityImpl(it.authority)
}
return new EsoUserDetails(user.username, user.password, user.enabled,
!user.accountExpired, !user.passwordExpired, !user.accountLocked, authorities,
user.id, user.getUserRealName())
}
我有错误:
类[eso.phase3.rm.User]上的方法在Grails应用程序之外使用。如果使用模拟API或正确引导Grails在测试环境中运行。