You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Ulrich Stärk <ul...@spielviel.de> on 2009/01/23 12:10:09 UTC
Re: Authentication
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 <ul...@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
>>>
>>
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org
Re: Authentication
Posted by Borut Bolčina <bo...@gmail.com>.
Ups, that was beers :-)
2009/1/23 Borut Bolčina <bo...@gmail.com>
> 100 bears for Ulrich!
>
> It works. You made my day. Thanks,
>
> -Borut
>
> 2009/1/23 Ulrich Stärk <ul...@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 <ul...@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
>>>>>
>>>>>
>>>>
>>
>
Re: Authentication
Posted by Borut Bolčina <bo...@gmail.com>.
100 bears for Ulrich!
It works. You made my day. Thanks,
-Borut
2009/1/23 Ulrich Stärk <ul...@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 <ul...@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
>>>>
>>>>
>>>
>