Fórum

No User exists with the primary key 0, when using a filter.

thumbnail
Cameron McBride, modificado 12 Anos atrás.

No User exists with the primary key 0, when using a filter.

Expert Postagens: 269 Data de Entrada: 08/02/11 Postagens 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:
19:25:09,596 ERROR [SecureFilter:59] com.liferay.portal.NoSuchUserException: No
User exists with the primary key 0
com.liferay.portal.NoSuchUserException: No User exists with the primary key 0
        at com.liferay.portal.service.persistence.UserPersistenceImpl.findByPrim
aryKey(UserPersistenceImpl.java:960)
        at com.liferay.portal.service.impl.UserLocalServiceImpl.getUserById(User
LocalServiceImpl.java:2450)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(Ser
viceBeanMethodInvocation.java:112)
        at com.liferay.portal.spring.transaction.TransactionInterceptor.invoke(T
ransactionInterceptor.java:71)
        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(Ser
viceBeanMethodInvocation.java:108)
        at com.liferay.portal.spring.aop.ChainableMethodAdvice.invoke(ChainableM
ethodAdvice.java:59)
        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(Ser
viceBeanMethodInvocation.java:108)
        at com.liferay.portal.spring.aop.ChainableMethodAdvice.invoke(ChainableM
ethodAdvice.java:59)
        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(Ser
viceBeanMethodInvocation.java:108)


<filter>
    <filter-name>SpnegoHttpFilter</filter-name>
    <filter-class>net.sourceforge.spnego.SpnegoHttpFilter</filter-class>

    <init-param>
        <param-name>spnego.allow.basic</param-name>
        <param-value>true</param-value>
    </init-param>
    
    <init-param>
        <param-name>spnego.allow.localhost</param-name>
        <param-value>true</param-value>
    </init-param>
    
    <init-param>
        <param-name>spnego.allow.unsecure.basic</param-name>
        <param-value>true</param-value>
    </init-param>
    
    <init-param>
        <param-name>spnego.login.client.module</param-name>
        <param-value>spnego-client</param-value>
    </init-param>
    
    <init-param>
        <param-name>spnego.krb5.conf</param-name>
        <param-value>E:\\liferay\\liferay-portal-6.1.0-ce-ga1\\krb5.conf</param-value>
    </init-param>
    
    <init-param>
        <param-name>spnego.login.conf</param-name>
        <param-value>E:\\liferay\\liferay-portal-6.1.0-ce-ga1\\login.conf</param-value>
    </init-param>
    
    <init-param>
        <param-name>spnego.preauth.username</param-name>
        <param-value>CorpSvcLifeRayDV</param-value>
    </init-param>
    
    <init-param>
        <param-name>spnego.preauth.password</param-name>
        <param-value>6pC4Kck</param-value>
    </init-param>
    
    <init-param>
        <param-name>spnego.login.server.module</param-name>
        <param-value>spnego-server</param-value>
    </init-param>
	
	<init-param>
		<param-name>spnego.allow.basic</param-name>
		<param-value>true</param-value>
	</init-param>
	
	<init-param>
		<param-name>spnego.allow.unsecure.basic</param-name>
		<param-value>true</param-value>
	</init-param>
	
	<init-param>
		<param-name>spnego.allow.localhost</param-name>
		<param-value>true</param-value>
	</init-param>
    
    <init-param>
        <param-name>spnego.prompt.ntlm</param-name>
        <param-value>true</param-value>
    </init-param>
    
    <init-param>
        <param-name>spnego.logger.level</param-name>
        <param-value>1</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>SpnegoHttpFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
thumbnail
David H Nebinger, modificado 12 Anos atrás.

RE: No User exists with the primary key 0, when using a filter.

Liferay Legend Postagens: 14916 Data de Entrada: 02/09/06 Postagens 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...
thumbnail
Cameron McBride, modificado 12 Anos atrás.

RE: No User exists with the primary key 0, when using a filter.

Expert Postagens: 269 Data de Entrada: 08/02/11 Postagens 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.
thumbnail
David H Nebinger, modificado 12 Anos atrás.

RE: No User exists with the primary key 0, when using a filter.

Liferay Legend Postagens: 14916 Data de Entrada: 02/09/06 Postagens 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...
thumbnail
Cameron McBride, modificado 12 Anos atrás.

RE: No User exists with the primary key 0, when using a filter.

Expert Postagens: 269 Data de Entrada: 08/02/11 Postagens 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.
thumbnail
David H Nebinger, modificado 12 Anos atrás.

RE: No User exists with the primary key 0, when using a filter.

Liferay Legend Postagens: 14916 Data de Entrada: 02/09/06 Postagens 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 ;-)
thumbnail
Cameron McBride, modificado 12 Anos atrás.

RE: No User exists with the primary key 0, when using a filter.

Expert Postagens: 269 Data de Entrada: 08/02/11 Postagens 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!
13:14:32,920 ERROR [error_jsp:427] User ID eqb9718
13:14:32,922 ERROR [error_jsp:428] Current URL /web/guest/home
13:14:32,923 ERROR [error_jsp:429] Referer null
13: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.
thumbnail
Cameron McBride, modificado 12 Anos atrás.

RE: No User exists with the primary key 0, when using a filter.

Expert Postagens: 269 Data de Entrada: 08/02/11 Postagens 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.
    public String getRemoteUser() {
        
        if (null == this.principal) {
            return super.getRemoteUser();
            
        } else {
            final String[] username = this.principal.getName().split("@", 2);
            return username[0];
            //System.out.println("User: " + this.principal.getRealm() + " - " + this.principal.getName());
        }
    }

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.
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
#in AutoLogin
Username: eqb9718
Realm: HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
#in AutoLogin
Username: eqb9718
Realm: HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
User: HCADEV.CORPADDEV.NET - eqb9718@HCADEV.CORPADDEV.NET
thumbnail
giampiero longobardi, modificado 12 Anos atrás.

RE: No User exists with the primary key 0, when using a filter.

New Member Postagens: 7 Data de Entrada: 17/12/10 Postagens 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.
thumbnail
Cameron McBride, modificado 11 Anos atrás.

RE: No User exists with the primary key 0, when using a filter.

Expert Postagens: 269 Data de Entrada: 08/02/11 Postagens 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.

    @Override
    public String getRemoteUser() {
        
    	/* PCM
        if (null == this.principal) {
            return super.getRemoteUser();
            
        } else {
            final String[] username = this.principal.getName().split("@", 2);
            return username[0];
        }
        */
    	return super.getRemoteUser();
    }




<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.
thumbnail
Vilmos Papp, modificado 11 Anos atrás.

RE: No User exists with the primary key 0, when using a filter.

Liferay Master Postagens: 529 Data de Entrada: 21/10/10 Postagens 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.
thumbnail
Vilmos Papp, modificado 12 Anos atrás.

RE: No User exists with the primary key 0, when using a filter.

Liferay Master Postagens: 529 Data de Entrada: 21/10/10 Postagens 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.