Fóruns

Início » Liferay Portal » English » 3. Development

Visualização combinada Visão plana Exibição em árvore
Tópicos [ Anterior | Próximo ]
toggle
Cameron McBride
No User exists with the primary key 0, when using a filter.
16 de Março de 2012 12:40
Resposta

Cameron McBride

Ranking: Expert

Mensagens: 273

Data de entrada: 8 de Fevereiro de 2011

Mensagens recentes

We are wanting to develop a SSO solution for Liferay using Kerberos KDC and then falling back to NTLM (both Active Directory). I found a really awesome filter called spnego that will do exactly this: http://spnego.sourceforge.net/.

To get the filter up and running you have some filter/filter-mapping entries for the web.xml, a jar file and a couple of config files. I set these up with Apache Tomcat 7 and a test jsp page and it works perfectly. The problem is when I try to plug the filter into tomcat/Liferay 6.1ce.

1. Copy the spnego jar to liferay-portal-6.1.0\tomcat-7.0.23\lib

2. I edit the web.xml in tomcat-7.0.23\webapps\ROOT\WEB-INF and placed the filter/filter-mapping before the other filter items. I also tried placing the filter in the tomcat\conf\web.xml with the same error. I will paste in the actual web.xml down below.

3. I fire up Liferay and I get an error that says No User exists with the primary key 0. I am unsure what this error is trying to tell me but I'll be searching around. At this point I dont have any autologin hooks or anything like that. It is just a filter that will authenticate a user against Kerberos/NTLM, which worked in a plain tomcat.

The error:
 119:25:09,596 ERROR [SecureFilter:59] com.liferay.portal.NoSuchUserException: No
 2User exists with the primary key 0
 3com.liferay.portal.NoSuchUserException: No User exists with the primary key 0
 4        at com.liferay.portal.service.persistence.UserPersistenceImpl.findByPrim
 5aryKey(UserPersistenceImpl.java:960)
 6        at com.liferay.portal.service.impl.UserLocalServiceImpl.getUserById(User
 7LocalServiceImpl.java:2450)
 8        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 9        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
10java:39)
11        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
12sorImpl.java:25)
13        at java.lang.reflect.Method.invoke(Method.java:597)
14        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(Ser
15viceBeanMethodInvocation.java:112)
16        at com.liferay.portal.spring.transaction.TransactionInterceptor.invoke(T
17ransactionInterceptor.java:71)
18        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(Ser
19viceBeanMethodInvocation.java:108)
20        at com.liferay.portal.spring.aop.ChainableMethodAdvice.invoke(ChainableM
21ethodAdvice.java:59)
22        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(Ser
23viceBeanMethodInvocation.java:108)
24        at com.liferay.portal.spring.aop.ChainableMethodAdvice.invoke(ChainableM
25ethodAdvice.java:59)
26        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(Ser
27viceBeanMethodInvocation.java:108)


 1<filter>
 2    <filter-name>SpnegoHttpFilter</filter-name>
 3    <filter-class>net.sourceforge.spnego.SpnegoHttpFilter</filter-class>
 4
 5    <init-param>
 6        <param-name>spnego.allow.basic</param-name>
 7        <param-value>true</param-value>
 8    </init-param>
 9   
