我让jenkins配置了openID插件进行身份验证。我使用配置了LDAP服务器的CAS来匹配用户ID和openid。验证成功后,我在验证后将CAS重定向回jenkins页面时收到错误。
我附上了完整的堆栈跟踪供您参考。
此致 J Shai
javax.servlet.ServletException: org.openid4java.message.MessageException: 0x100: Required parameter missing: openid.mode
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:796)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:876)
at org.kohsuke.stapler.MetaClass$4.doDispatch(MetaClass.java:211)
at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:53)
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:746)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:876)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:649)
at org.kohsuke.stapler.Stapler.service(Stapler.java:238)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:686)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1494)
at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:96)
at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:88)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:48)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:51)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at jenkins.security.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:117)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:142)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at jenkins.security.BasicHeaderProcessor.doFilter(BasicHeaderProcessor.java:93)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
at hudson.security.HttpSessionContextIntegrationFilter2.doFilter(HttpSessionContextIntegrationFilter2.java:67)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:76)
at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:164)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
at org.kohsuke.stapler.compression.CompressionFilter.doFilter(CompressionFilter.java:46)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:81)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
at org.kohsuke.stapler.DiagnosticThreadNameFilter.doFilter(DiagnosticThreadNameFilter.java:30)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1474)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:499)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:533)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:370)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)
at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:949)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1011)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:644)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:668)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at winstone.BoundedExecutorService$1.run(BoundedExecutorService.java:77)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.openid4java.message.MessageException: 0x100: Required parameter missing: openid.mode
at org.openid4java.message.Message.validate(Message.java:187)
at org.openid4java.message.AuthSuccess.validate(AuthSuccess.java:405)
at org.openid4java.message.AuthSuccess.createAuthSuccess(AuthSuccess.java:118)
at org.openid4java.consumer.ConsumerManager.verify(ConsumerManager.java:1142)
at hudson.plugins.openid.OpenIdSession.doFinishLogin(OpenIdSession.java:111)
at hudson.plugins.openid.OpenIdSsoSecurityRealm.doFinishLogin(OpenIdSsoSecurityRealm.java:210)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.kohsuke.stapler.Function$InstanceFunction.invoke(Function.java:298)
at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:161)
at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:96)
at org.kohsuke.stapler.MetaClass$1.doDispatch(MetaClass.java:121)
at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:53)
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:746)
... 63 more
在此处附加我的login-webflow.xml以供参考
<?xml version="1.0" encoding="UTF-8"?>
<!-- Licensed to Jasig under one or more contributor license agreements. See the NOTICE file distributed with this work for
additional information regarding copyright ownership. Jasig licenses this file to you 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
the following location: 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. -->
<flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<var name="credential" class="org.jasig.cas.authentication.UsernamePasswordCredential" />
<on-start>
<evaluate expression="initialFlowSetupAction" />
</on-start>
<!-- If the request contains a parameter called openid.mode and is not an association request, switch to openId. Otherwise,
continue normal webflow. -->
<decision-state id="selectFirstAction">
<if
test="externalContext.requestParameterMap['openid.mode'] neq ''
&& externalContext.requestParameterMap['openid.mode'] neq null
&& externalContext.requestParameterMap['openid.mode'] neq 'associate'"
then="openIdSingleSignOnAction" else="ticketGrantingTicketExistsCheck" />
</decision-state>
<decision-state id="ticketGrantingTicketExistsCheck">
<if test="flowScope.ticketGrantingTicketId != null" then="hasServiceCheck" else="gatewayRequestCheck" />
</decision-state>
<!-- The OpenID authentication action. If authentication is successful, send the ticket granting ticker. Otherwise, redirect
to the login form. -->
<action-state id="openIdSingleSignOnAction">
<evaluate expression="openIdSingleSignOnAction" />
<transition on="success" to="sendTicketGrantingTicket" />
<transition on="error" to="viewLoginForm" />
<transition on="warn" to="warn" />
</action-state>
<action-state id="ticketGrantingTicketCheck">
<evaluate expression="ticketGrantingTicketCheckAction.checkValidity(flowRequestContext)" />
<transition on="notExists" to="gatewayRequestCheck" />
<transition on="invalid" to="terminateSession" />
<transition on="valid" to="hasServiceCheck" />
</action-state>
<action-state id="terminateSession">
<evaluate expression="terminateSessionAction.terminate(flowRequestContext)" />
<transition to="generateLoginTicket" />
</action-state>
<decision-state id="gatewayRequestCheck">
<if test="requestParameters.gateway != '' and requestParameters.gateway != null and flowScope.service != null"
then="gatewayServicesManagementCheck" else="serviceAuthorizationCheck" />
</decision-state>
<decision-state id="hasServiceCheck">
<if test="flowScope.service != null" then="renewRequestCheck" else="viewGenericLoginSuccess" />
</decision-state>
<decision-state id="renewRequestCheck">
<if test="requestParameters.renew != '' and requestParameters.renew != null" then="serviceAuthorizationCheck"
else="generateServiceTicket" />
</decision-state>
<!-- Do a service authorization check early without the need to login first -->
<action-state id="serviceAuthorizationCheck">
<evaluate expression="serviceAuthorizationCheck" />
<transition to="generateLoginTicket" />
</action-state>
<!-- The "warn" action makes the determination of whether to redirect directly to the requested service or display the
"confirmation" page to go back to the server. -->
<decision-state id="warn">
<if test="flowScope.warnCookieValue" then="showWarningView" else="redirect" />
</decision-state>
<!-- <action-state id="startAuthenticate"> <action bean="x509Check" /> <transition on="success" to="sendTicketGrantingTicket"
/> <transition on="warn" to="warn" /> <transition on="error" to="generateLoginTicket" /> </action-state> -->
<action-state id="generateLoginTicket">
<evaluate expression="generateLoginTicketAction.generate(flowRequestContext)" />
<transition on="generated" to="viewLoginForm" />
</action-state>
<view-state id="viewLoginForm" view="casLoginView" model="credential">
<binder>
<binding property="username" />
<binding property="password" />
</binder>
<on-entry>
<set name="viewScope.commandName" value="'credential'" />
</on-entry>
<transition on="submit" bind="true" validate="true" to="realSubmit">
<evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credential)" />
</transition>
</view-state>
<action-state id="realSubmit">
<evaluate expression="authenticationViaFormAction.submit(flowRequestContext, flowScope.credential, messageContext)" />
<transition on="warn" to="warn" />
<transition on="success" to="sendTicketGrantingTicket" />
<transition on="successWithWarnings" to="showMessages" />
<transition on="authenticationFailure" to="handleAuthenticationFailure" />
<transition on="error" to="generateLoginTicket" />
</action-state>
<view-state id="showMessages" view="casLoginMessageView">
<on-entry>
<evaluate expression="sendTicketGrantingTicketAction" />
<set name="requestScope.messages" value="messageContext.allMessages" />
</on-entry>
<transition on="proceed" to="serviceCheck" />
</view-state>
<action-state id="handleAuthenticationFailure">
<evaluate expression="authenticationExceptionHandler.handle(currentEvent.attributes.error, messageContext)" />
<transition on="AccountDisabledException" to="casAccountDisabledView" />
<transition on="AccountLockedException" to="casAccountLockedView" />
<transition on="CredentialExpiredException" to="casExpiredPassView" />
<transition on="InvalidLoginLocationException" to="casBadWorkstationView" />
<transition on="InvalidLoginTimeException" to="casBadHoursView" />
<transition on="FailedLoginException" to="generateLoginTicket" />
<transition on="AccountNotFoundException" to="generateLoginTicket" />
<transition on="UNKNOWN" to="generateLoginTicket" />
</action-state>
<action-state id="sendTicketGrantingTicket">
<evaluate expression="sendTicketGrantingTicketAction" />
<transition to="serviceCheck" />
</action-state>
<decision-state id="serviceCheck">
<if test="flowScope.service != null" then="generateServiceTicket" else="viewGenericLoginSuccess" />
</decision-state>
<action-state id="generateServiceTicket">
<evaluate expression="generateServiceTicketAction" />
<transition on="success" to="warn" />
<transition on="authenticationFailure" to="handleAuthenticationFailure" />
<transition on="error" to="generateLoginTicket" />
<transition on="gateway" to="gatewayServicesManagementCheck" />
</action-state>
<action-state id="gatewayServicesManagementCheck">
<evaluate expression="gatewayServicesManagementCheck" />
<transition on="success" to="redirect" />
</action-state>
<action-state id="redirect">
<evaluate expression="flowScope.service.getResponse(requestScope.serviceTicketId)" result-type="org.jasig.cas.authentication.principal.Response"
result="requestScope.response" />
<transition to="postRedirectDecision" />
</action-state>
<decision-state id="postRedirectDecision">
<if test="requestScope.response.responseType.name() == 'POST'" then="postView" else="redirectView" />
</decision-state>
<!-- the "viewGenericLogin" is the end state for when a user attempts to login without coming directly from a service.
They have only initialized their single-sign on session. -->
<end-state id="viewGenericLoginSuccess" view="casLoginGenericSuccessView" />
<!-- The "showWarningView" end state is the end state for when the user has requested privacy settings (to be "warned")
to be turned on. It delegates to a view defines in default_views.properties that display the "Please click here to go to
the service." message. -->
<end-state id="showWarningView" view="casLoginConfirmView" />
<!-- Password policy failure states -->
<end-state id="abstactPasswordChangeView">
<on-entry>
<set name="flowScope.passwordPolicyUrl" value="passwordPolicy.passwordPolicyUrl" />
</on-entry>
</end-state>
<end-state id="casExpiredPassView" view="casExpiredPassView" parent="#abstactPasswordChangeView" />
<end-state id="casMustChangePassView" view="casMustChangePassView" parent="#abstactPasswordChangeView" />
<end-state id="casAccountDisabledView" view="casAccountDisabledView" />
<end-state id="casAccountLockedView" view="casAccountLockedView" />
<end-state id="casBadHoursView" view="casBadHoursView" />
<end-state id="casBadWorkstationView" view="casBadWorkstationView" />
<end-state id="postView" view="postResponseView">
<on-entry>
<set name="requestScope.parameters" value="requestScope.response.attributes" />
<set name="requestScope.originalUrl" value="flowScope.service.id" />
</on-entry>
</end-state>
<!-- The "redirect" end state allows CAS to properly end the workflow while still redirecting the user back to the service
required. -->
<end-state id="redirectView" view="externalRedirect:${requestScope.response.url}" />
<end-state id="viewServiceErrorView" view="viewServiceErrorView" />
<end-state id="viewServiceSsoErrorView" view="viewServiceSsoErrorView" />
<global-transitions>
<!-- CAS-1023 This one is simple - redirects to a login page (same as renew) when 'ssoEnabled' flag is unchecked instead
of showing an intermediate unauthorized view with a link to login page -->
<transition to="viewLoginForm" on-exception="org.jasig.cas.services.UnauthorizedSsoServiceException" />
<transition to="viewServiceErrorView" on-exception="org.springframework.webflow.execution.repository.NoSuchFlowExecutionException" />
<transition to="viewServiceErrorView" on-exception="org.jasig.cas.services.UnauthorizedServiceException" />
</global-transitions>
</flow>
答案 0 :(得分:0)
这已经解决了。
事实证明,没有形成URL来提取参数,因为缺少opEnpointUrl的applicationContext.xml中的spring配置。
<bean id="serverManager" class="org.openid4java.server.ServerManager"
p:oPEndpointUrl="${cas.securityContext.casProcessingFilterEntryPoint.loginUrl}"
p:enforceRpId="false" />