Per-context authentication database
Hi, It is possible to have a per-context authentication database, especially one that does not have to be configured using server.xml ? This is the sort of scenario I am looking at: A WAR file is added to the webapps directory, and on restarting Tocmat will be deployed. It contains all of the information necessary for it to function, including its own password database (and maybe even the database drivers). There is no need to modify the server.xml in any way. The very important catch here is that I want to use Tomcat's support for form logon - that is, the form-logon- page and logon-error-page in the web.xml, and all that jazz. I do not intend writing my own logic to handle the authentication! Can this be done? If it can't, would it be possible to do it by making a new RequestInterceptor? Twylite
Re: Per-context authentication database
Hi, I sortof answered my own question, by writing my own Realm to do the trick. But I'm having some trouble :/ to override the default. In the realm implementation authenticate() I just do stuff like Context ctx = req.getContext(); String jaasConfigEntry = ctx.getInitParameter(jaasConfigKey); Interestingly I'm doing something almost exactly like that ... but no matter what page/context I'm accessing I appear to be getting the root context from req.getContext() . Any suggestions? I'm not sure what you mean by not wanting to write your own logic to handle the authentication. JDBC realm simply does string comparison Many in the Great Unwashed Masses seem oblivious to the existance of Tomcat's logon handling, and write their own code in JSPs with lots of If...Thens to check if the person is logged on, and authenticate in their own way against their own database(s). i.e. not using Realms at all. Thanks, Twylite
Re: Per-context authentication database
Hi, Thanks for the reply. Interestingly I'm doing something almost exactly like that ... but no matter what page/context I'm accessing I appear to be getting the root context from req.getContext() . Any suggestions? Have you got the different contexts defined in server.xml? Yes. Of course ... I should probably have consulted my configuration before jumping to conclusions ... let's just say I changed the root context to my development directory, and wasn't expecting Ctx ( ) for it ;) *hits head and weeps in shame* But everything's working fine now ;) It was working fine before ... I just didn't know it. Shees. Twylite
Re: Why is authorization=null? Esp. to Twylite
Hi, thank you for the information about authorization header, form based login and POST method. So the authorization in the HTTP header isn't filled. However I ask myself from where the getRemoteUser and getAuthtype - Methode get the information because these methods do work and I get the correct username and auth form. Basic and Form-based logon are totally separate in their logic, this is how they work: 1. Basic Basic authentication is written into the HTTP specification. When attempting to access a page, the web server can determine if the permissions are insufficient, and reply with a 401 Unauthorized response. Then web browser then displays that popup login dialog to the user. The browser's next attempt to access the page includes a Authorization header with the authentication type (BASIC) and base64 encoded username:password. The web server checks this header against some database of users, and decides whether or not to permit the access. Tomcat detects the Authorization header and sets the username in the request object. 2. Form-based There is no HTTP or HTML specification covering form-based logon. This is a special feature of Tomcat (and I assume other JSP servers, but I'm not sure). In your web.xml file you specify (under the login-config for form- based login) the form-logon-page and form-error-page. If you attempt to access a page for which you don't have permission, Tomcat will instead serve up the form- login-page, keeping in your session the URL of the page you really want to get to. The form-logon-page must have a particular action (j_security_check) which Tomcat will substitute with an appropriate URL, for internal use. The form-logon-page must also have a j_username and j_password field. When the form is submitted it goes to the Tomcat-defined URL where the j_username and j_password are extracted, and sent to the Realm configured in server.xml, for authentication and authorization. If this fails, Tomcat serves up the form-logon-page again (up to three times) and then finally the form-error-page. If the logon is successful and the user has the required roles to access the originally desired page, that page will be served up. Once the login is successful, Tomcat sets the username in the session object, and on every request transfers this into the request object. Hope this clarifies things, and that I haven't made any glaring errors ;) Twylite
RE: JDBC/ODBC: Technological choice
Hi, I recently analyzed a JDBC application for performance problems (using JProbe) and found that 2/3 of my time was being spent by the driver looking up my column number with the name. Always refer to columns by number, and read them all in one time -- first to last -- into a data structure from which you can randomly access what you need how you need it. This is excellent advice; having had the same performance problems myself I can't agree enough. The primary problem with JDBC is the amount of String handling it does - in an application where I was storing and manipulating up to 80Mb of Strings in memory, and database access occurred on approximately every 100th String access, the JDBC driver was responsible for more String object creation and use than my portion of the logic (which, being prototype at the time, did not bother to use StringBuffer or any other optimizations). My recommendations in this regard are fairly straightforward: 1. Use PreparedStatement wherever you can! Creating a new Statement for every database access often seems easier, but uses a LOT of resources, especially Strings. PreparedStatement is also somewhat faster. On the same rant, don't create new Statements every time - a Statement object can be reused with different queries. 2. Whenever you do SELECTs and the like, never use SELECT * - always name your parameters (SELECT alpha, beta FROM myTable). More than just the sheer issue of design and associated problems if you modify the table, you are guaranteed to have the columns returned in the listed order, allowing you to safely use column number indexing to retrieve values, and saving that really nasty overhead of looking up column names to get numbers (which, not surprisingly, creates an astonishing amount of Strings). 3. Cache your results and close the ResultSet as soon as possible. Remember that in Java assigning a String to another data structure does not make a new object - it assigns a reference to the same String object that JDBC created, because Strings are immutable. Typically only one ResultSet can be used by a Connection at a time, so this is prudent to improve the efficiency of multithreaded applications. Use the cached results for as long as possible, to prevent more JDBC calls. 4. Use SQL, not your own logic. Too many people fall prey to the select everything and then pick out what I want problem. Every SQL row you transfer from a database creates new objects. In Java there is no reuse of these objects, so retrieving 100 rows so that you can pick out five of them wastes a lot of memory, and means the garbage collector has to do a lot of extra work later. Use the WHERE clause, use SORT, use GROUP BY and use joins. People also have some sort of innate need to select from one table, and then use that data to select from another table, and so on. Maybe they need SQL tuition, or maybe they somehow believe their method is better. It isn't ... get over it ... use joins. 5. Linked to (4), only transfer what you need. If you only need the Username and Password columns, don't use SELECT * or also retrieve the user's real name and postal address, on the off chance that you may need them. Either you do or you don't. Wells, thats my R2. Given the exchange rate ... that's not far off 2c. Shyte. Twylite
Re:certificate for tomcat and ssl
Hi Has someone configured tomcat to work with SSL without use APACHE server? I've try lot of things and nothing has worked, i'm seeking for all the steps to generated certificate and configure tomcat to work with it. Can someone help me? I am running Tomcat 3.2.1 (as its own webserver) under Windows 2000 with Sun's JDK 1.3. I have SSL working successfully. For the most part following the tomcat-ssl HOWTO is the right way to go. This is what I did (if I remember correctly): Download the JSSE jar file from sun (http://java.sun.com/products/jsse/). Place the .jar file in your $JAVA_HOME/jre/lib/ext directory, as well as in $TOMCAT_HOME/lib . You shouldn't need both, but I have class-not-found problems otherwise. Tomcat 3.2.1 is compiled with SSL support, as long as it finds that jsse.jar file, so that's all okay. Find the file $JAVA_HOME/jre/lib/security/java.security. There is probably already a line starting with security.provide.2 - comment it out with a #, and add the line: security.provider.2=com.sun.net.ssl.internal.ssl.Provider Now create yourself an SSL certificate, using the Java keytool utility. You should run: keytool -genkey -alias tomcat Answer all the questions, and use the same password for the keystore and the key you generate! Now you need to edit your $TOMCAT_HOME/conf/server.xml file, and add in the SSL configuration: (if you have an HTML browser, the next bit, which is XML, will be missing. Have a nice day.) Connector className=org.apache.tomcat.service.PoolTcpConnector Parameter name=handler value=org.apache.tomcat.service.http.HttpConnectionHandler/ Parameter name=port value=8443/ Parameter name=socketFactory value=org.apache.tomcat.net.SSLSocketFactory / Parameter name=keypass value=mypass/ /Connector Now restart your tomcat server, and watch as it hopefully finds everything and starts listening for SSL connections on port 8443. Twylite
Re:certificate for tomcat and ssl
Oooh yeah, one other thing. You will notice that I don't specify the keystore. Tomcat uses the default keystore for the user executing Tomcat, unless you specify the keystore in the server.xml file. I am logged in an run tomcat as Administrator (dev box, shuddup about the security ;p ), and start tomcat manually (I don't run it as a service). My keystore will actually be $USER_HOME/.keystore, which works out to something like /winnt/profiles/administrator/.keystore, but that's a nasty thing to code into your server.xml . If you have a keystore stored elsewhere, specify the location when you use keytool, and specify the location in the server.xml . Twylite
Re: Re:certificate for tomcat and ssl
Hi, value=$JAVA_HOME/jre/lib/security/jssecacerts / Parameter name=keypass value=xx / In your server.xml maybe try hard-coding the value of $JAVA_HOME ... I'm honestly not sure if it does the substitution correctly (although its not complaining ...). (Starting tcp endpoint on 8443 with org.apache.tomcat.service.http.HttpConnectionHandler is written) Sounds good - mine says pretty much the same. but a client can't get a connection to my server by the URL https://server_ip_adr:8443 (no problem with http://server_ip_adr:8443) Well, that pretty much settles it that its not using SSL. Were it to do so, you'd get about 6 unprintable characters displayed in your browser window (under IE5, at least). If I don't have my jsse.jar in the classpath, I can't even start Tomcat. If I get the keypass wrong, it gives me an error on loading. I can't see anything else wrong with your configuration. I can only stress that I'm using Tomcat 3.2.1 ... your version, if different, may have problems ...? Anyone else care to shed some light on this? Twylite
Re:Problems with ResultSet
Hi, Statement s=cn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); if (!rs.isFirst()) rs.previous(); %tr td%=rs.getString(1)%/td% } [Microsoft][ODBC Driver Manager] Invalid cursor state You never close your result set. If you try executing this more than on the same connection, it will fail. For some drivers (specifically NOT ODBC) you can use any number of new ResultSet objects over the same connection, but not reuse any one unless you close the result set. MSAccess in particular, only supports one cursor per connection, and JDBC ResultSets attempt (unsuccessfully) to share that cursor. Hence the Invalid cursor state. Also be careful with the cursor position (as reflected in the ResultSet): the initial position is before the first row, and the final position (if iterating forwards) will be after the last row. Use rs.first() to move to the beginning of the ResultSet instead of iterating to get there. Correct JDBC logic: Class.forName(DRIVER_CLASS); Connection con = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD); Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); { // This can be done in a loop ResultSet r = stmt.executeQuery(SELECT * FROM MYTABLE); if (r != null) { while (r.next()) { // Do something with r.getString(1) } r.close(); } } stmt.close(); con.close(); Alternative for inner loop: ResultSet r = stmt.executeQuery(SELECT * FROM MYTABLE); if (r != null r.last()) { while (r.previous()) { // Do something with r.getString(1) } r.close(); }
Re:Who Can Provide Me org.hsql.jdbcDriver ?Thanks!
Hi, Who Can Provide Me org.hsql.jdbcDriver ?Thanks In Advance. http://hsqldb.sourceforge.net Twylite
Re:Problem sun.misc solved - but why is authorization=null???? Please help (urgent!)
Hi I solved the problem with sun.misc (was an error in directive). But now I had a strange error. When performing form login via JDBC and trying to read out AUTHORIZATION Header the string is NULL. Why? Does form login not write Authorization in HTTP Header? Form-based logon uses a POST method to communicate logon information, not the Authorization header. That header is only used if you are using Basic logon. Things will remain that way until browsers and servers define other methods of logon. Twylite
Re:xtp in Tomcat
Hi there, Is anybody have HOWTO for using xsl stylesheets for jsp output in Tomcat? I think about something like xtp in Resin. Don't know anything about xtp or Resin, but there are a couple of possible answers to your question: 1. Take a look at Cocoon, if you're insterested in trying XSP instead of JSP. 2. To stick with JSP try the x-tags library (also from jakarta.apache.org). It allows you to parse XML within your JSP page, and format it using XSL. Alternatively you can just include an XSL formatted XML file in your output. x-tags also suppots XPath and a sortof dynamic XSL-in-JSP syntax, allowing some pretty funky stuff: (If your browser displays HTML the following may not work too well...) -- xtags:parse id=doc1 root author name=Twylite / /root /xtags:parse xtags:valueOf select=//author/@name / -- This will parse the inline XML document, and then output (to the current JSP output stream) the name attribute of the author element. Combining that with other elements of JSP, you can do stuff like: -- xtags:parse id=doc1 root article title=%= article.getTitle() % keywords=%= article.getKeywords() % / author name=%= article.getAuthor() % / /root /xtags:parse xtags:style xsl=/style/article.xsl/ -- This will parse the inline XML, then apply the specified stylesheet and include the results in the output stream. (Note: before you tear out your hair trying to use xtags:style ... the xsl= path MUST have a leading / ) 3. You can generate XML from the JSP page, and allow the browser to do the XSL formatting by associating the appropriate stylesheet with the xml generated: ?xml version=1.0 standalone=yes? ?xml-stylesheet href=mystyle.xsl type=text/xsl? SomeRootElement xmlns=http://www.mydomain.com; !-- blah -- /SomeRootElement Hope this helps Twylite
Re:Problems replacing SessionInterceptor
Hi, I've written my own version of the SessionInterceptor and placed this with my application class files (com.myapp.uril.SessionInterceptor). I updated the server.xml file to point to my version of the class instead of Tomcats by updating the following: RequestInterceptor className=com.myapp.util.SessionInterceptor noCookies=false / Unless I'm mistaken you're going to need your class files in tomcat's lib directory, or in your Java class path before you start tomcat. Anything in server.xml is server-wide, and must be available to Tomcat when you start the server. Anything in web.xml is context-wide, and must be available to the context when you first access it. Twylite