Ups, that was beers :-)

2009/1/23 Borut Bolčina <borut.bolc...@gmail.com>

> 100 bears for Ulrich!
>
> It works. You made my day. Thanks,
>
> -Borut
>
> 2009/1/23 Ulrich Stärk <u...@spielviel.de>
>
> Hi Borut,
>>
>> the problem was that both the OpenIdProcessingFilter and the filter used
>> for form-based authentication both were configured for the same url, namely
>> spring-security.check.url. Therefore both filters tried to process the
>> credentials entered, which had to fail. I updated the wiki article.
>> Basically it's all about introducing a new symbol,
>> spring-security.openidcheck.url with the value
>> "/j_spring_openid_security_check" and configuring the login page and the
>> OpenId processing filter to use this instead of the
>> spring-security.check.url. Then you can have to forms on your login page,
>> one for openid login and the other for form-based logins and everything
>> should work.
>>
>>
>> Cheers,
>>
>> Uli
>>
>>
>> Borut Bolčina schrieb:
>>
>>> Sure!
>>>
>>> 2008/12/12 Ulrich Stärk <u...@spielviel.de>
>>>
>>>  Please give me some time to have a look, atm I'm busy writing a paper
>>>> for a
>>>> conference in january.
>>>>
>>>> Cheers,
>>>>
>>>> Uli
>>>>
>>>> Borut Bolčina schrieb:
>>>>
>>>>  Hello Ulrich,
>>>>
>>>>> I hope you don't mind me writing you directly. I am trying to implement
>>>>> OpenID and Username/Password authentication. I read your great article
>>>>> at
>>>>> T5
>>>>> wiki.
>>>>>
>>>>> My goal: authenticate via DaoAuthenticationProvider if user inputs
>>>>> username
>>>>> and password OR authenticate via OpenIDAuthenticationProvider if user
>>>>> enters
>>>>> openid url.
>>>>>
>>>>> The problem: OpenIDAuthenticationProvider is trying to authenticate
>>>>> eventhough it is contributed as second provider.
>>>>>
>>>>> Can you please have a look at the AppModule code and suggest a
>>>>> correction?
>>>>>
>>>>> AppModule.java
>>>>> ============
>>>>> import java.io.IOException;
>>>>>
>>>>> import
>>>>> nu.localhost.tapestry5.springsecurity.services.SpringSecurityServices;
>>>>> import
>>>>>
>>>>>
>>>>> nu.localhost.tapestry5.springsecurity.services.internal.HttpServletRequestFilterWrapper;
>>>>>
>>>>> import org.apache.tapestry5.SymbolConstants;
>>>>> import org.apache.tapestry5.ioc.MappedConfiguration;
>>>>> import org.apache.tapestry5.ioc.OrderedConfiguration;
>>>>> import org.apache.tapestry5.ioc.ServiceBinder;
>>>>> import org.apache.tapestry5.ioc.annotations.Inject;
>>>>> import org.apache.tapestry5.ioc.annotations.InjectService;
>>>>> import org.apache.tapestry5.ioc.annotations.Local;
>>>>> import org.apache.tapestry5.ioc.annotations.Value;
>>>>> import org.apache.tapestry5.services.HttpServletRequestFilter;
>>>>> import org.apache.tapestry5.services.Request;
>>>>> import org.apache.tapestry5.services.RequestFilter;
>>>>> import org.apache.tapestry5.services.RequestHandler;
>>>>> import org.apache.tapestry5.services.Response;
>>>>> import org.slf4j.Logger;
>>>>> import org.springframework.security.AuthenticationManager;
>>>>> import org.springframework.security.providers.AuthenticationProvider;
>>>>> import org.springframework.security.providers.dao.SaltSource;
>>>>> import org.springframework.security.providers.encoding.PasswordEncoder;
>>>>> import
>>>>>
>>>>>
>>>>> org.springframework.security.providers.openid.OpenIDAuthenticationProvider;
>>>>> import
>>>>>
>>>>>
>>>>> org.springframework.security.ui.openid.OpenIDAuthenticationProcessingFilter;
>>>>> import org.springframework.security.ui.rememberme.RememberMeServices;
>>>>> import org.springframework.security.userdetails.UserDetailsService;
>>>>>
>>>>> /**
>>>>>  * This module is automatically included as part of the Tapestry IoC
>>>>> Registry, it's a good place to configure and extend
>>>>>  * Tapestry, or to place your own service definitions.
>>>>>  */
>>>>> public class AppModule {
>>>>>   public static void bind(ServiceBinder binder) {
>>>>>       binder.bind(PersistenceManager.class,
>>>>> PersistenceManagerImpl.class);
>>>>>   }
>>>>>
>>>>>   public static void
>>>>> contributeApplicationDefaults(MappedConfiguration<String, String>
>>>>> configuration) {
>>>>>       configuration.add(SymbolConstants.SUPPORTED_LOCALES,
>>>>> "sl_SI,sr,en");
>>>>>
>>>>>       // The factory default is true but during the early stages of an
>>>>> application
>>>>>       // overriding to false is a good idea. In addition, this is often
>>>>> overridden
>>>>>       // on the command line as -Dtapestry.production-mode=false
>>>>>       configuration.add(SymbolConstants.PRODUCTION_MODE, "false");
>>>>>       configuration.add(SymbolConstants.COMPRESS_WHITESPACE, "false");
>>>>>
>>>>>       configuration.add("spring-security.failure.url",
>>>>> "/login/failed");
>>>>>       // configuration.add( "spring-security.accessDenied.url",
>>>>> "/forbidden" );
>>>>>       // configuration.add(
>>>>>       // "spring-security.check.url",
>>>>>       // "/j_spring_security_check" );
>>>>>       configuration.add("spring-security.target.url", "/index");
>>>>>       // configuration.add( "spring-security.afterlogout.url", "/" );
>>>>>       // configuration.add( "spring-security.rememberme.key",
>>>>> "REMEMBERMEKEY" );
>>>>>       configuration.add("spring-security.loginform.url", "/login");
>>>>>       // configuration.add( "spring-security.force.ssl.login", "false"
>>>>> );
>>>>>       // configuration.add( "spring-security.anonymous.key",
>>>>> "acegi_anonymous" );
>>>>>       // configuration.add(
>>>>>       // "spring-security.anonymous.attribute",
>>>>>       // "anonymous,ROLE_ANONYMOUS" );
>>>>>       configuration.add( "spring-security.password.salt", "DEADBEEF" );
>>>>>   }
>>>>>
>>>>>   /**
>>>>>    * This is a service definition, the service will be named
>>>>> "TimingFilter". The interface, RequestFilter, is used
>>>>>    * within the RequestHandler service pipeline, which is built from
>>>>> the
>>>>> RequestHandler service configuration.
>>>>>    * Tapestry IoC is responsible for passing in an appropriate Logger
>>>>> instance. Requests for static resources are
>>>>>    * handled at a higher level, so this filter will only be invoked for
>>>>> Tapestry related requests.
>>>>>    *
>>>>>    * <p>
>>>>>    * Service builder methods are useful when the implementation is
>>>>> inline
>>>>> as an inner class (as here) or require some
>>>>>    * other kind of special initialization. In most cases, use the
>>>>> static
>>>>> bind() method instead.
>>>>>    *
>>>>>    * <p>
>>>>>    * If this method was named "build", then the service id would be
>>>>> taken
>>>>> from the service interface and would be
>>>>>    * "RequestFilter". Since Tapestry already defines a service named
>>>>> "RequestFilter" we use an explicit service id
>>>>>    * that we can reference inside the contribution method.
>>>>>    */
>>>>>   public RequestFilter buildTimingFilter(final Logger log) {
>>>>>       return new RequestFilter() {
>>>>>           public boolean service(Request request, Response response,
>>>>> RequestHandler handler) throws IOException {
>>>>>               long startTime = System.currentTimeMillis();
>>>>>
>>>>>               try {
>>>>>                   // The responsibility of a filter is to invoke the
>>>>> corresponding method
>>>>>                   // in the handler. When you chain multiple filters
>>>>> together, each filter
>>>>>                   // received a handler that is a bridge to the next
>>>>> filter.
>>>>>
>>>>>                   return handler.service(request, response);
>>>>>               } finally {
>>>>>                   long elapsed = System.currentTimeMillis() -
>>>>> startTime;
>>>>>
>>>>>                   log.info(String.format("Request time: %d ms",
>>>>> elapsed));
>>>>>               }
>>>>>           }
>>>>>       };
>>>>>   }
>>>>>
>>>>>   /**
>>>>>    * This is a contribution to the RequestHandler service
>>>>> configuration.
>>>>> This is how we extend Tapestry using the
>>>>>    * timing filter. A common use for this kind of filter is transaction
>>>>> management or security. The @Local annotation
>>>>>    * selects the desired service by type, but only from the same
>>>>> module.
>>>>> Without @Local, there would be an error due
>>>>>    * to the other service(s) that implement RequestFilter (defined in
>>>>> other modules).
>>>>>    */
>>>>>   public void
>>>>> contributeRequestHandler(OrderedConfiguration<RequestFilter>
>>>>> configuration, @Local RequestFilter filter) {
>>>>>       // Each contribution to an ordered configuration has a name, When
>>>>> necessary, you may
>>>>>       // set constraints to precisely control the invocation order of
>>>>> the
>>>>> contributed filter
>>>>>       // within the pipeline.
>>>>>
>>>>>       configuration.add("Timing", filter);
>>>>>   }
>>>>>
>>>>>   /* COMMON UserDetailsService */
>>>>>   public static UserDetailsService buildUserDetailsService(@Inject
>>>>> PersistenceManager persistenceManager, final Logger log) {
>>>>>       return new UserDetailsServiceImpl(persistenceManager,log);
>>>>>   }
>>>>>
>>>>>   /* USERNAME, PASSWORD */
>>>>> //    public static UserDetailsService
>>>>> buildUserDetailsWithUsernameAndPasswordService(/*...@inject
>>>>> PasswordEncoder
>>>>> encoder,
>>>>> //            @Inject SaltSource salt, */final Logger log) {
>>>>> //        return new
>>>>> UserDetailsWithUsernameAndPasswordService(/*encoder,
>>>>> salt, */log);
>>>>> //    }
>>>>>
>>>>>   /* OPENID */
>>>>> //    public static UserDetailsService
>>>>> buildUserDetailsWithOpenIDService()
>>>>> {
>>>>> //        return new UserDetailsWithOpenIDServiceImpl();
>>>>> //    }
>>>>>
>>>>>   public static OpenIDAuthenticationProvider
>>>>> buildOpenIDAuthenticationProvider(
>>>>>           @InjectService("UserDetailsWithOpenIDService")
>>>>> UserDetailsService userDetailsService) throws Exception {
>>>>>       OpenIDAuthenticationProvider provider = new
>>>>> OpenIDAuthenticationProvider();
>>>>>
>>>>>       provider.setUserDetailsService(userDetailsService);
>>>>>       provider.afterPropertiesSet();
>>>>>
>>>>>       return provider;
>>>>>   }
>>>>>
>>>>>   public static void
>>>>> contributeProviderManager(OrderedConfiguration<AuthenticationProvider>
>>>>> configuration,
>>>>>
>>>>>           @InjectService("DaoAuthenticationProvider")
>>>>> AuthenticationProvider daoAuthenticationProvider,
>>>>>           @InjectService("OpenIDAuthenticationProvider")
>>>>> AuthenticationProvider openIdAuthenticationProvider) {
>>>>>
>>>>>       configuration.add("daoAuthenticationProvider",
>>>>> daoAuthenticationProvider);
>>>>>       configuration.add("openIDAuthenticationProvider",
>>>>> openIdAuthenticationProvider);
>>>>>   }
>>>>>
>>>>>
>>>>>   public static OpenIDAuthenticationProcessingFilter
>>>>> buildRealOpenIDAuthenticationProcessingFilter(
>>>>>           @SpringSecurityServices final AuthenticationManager manager,
>>>>>           @SpringSecurityServices final RememberMeServices
>>>>> rememberMeServices,
>>>>>           @Inject @Value("${spring-security.check.url}") final String
>>>>> authUrl,
>>>>>           @Inject @Value("${spring-security.target.url}") final String
>>>>> targetUrl,
>>>>>           @Inject @Value("${spring-security.failure.url}") final String
>>>>> failureUrl) throws Exception {
>>>>>       OpenIDAuthenticationProcessingFilter filter = new
>>>>> OpenIDAuthenticationProcessingFilter();
>>>>>
>>>>>       filter.setAuthenticationManager(manager);
>>>>>       filter.setAuthenticationFailureUrl(failureUrl);
>>>>>       filter.setDefaultTargetUrl(targetUrl);
>>>>>       filter.setFilterProcessesUrl(authUrl);
>>>>>       filter.setRememberMeServices(rememberMeServices);
>>>>>       filter.afterPropertiesSet();
>>>>>
>>>>>       return filter;
>>>>>   }
>>>>>
>>>>>   public static HttpServletRequestFilter
>>>>> buildOpenIDAuthenticationProcessingFilter(
>>>>>           final OpenIDAuthenticationProcessingFilter filter) {
>>>>>       return new HttpServletRequestFilterWrapper(filter);
>>>>>   }
>>>>>
>>>>>   public static void contributeHttpServletRequestHandler(
>>>>>           OrderedConfiguration<HttpServletRequestFilter> configuration,
>>>>>
>>>>>           @InjectService("OpenIDAuthenticationProcessingFilter")
>>>>> HttpServletRequestFilter openIDAuthenticationProcessingFilter) {
>>>>>       configuration.add("openIDAuthenticationProcessingFilter",
>>>>>
>>>>>       openIDAuthenticationProcessingFilter,
>>>>>
>>>>>       "before:springSecurityAuthenticationProcessingFilter",
>>>>>
>>>>>       "after:springSecurityHttpSessionContextIntegrationFilter");
>>>>>   }
>>>>>
>>>>> }
>>>>>
>>>>>
>>>>>
>>>>> Is there a problem in this last method
>>>>> ("before:springSecurityAuthenticationProcessingFilter")? Both forms
>>>>> (for
>>>>> u/p
>>>>> and openid url) are on the same page.
>>>>>
>>>>> <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
>>>>>   <head>
>>>>>       <title>Najdi.si prijavna stran</title>
>>>>>       <link rel="stylesheet" type="text/css"
>>>>> href="${asset:context:css/iopenid.css}" />
>>>>>   </head>
>>>>>   <body>
>>>>>       <t:layout xmlns:t="
>>>>> http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
>>>>>
>>>>>           <div style="margin-left: 50px">
>>>>>               <t:block t:id="loginWithUserNameAndPassword">
>>>>>                   <p>
>>>>>                       Prijavite se z uporabniškim imenom in geslom ali
>>>>> z
>>>>>                       <a t:type="actionlink" t:id="refreshOpenIDZone"
>>>>> href="#" t:zone="loginZone">OpenID</a>
>>>>>                   </p>
>>>>>                   <form xmlns:t="
>>>>> http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";
>>>>> action="${loginCheckUrl}" method="POST">
>>>>>                       <t:if test="failed">
>>>>>                           Napačno uporabniško ime ali geslo!
>>>>>                           <br />
>>>>>                       </t:if>
>>>>>                       <label class="username"
>>>>> for="j_username">uporabniško
>>>>> ime:</label>
>>>>>                       <input class="username" name="j_username"
>>>>> type="text" size="10" maxlength="30" />
>>>>>                       <label class="password"
>>>>> for="j_password">geslo:</label>
>>>>>                       <input class="password" name="j_password"
>>>>> type="password" size="10" maxlength="30" />
>>>>>                       <input id="submit" class="submit" type="submit"
>>>>> value="log in" />
>>>>>                   </form>
>>>>>                   <p>Še nimate Najdi.si računa? <a t:type="pagelink"
>>>>> t:page="Register" href="#">Registrirajte se!</a></p>
>>>>>                   <p><a t:type="pagelink" t:page="RetrievePassword"
>>>>> href="#">Pozabil sem geslo.</a></p>
>>>>>               </t:block>
>>>>>               <t:block t:id="loginWithOpenID">
>>>>>                   <p>
>>>>>                       Prijavite se z
>>>>>                       <a t:type="actionlink"
>>>>> t:id="refreshUsernamePasswordZone" href="#"
>>>>> t:zone="loginZone">uporabniškim
>>>>> imenom in
>>>>>                           geslom</a>
>>>>>                       ali z OpenID
>>>>>                   </p>
>>>>>                   <form xmlns:t="
>>>>> http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";
>>>>> action="${loginCheckUrl}" method="POST">
>>>>>                       <t:if test="failed">
>>>>>                           Napaka!
>>>>>                           <br />
>>>>>                       </t:if>
>>>>>                       <label class="username"
>>>>> for="j_username">OpenID:</label>
>>>>>                       <input class="username" name="j_username"
>>>>> type="text" size="30" />
>>>>>                       <input id="submit" class="submit" type="submit"
>>>>> value="log in" />
>>>>>                   </form>
>>>>>                   <p>Še nimate Najdi.si računa? Ob <a t:type="pagelink"
>>>>> t:page="Register" href="#">registraciji</a> dobite tudi Najdi.si
>>>>> OpenID.</p>
>>>>>               </t:block>
>>>>>               <t:zone t:id="loginZone">
>>>>>                   <t:delegate to="loginWithUserNameAndPassword" />
>>>>>               </t:zone>
>>>>>               <br />
>>>>>
>>>>>           </div>
>>>>>
>>>>>       </t:layout>
>>>>>   </body>
>>>>> </html>
>>>>>
>>>>>
>>>>> public class Login {
>>>>>   @Inject
>>>>>   @Property
>>>>>   private Block loginWithUserNameAndPassword;
>>>>>
>>>>>   @Inject
>>>>>   @Property
>>>>>   private Block loginWithOpenID;
>>>>>
>>>>>   @Inject
>>>>>   @Property
>>>>>   private Request _request;
>>>>>
>>>>>   void onActionFromRefreshPage() {
>>>>>       // Nothing to do - the page will get fresh times as it is
>>>>> rendered.
>>>>>   }
>>>>>
>>>>>   Block onActionFromRefreshOpenIDZone() {
>>>>>       // Check this is an AJAX link - if the link is clicked before the
>>>>> DOM is fully loaded then AJAX behaviour won't
>>>>>       // be there so don't try returning a Block. See
>>>>> https://issues.apache.org/jira/browse/TAP5-1 .
>>>>>       if (!_request.isXHR()) {
>>>>>           return null;
>>>>>       }
>>>>>
>>>>>       // Return the zone we want rendered. Without Ajax we'd typically
>>>>> return the page we want rendered.
>>>>>       return loginWithOpenID;
>>>>>   }
>>>>>
>>>>>   Block onActionFromRefreshUsernamePasswordZone() {
>>>>>       // Check this is an AJAX link - if the link is clicked before the
>>>>> DOM is fully loaded then AJAX behaviour won't
>>>>>       // be there so don't try returning a Block. See
>>>>> https://issues.apache.org/jira/browse/TAP5-1 .
>>>>>       if (!_request.isXHR()) {
>>>>>           return null;
>>>>>       }
>>>>>
>>>>>       // Return the zone we want rendered. Without Ajax we'd typically
>>>>> return the page we want rendered.
>>>>>       return loginWithUserNameAndPassword;
>>>>>   }
>>>>>
>>>>>   @Inject
>>>>>   @Value("${spring-security.check.url}")
>>>>>   private String checkUrl;
>>>>>
>>>>>   @Inject
>>>>>   private Request request;
>>>>>
>>>>>   private boolean failed = false;
>>>>>
>>>>>   public boolean isFailed() {
>>>>>       return failed;
>>>>>   }
>>>>>
>>>>>   public String getLoginCheckUrl() {
>>>>>       return request.getContextPath() + checkUrl;
>>>>>   }
>>>>>
>>>>>   void onActivate(String extra) {
>>>>>       if (extra.equals("failed")) {
>>>>>           failed = true;
>>>>>       }
>>>>>   }
>>>>>
>>>>> I would be really gratefull for your help!
>>>>>
>>>>> Regards,
>>>>> Borut
>>>>>
>>>>>
>>>>
>>
>

Reply via email to