10    <init-param>
11        <param-name>spnego.allow.localhost</param-name>
12        <param-value>true</param-value>
13    </init-param>
14   
15    <init-param>
16        <param-name>spnego.allow.unsecure.basic</param-name>
17        <param-value>true</param-value>
18    </init-param>
19   
20    <init-param>
21        <param-name>spnego.login.client.module</param-name>
22        <param-value>spnego-client</param-value>
23    </init-param>
24   
25    <init-param>
26        <param-name>spnego.krb5.conf</param-name>
27        <param-value>E:\\liferay\\liferay-portal-6.1.0-ce-ga1\\krb5.conf</param-value>
28    </init-param>
29   
30    <init-param>
31        <param-name>spnego.login.conf</param-name>
32        <param-value>E:\\liferay\\liferay-portal-6.1.0-ce-ga1\\login.conf</param-value>
33    </init-param>
34   
35    <init-param>
36        <param-name>spnego.preauth.username</param-name>
37        <param-value>CorpSvcLifeRayDV</param-value>
38    </init-param>
39   
40    <init-param>
41        <param-name>spnego.preauth.password</param-name>
42        <param-value>6pC4Kck</param-value>
43    </init-param>
44   
45    <init-param>
46        <param-name>spnego.login.server.module</param-name>
47        <param-value>spnego-server</param-value>
48    </init-param>
49   
50    <init-param>
51        <param-name>spnego.allow.basic</param-name>
52        <param-value>true</param-value>
53    </init-param>
54   
55    <init-param>
56        <param-name>spnego.allow.unsecure.basic</param-name>
57        <param-value>true</param-value>
58    </init-param>
59   
60    <init-param>
61        <param-name>spnego.allow.localhost</param-name>
62        <param-value>true</param-value>
63    </init-param>
64   
65    <init-param>
66        <param-name>spnego.prompt.ntlm</param-name>
67        <param-value>true</param-value>
68    </init-param>
69   
70    <init-param>
71        <param-name>spnego.logger.level</param-name>
72        <param-value>1</param-value>
73    </init-param>
74</filter>
75
76<filter-mapping>
77    <filter-name>SpnegoHttpFilter</filter-name>
78    <url-pattern>/*</url-pattern>
79</filter-mapping>
David H Nebinger
RE: No User exists with the primary key 0, when using a filter.
16 de Março de 2012 13:02
Resposta

David H Nebinger

Community Moderator

Ranking: Liferay Legend

Mensagens: 11304

Data de entrada: 1 de Setembro de 2006

Mensagens recentes

You might not be able to just drop it in and get it to work.

I'd look through the implementation of the NTLM authentication stuff to identify what might be missing, but I'm pretty sure that it probably sets user info into the request and/or session so the user can be found.

Note that having this authentication does not mean you can bypass having the users defined in the Liferay database - they are still needed there to satisfy foreign keys...
Cameron McBride
RE: No User exists with the primary key 0, when using a filter.
16 de Março de 2012 13:19
Resposta

Cameron McBride

Ranking: Expert

Mensagens: 273

Data de entrada: 8 de Fevereiro de 2011

Mensagens recentes

I am not using anything from Liferay in this example. I am not trying to create user accounts, log users in or anything along those lines. The end goal will be for all of our users to be synced from ldap and the autologin hook would check for the authenticated user (which is set in the request object by spnego) and I would log the user in.

Your idea about spnego messing up the request object could certainly be the problem. In the working tomcat environment (without Liferay) I can grab the user from request.getRemoteUser(). I can see where this data could be set and then Liferay getting all confused. Maybe I am going to need to edit the spnego source and set that information some other way besides the default.
Vilmos Papp
RE: No User exists with the primary key 0, when using a filter.
16 de Março de 2012 13:31
Resposta

Vilmos Papp

LIFERAY STAFF

Ranking: Liferay Master

Mensagens: 521

Data de entrada: 21 de Outubro de 2010

Mensagens recentes

If you already started Liferay before the settings, you probably should empty the browser caches. If I remember correctly, I saw some similar problem when I started Liferay with HSQL then switched the DB to MySQL. Then this solved my problem, but it didn't relates to Kerberos or NTLM in my situation as there were no such settings set at all.
David H Nebinger
RE: No User exists with the primary key 0, when using a filter.
16 de Março de 2012 13:47
Resposta

David H Nebinger

Community Moderator

Ranking: Liferay Legend

Mensagens: 11304

Data de entrada: 1 de Setembro de 2006

Mensagens recentes

If you check the source for <portal-trunk>/portal-impl/src/com/liferay/portal/servlet/filters/sso/ntlm/NtlmFilter, you'll see that when NTLM is successful they set two attributes:

In the request, they set NTLM_REMOTE_USER to the username.
In the session (if it exists), they set NTLM_USER_ACCOUNT to the NtlmUserAccount instance.

Also shows what they do when NTLM auth fails, how to handle it for the /login request, ...

If I had to guess, I'd say you're probably looking at perhaps extending this class and adding the stuff from the spnego filter in order to integrate it...
Cameron McBride
RE: No User exists with the primary key 0, when using a filter.
16 de Março de 2012 14:39
Resposta

Cameron McBride

Ranking: Expert

Mensagens: 273

Data de entrada: 8 de Fevereiro de 2011

Mensagens recentes

With what I set up I anticipated landing at the login/home page of Liferay and not being logged in at all, since I have not configured or written any type of autologin. Maybe a good next step is to print out all of the request/header information on the working tomcat (without Liferay) and see what's in there and then compare it to a stock/out-of-the-box Liferay login. Maybe I can pinpoint something that Liferay is taking to mean a "logged in user".

I do not think we will be using the OOB NTLM autologin but it may be a good thing to look at to see what they are doing in their filter! I will definitely be taking a look at that over the weekend.

That also gave me another idea, aren't all those filters on out-of-the-box, like 15 of them? I bet I should turn every single one off to see if that resolves the conflict.

This is a little off topic but NTLM OOB SSO: I looked at it back in 6.0 and it required a computer account set up on the domain controller. We have 12+ domain controllers so that would not work to just use one. With the spnego you can use an AD service account and I can connect to your global cataglog instead. All of our ad controllers are also Kerberos KDCs.
David H Nebinger
RE: No User exists with the primary key 0, when using a filter.
16 de Março de 2012 16:42
Resposta

David H Nebinger

Community Moderator

Ranking: Liferay Legend

Mensagens: 11304

Data de entrada: 1 de Setembro de 2006

Mensagens recentes

Yes, all 15 (or so) are in the filter chain by default. As a tuning measure you should disable the ones you're not using, but be aware that you cannot just flip things on in the control panel after disabling the filters ;-)
Cameron McBride
RE: No User exists with the primary key 0, when using a filter.
19 de Março de 2012 07:15
Resposta

Cameron McBride

Ranking: Expert

Mensagens: 273

Data de entrada: 8 de Fevereiro de 2011

Mensagens recentes

The first thing I've done this morning was to disable all of the filters. I'll probably need to review all of them later on but this was for a quick test. I also removed a servlet block from the web.xml (http://www.liferay.com/community/wiki/-/wiki/Main/Slimming+Liferay+Portal#section-Slimming+Liferay+Portal-Turn+off+Unused+Filters) but that breaks the portal totally so I put that back in.

I still get the No user exists with primary key 0 but now I get some extra messages below that!
113:14:32,920 ERROR [error_jsp:427] User ID eqb9718
213:14:32,922 ERROR [error_jsp:428] Current URL /web/guest/home
313:14:32,923 ERROR [error_jsp:429] Referer null
413:14:32,923 ERROR [error_jsp:430] Remote address 127.0.0.1


That "eqb9718" is my screen name. I'll be grabbing some headers to see what I can see in there next.
Cameron McBride
RE: No User exists with the primary key 0, when using a filter.
21 de Março de 2012 06:45
Resposta

Cameron McBride

Ranking: Expert

Mensagens: 273

Data de entrada: 8 de Fevereiro de 2011

Mensagens recentes

I have made some progress on my spnego filter. I abandoned getting the filter to work at the tomcat level and figured if I was going to have to edit the spnego source that I might as well make it a servlet filter hook that can be easily deployed. I created a servlet filter hook and added the spnego source. Spnego relies on no 3rd party libraries so that made things easier. I got even luckier because the filter's main class SpnegoHttpFilter.java implements Filter which is exactly what you need when creating a servlet filter in 6.1. The old ext in 6.0 used BasePortalFilter.

I deployed this and of course got the same error as before. After a day of tracing through the code (slow and easily side tracked) I found that it is using a class SpnegoHttpServletRequest that extends HttpServletRequest. In there it is overriding getRemoteUser and returning the users AD user name (or whatever you were authenticating against). This is what is causing Liferay to fall to pieces.
 1    public String getRemoteUser() {
 2       
 3        if (null == this.principal) {
 4            return super.getRemoteUser();
 5            
 6        } else {
 7            final String[] username = this.principal.getName().split("@", 2);
 8            return username[0];
 9            //System.out.println("User: " + this.principal.getRealm() + " - " + this.principal.getName());
10        }
11    }

I commented that garbage out and put in a print line. Liferay now executes the filter perfect and the users domain and username get printed out!

My next steps will be:
- To set some other request variable and then pull that request variable from an AutoLogin hook.
- Keep the servlet filter from executing like crazy on every page.
- Create an autologin hook that reads the variable, imports the user from AD if they don't exist (easy) and log them in.

That second task is a bit concerning. The filter executes the "doFilter" method at least 70 times per page and also gets to the getRemoteUser 6 or 7 times per page. That is a lot of wasted time I think. I need to figure out how to skip the filter if the user is already logged in maybe.

I am now setting a session variable for the domain and username and pulling that out in an autologin hook. All the "User:" lines is when it goes through the filter and authenticates. Clearly it doesn't need to do the handshake that many times for one page.
 1User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
 2User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
 3#in AutoLogin
 4Username: eqb9718
 5Realm: HCADEV.CORPADDEV.NET
 6User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
 7#in AutoLogin
 8Username: eqb9718
 9Realm: HCADEV.CORPADDEV.NET
10User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
11User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
12User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
13User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
14User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
15User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
16User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
17User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
18User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
19User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
20User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
21User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
22User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
23User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
giampiero longobardi
RE: No User exists with the primary key 0, when using a filter.
16 de Abril de 2012 08:40
Resposta

giampiero longobardi

Ranking: New Member

Mensagens: 7

Data de entrada: 17 de Dezembro de 2010

Mensagens recentes

Cameron,
how have you modified the the getRemoteUser() method inside SpnegoHttpServletRequest class ? Could you share the code ?

Concerning the problem you have mentioned, I think the filter executes the "doFilter" method several times per page because the SPNEGO filter should act only on the login action

<filter-mapping>
<filter-name>SpnegoHttpFilter</filter-name>
<url-pattern>/c/portal/login</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>

This filter should be combined with an AutoLogin subclass filter for SSO, avoiding the problem you mentioned.
Cameron McBride
RE: No User exists with the primary key 0, when using a filter.
1 de Maio de 2012 07:45
Resposta

Cameron McBride

Ranking: Expert

Mensagens: 273

Data de entrada: 8 de Fevereiro de 2011

Mensagens recentes

giampiero longobardi:

how have you modified the the getRemoteUser() method inside SpnegoHttpServletRequest class ? Could you share the code ?

I am actually not using that SpegoHttpServletRequest class anymore, I'm just using the HttpServletRequest now. What I did was I downloaded the Spnego source code (it's free) and I copied all of it into my project. Then I just edited the SpnegoHttpServletRequest source class.

 1    @Override
 2    public String getRemoteUser() {
 3       
 4        /* PCM
 5        if (null == this.principal) {
 6            return super.getRemoteUser();
 7            
 8        } else {
 9            final String[] username = this.principal.getName().split("@", 2);
10            return username[0];
11        }
12        */
13        return super.getRemoteUser();
14    }




<filter-mapping>
<filter-name>SpnegoHttpFilter</filter-name>
<url-pattern>/c/portal/login</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>


This type of filter would not work for us. Our users need to be single signed in no matter where they go. Access any page, SSO. Access any document, SSO. What you suggest requires that the user click the sign in button before they can do anything.
Vilmos Papp
RE: No User exists with the primary key 0, when using a filter.
24 de Julho de 2012 04:03
Resposta

Vilmos Papp

LIFERAY STAFF

Ranking: Liferay Master

Mensagens: 521

Data de entrada: 21 de Outubro de 2010

Mensagens recentes

I would suggest you check liferay-web.xml for SSO Ntlm Filter and SSO Ntlm Post Filter and their mapping. The similar pattern maybe can applied in your scenario as well.