﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-learning java-文章分类-java身份认证转帖</title><link>http://www.blogjava.net/lmsun/category/2788.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 20:24:43 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 20:24:43 GMT</pubDate><ttl>60</ttl><item><title>JAAS Security in Action</title><link>http://www.blogjava.net/lmsun/articles/11031.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Thu, 25 Aug 2005 05:43:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/11031.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/11031.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/11031.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/11031.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/11031.html</trackback:ping><description><![CDATA[More than ever before, corporations are clamoring to evaluate their security architectures and identify any gaps. The Java platform, and specifically the J2EE platform, provides some of the most robust application-level security available today. The Java Authentication and Authorization Service (JAAS), which was introduced as an optional security package for the Java 2 SDK, Standard Edition, version 1.3, has been formally included as a part of the standard Java packages as of version 1.4. 
<P>This 10-Minute Solution provides a brief introduction to the JAAS (pronounced "Jazz") architecture, API, and programming model. It covers both authentication and authorization with JAAS, providing full working code examples that demonstrate JAAS security in action. <BR><BR><BR><BR>How do I implement security, one of the most important aspects of today's software applications, into my Java environment when most security implementations are inflexible, proprietary systems?<BR><BR><BR><BR>The Java Authentication and Authorization Service (JAAS) is a flexible, standardized API that supports runtime pluggability of security modules.<BR><BR></P>
<DIV><B>What Is JAAS?</B><BR>According to Sun's Web site, "The Java Authentication and Authorization Service (JAAS) is a set of packages that enables services to authenticate and enforce access controls upon users. It implements a Java version of the standard Pluggable Authentication Module (PAM) framework, and supports user-based authorization." </DIV>
<DIV>
<P>In practice, JAAS represents the new Java security standard, as it has formally been added to the JDK 1.4 code base. From an architectural standpoint, JAAS implements a Java version of the Pluggable Authentication Module (PAM) framework. First released in May 2000 by <A href="http://www.pamforum.org/" target=_blank>The PAM Forum</A>, the framework is a modularized architecture designed to support the seamless exchange of one security protocol component for another. The framework allows multiple authentication technologies and/or authentication approaches to be added without changing or interfering with any of the existing login services. PAM can be used to integrate login services with various authentication technologies, such as RSA, DCE, Kerberos, S/Key, and even to support smart card-based authentication systems. 
<P><B>Authenticating with JAAS</B><BR>JAAS authentication is deployed in a pluggable manner, using code modules that implement certain interfaces. This enables Java applications to remain decoupled from the underlying authentication technologies. Additional authentication protocols and updated authentication technologies can be plugged in at runtime without modifying the application or recompiling the source code. 
<P>The JAAS Authentication API is quite extensive. The key interfaces and classes that you need to familiarize yourself with are as follows: 
<P>
<LI><B>Callback</B> – Implementations of this interface encapsulate information (usernames, passwords, error and warning messages) that is exchanged between security services and a CallbackHandler.<BR>
<LI><B>CallbackHandler</B> – An application implements a CallbackHandler and passes it to underlying security services to facilitate interaction between the security services and the application.<BR>
<LI><B>LoginContext</B> – The LoginContext class provides the basic methods used to authenticate Subjects in a neutral manner, decoupled from the underlying authentication technology.<BR>
<LI><B>LoginModule</B> – Authentication technology providers implement this interface to provide a particular type of authentication via a pluggable module.<BR>
<LI><B>Principal</B> – The Principal interface represents the abstract notion of a principal, which can be used to represent any unique entity (individual, corporation, organization, login id, social security number, etc.) that can be authenticated.<BR>
<LI><B>Subject</B> – A Subject object represents a grouping of related information for a single entity, such as a person. One or more Principals are bound to a subject. Each Principal represents one identity for the subject (name, social security #, etc.). A Subject also maintains security-related attributes (passwords and cryptographic keys, for example).</LI></DIV>
<DIV><B>Authorization with JAAS</B><BR>JAAS authorization is built on top of JAAS authentication. It augments the existing code-centric access controls that were introduced with the Java 2 platform (JDK 1.2.x) with new user-centric access controls. In this way, JAAS authorization allows you to grant permissions based not on just what code is running but also on <I>who</I> is running it. </DIV>
<DIV>
<P>After a user has been authenticated by JAAS, the authorization API associates the Subject (created to represent the authenticated entity) with an appropriate access control context. Whenever the Subject attempts a restricted operation (database access, local file access, etc.), the Java runtime consults the policy file to determine which Principal(s) may perform the operation. If the Subject in question contains the designated Principal, the Java runtime allows the operation. Otherwise, it throws an exception. 
<P>You don't need to import additional packages to access the JAAS authorization features, because JAAS authorization is built on top of JAAS authentication. In addition to the classes and interfaces used in the authentication piece, one additional interface is of interest for the simple example in this Solution: 
<P>
<LI><B>PrivilegedAction</B> – This interface defines only one member, a method named run(). It accepts no parameters and returns type Object. A class wanting to restrict access to one or more actions implements this interface and puts the calls to the restricted functions within its run() method.</LI></DIV>
<DIV><B>See JAAS in Action</B><BR>Included with this Solution is a <A href="http://www.devx.com/assets/sourcecode/4138.zip">downloadable zip file</A> that contains all the source code and class files necessary to see JAAS authentication and authorization in action. </DIV>
<P>
<TABLE style="MARGIN-TOP: 10px; MARGIN-BOTTOM: 10px" cellSpacing=0 cellPadding=0 align=center border=0>
<TBODY>
<TR>
<TD align=middle></TD></TR>
<TR>
<TD><!-- OAS ad tag start -->
<DIV><IMG height=0 alt=advertisement hspace=0 src="http://www.devx.com/assets/HPAssets/2228.gif" width=0 align=top border=0></DIV><!-- OAS ad tag end --></TD></TR></TBODY></TABLE></P>
<DIV>
<P><B><I>Authentication Files</I></B><BR>
<LI><B>SimpleAuth.java</B> – This file contains the main() method. It creates a LoginContext object by passing in a LoginModule configuration id ("JAAS_Module") and an instance of the CallbackHandler interface. The LoginContext reads a configuration file, looking for the configuration ID. Upon finding a match, it instantiates the specified LoginModules. Each LoginModule is initialized with a Subject, a CallbackHandler, shared LoginModule state, and LoginModule-specific options. Finally, the login process is kicked off by calling the login() method on the LoginContext object (which is implemented by the LoginModule class).<BR>
<LI><B>SimpleJAAS.config</B> – This file associates configuration IDs (simple text string) with LoginModules and optional properties.<BR>
<LI><B>SimpleCallbackHandler.java</B> – This file implements the CallbackHandler interface and handles the callback events passed by the security service components.<BR>
<LI><B>SimpleLoginModule.java</B> – This file implements the LoginModule interface and interfaces between the user and the CallbackHandler to authenticate the user. It uses two arrays to maintain the set of possible usernames and passwords. The passwords are then compared by passing a PasswordCallback instance to the SimpleCallbackHandler and using the readPassword() method defined in the SimpleCallbackHandler class.<BR>
<LI><B>SimplePrincipal.java</B> – This file provides a bare-bones implementation of the Principal interface. 
<P><B><I>Authorization Files</I></B><BR></P>
<LI><B>SimpleAuthz.java</B> – This class is identical to the SimpleAuth.java class in all but one respect. After authenticating the user, it attempts a privileged action. To do this, the code obtains a reference to the current Subject and calls the doAsPrivileged() method from that object reference. We pass the Subject reference and an instance of the SimpleAction class into this method. The Java runtime then will take the supplied Subject reference and attempt to execute the privileged action defined within the run() method of the SimpleAction class.<BR>
<LI><B>SimpleAction.java</B> – This class implements the PrivilegedAction interface and defines a single method, run(). It attempts to perform a few actions that are restricted to privileged users (as defined by the policy file). If the Subject has the appropriate privileges to perform these actions, the method will execute without any trouble. Otherwise, it throws an exception.<BR>
<LI><B>SimpleJAAS.policy</B> – This file defines the activities for which permission has been granted and which code has permission to perform them (code-level access). These grant statements can further be narrowed to allow only a particular Principal (user-level access). 
<P>To test the application, run the provided script and indicate whether you want to test just authentication ('run auth') or authentication and authorization ('run authz'). When prompted for a username and password, provide any of the following pairs: <BR></P>
<LI>guest, sesame 
<LI>user1, pass1 
<LI>user2, pass2 
<P>You will receive verbose output if the debug option in the config file debug property is set to 'true'. The output will be limited if it is set to 'false'.</P></LI></DIV><img src ="http://www.blogjava.net/lmsun/aggbug/11031.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-25 13:43 <a href="http://www.blogjava.net/lmsun/articles/11031.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Implement Single Sign-on with JAAS </title><link>http://www.blogjava.net/lmsun/articles/11029.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Thu, 25 Aug 2005 05:29:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/11029.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/11029.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/11029.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/11029.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/11029.html</trackback:ping><description><![CDATA[<DIV class=articleTitle>&nbsp;</DIV>
<DIV class=articleDek>JAAS is an ideal tool for access control in a multi-user environment where users must be granted varying privileges. Learn how to implement single sign-on for multiple Web applications based on JAAS. &nbsp;</DIV>
<P>With the increasing use of distributed systems, users often need to access multiple resources to finish a single business transaction. Traditionally, users have had to sign on to all these systems, each of which may involve different usernames and authentication requirements. With the introduction of the single sign-on technique, users can login once and be authenticated for all systems involved in a given business transaction. </P>
<P>Although the single sign-on concept is appealing, implementing it is not at all easy because enterprise systems often have varying security requirements and a wide range of underlying technologies on which they are deployed. In Java environments, Java Authentication and Authorization Service (JAAS) has made implementation easier. JAAS, a significant enhancement to the Java security architecture, is an ideal tool for access control in a multi-user environment where users must be granted varying privileges. Unlike the standard JDK security model, which is code-source-based permission checking, JAAS controls access to resources with both code-source-based and user/role-based permission checking. Most importantly, the "pluggable" and stackable login module architecture that JAAS defines makes it instrumental in supporting legacy security implementations on different technologies and serves as a useful mechanism for implementing single sign-on. 
<P>Single sign-on can be implemented for applications that are deployed either locally or over a network. In the case of a network, after the user logs into the primary domain, an encrypted secure token is created and sent over the wire to other applications. In local networks, user credential data is exchanged directly between applications. Both deployment options share two key challenges: passing user credential information between involved domains and translating this information. 
<P>An enterprise application can be comprised of several Web applications, each of which may depend on different technologies and data stores to retrieve the user information it needs to authenticate the user and determine his or her privilege. If a business transaction crosses the Web application boundary, the user needs to log into each Web application and present similar credentials to each of the application authentication services. 
<P>This article demonstrates a single sign-on implementation for multiple Web applications based on JAAS. Specifically, it introduces an approach to achieving single sign-on between Web applications deployed on the same application server.<BR><BR></P>
<DIV><B>The JAAS Authentication Framework</B><BR>Before I get into the single sign-on implementation, let's examine what's under the JAAS hood. The JAAS framework is composed of two interdependent parts: an authentication part and an authorization part. The authentication part is used to determine the identity of the user, while the authorization part checks the permission of the authenticated user and controls resource access based on the user's privileges. </DIV>
<P>&nbsp;</P>
<DIV>
<P>A user has to be authenticated before he/she can access any sensitive resources. After the user is successfully authenticated, his/her principal is populated in the associated Subject class and the permissions granted to the principal are then checked by the authorization component. 
<P><B><I>Pluggable Authentication Module (PAM) Framework</I></B><BR>The JAAS authentication framework is based on Pluggable Authentication Module (PAM). JAAS authentication is performed in a pluggable fashion that allows an application to add more authentication modules. Java applications can remain independent from underlying authentication technologies, and thus both legacy and new authentication technologies can be seamlessly configured without requiring modifications to the application itself. 
<P>The JAAS authentication framework allows applications to define any number of login modules in the configuration file. The JAAS framework invokes these login modules in the order they were specified. Applications can also specify a flag to each login module to indicate the relative importance of that module. The overall authentication depends on the combined results of these individual authentication modules. 
<P>PAM allows different Web applications to authenticate users against its own data store, be it an LDAP server, relational database, NT domain, or even a file. PAM is the feature that enables developers to implement single sign-on among Web applications deployed on the same application server. 
<P><B><I>LoginModule</I></B><BR>The LoginModule interface gives developers the ability to implement different kinds of authentication technologies that can be plugged under an application. For example, one type of LoginModule may perform a username/password-based form of authentication. Other LoginModules may interface to hardware devices such as smart cards or biometric devices. 
<P>The ability to pass optional share information between login modules is the key feature I employ to achieve single sign-on among Web applications. User credential information can be shared using this option and since it is not sent across the network, there is no need for extra effort to maintain the integrity and security of the credential information.<BR><BR></P>
<DIV><B>JAAS Implementation of Single Sign-On for Multiple Web Apps</B><BR>Now let's get to the implementation of single sign-on based on JAAS for Web applications deployed on the same server. To make it easier for discussion, I use an LDAP-based login module as an example. </DIV>
<P>&nbsp;</P>
<DIV>
<P><B><I>Login Configuration for Single Sign-On</I></B><BR>When multiple Web applications are deployed on a single application server instance, usually each Web application authenticates users based on its own data store. One Web application may use a relational database to store user security information and another may use an LDAP server to authenticate users. The JAAS PAM architecture allows an enterprise application to define a stack of login modules, each of which is independent and communicates to its own data source. To achieve single sign-on, each Web application defines its own login module and all modules are stacked in a certain order in the login configuration file. 
<P>JAAS defines a configuration interface, which a user can implement to store configuration data in a file or a database. In this discussion, I assume a file-based login configuration and I use a Logistics enterprise application as an example. The Logistics enterprise application contains two Web applications: carrier Web application and shipper Web application. Carrier users log into the carrier Web application to report location and movement events for shipment and Shipper users log into the shipper Web application to query the delivery events of shipment. 
<P>If a 3PL (third-part logistics) uses this Logistics enterprise application, employees of the 3PL will need to log into both Web applications to maintain and query shipment status on behalf of both the carrier and shipper. To achieve single sign-on in this situation based on JAAS, the login configuration file needs to be defined as follows: <PRE><CODE>
LogisticsEnterpriseApplication
{
   com.cysive.framework.security.ldap.LDAPLoginModule <BR>   required name=CarrierSecurityDomain;
   com.cysive.framework.security.ldap.LDAPLoginModule <BR>   required name=ShipperSecurityDomain  useSharedState=true;
};
</CODE></PRE>
<P>Notice two LDAP login modules are defined: one for the carrier Web application and one for the shipper Web application. These two login modules may communicate to the same LDAP server or different ones, depending on the configuration (using name attribute to link to the particular configuration block) for the LDAP server. For single sign-on, the flags for both login modules are specified as required (other flags include optional, sufficient, and requisite), which means the user must be successfully authenticated by both LDAP servers. 
<P>Additionally, the attribute useSharedState is specified. If it is true, this LoginModule retrieves the username and password from the module's shared state, using "javax.security.auth.login.name" and "javax.security.auth.login.password" as the respective keys. The retrieved values are used for authentication. The username and password are set into shared state by LoginContext before invoking the login method of the login module instance. The useSharedState attribute allows all login modules to share the user's credential information, which is captured only once. 
<P><B><I>An XML-based Configuration for Login Module</I></B><BR>When the login module communicates with the data store, be it a database or an LDAP server, it requires certain configurations for common or special attributes. Using the LDAP login module for example, it will at least know the hostname of the LDAP server. Depending on your implementation, you may need different configuration parameters. <A href="javascript:showSupportItem('listing1')"><B>Listing 1</B></A> shows a sample configuration block for the two LDAP login modules defined in the previous sections. 
<P>This configuration needs to be loaded when the application server starts up so it can be shared by Web applications loaded later. I will not discuss each entry in detail but instead focus on the parts that are relevant to single sign-on. 
<P>While each block is being loaded, the initializer class is invoked. The initializer reads all the properties and registers them in the domain manager class with the name specified by the name attribute. The value of this name attribute is the same as the one specified in the login configuration file. This is how the login module entry is associated with its configuration block. 
<P>If the configuration is simple, you can even configure it when you define the login module in the configuration file, such as: <PRE><CODE>
com.cysive.framework.security.ldap.LDAPLoginModule <BR>required DriverName="oracle.jdbc.driver.OracleDriver" <BR>InitialCapacity="0" MaxCapacity="10" Properties="user=cymbio;password=cymbio <BR>URL="jdbc:oracle:thin:@jtao1:1521:jtao1"; 	
</CODE></PRE>
<P>However, if your initialization for a login module requires substantial setup, a separate initialization block is the preferred approach. 
<P>In the two sample LDAP initialization blocks, the carrier security domain configures the login module to talk to the carrier.cysive.com LDAP server while the shipper login module communicates with shipper.cysive.com. You can easily substitute one of them with a relational database login module if user security information is stored in a database.<BR><BR></P>
<DIV><B>Passing Shared Security Token Between Login Modules</B><BR>JAAS defines a LoginContext class, which provides a context for all login modules defined for an application. Its login method iterates through all login modules and calls each login module's login method. It determines the overall authentication result by combining the results of the login method returned from each login module. </DIV>
<DIV>
<P>In the login method of LoginContext, each login module defined in the configuration file is instantiated and then is passed four parameters using the initialize method of the login module (<A href="javascript:showSupportItem('listing2')">See <B>Listing 2</B></A>, exception checking is omitted for smaller code). 
<P>The following are the four parameters the initialize method passes: 
<LI><B>Subject</B> is populated with principal and credential information by the login module 
<LI><B>CallBackHandler</B> is used by the login module for capturing user credential information (such as username/password) 
<LI><B>Shared state map</B> will be used for passing user security information between login modules 
<LI><B>Options</B> are additional name/value pairs defined in the configuration file and are meaningful only for that particular login module. 
<P>The shared state map parameter is key to implementing single sign-on. After the first login module captures the user credential information, such as user name and password, it puts the information into the shared state map and passes it to other login modules on the list. The other login module has an optional parameter specified (useSharedState=true), so it simply gets the shared security information back and authenticates against its own security data store. <A href="javascript:showSupportItem('listing3')"><B>Listing 3</B></A> shows a code excerpt for the LoginModule that implements this (exception checking has been omitted to reduce the length of the code segment). 
<P><B>ReMapping of Security Information</B><BR>Using a shared state map to pass security information between login modules to achieve single sign-on requires the user to have the same credential information across all domains. I could enforce the same username and password for all domains that involve single sign-on, but that may limit legacy security systems that have varying user name and password requirements. For example, different authentication mechanisms may have their own distinctive password requirements with regard to length, characters allowed, and so forth. These requirements make using the same username and password for multiple login modules problematic. 
<P>In their paper, "Making Login Services Independent of Authentication Technologies", Vipin Samar and Charlie Lai proposed a mapping mechanism that solves this problem. This mapping enables the user's primary password to be used for encrypting the user's secondary passwords. Once the primary password is verified, the login module obtains the password by decrypting the mechanism-specific encrypted password with the primary password. It then authenticates it to its data store. How the password is encrypted depends completely on the module implementation. To use password mapping, Samar and Lai also suggest two more optional attributes be passed to the login module: </P>
<LI><B>use_mapped_pass</B> - Use the password-mapping scheme to get the actual password for this module. The module should not ask for the password if the user cannot be authenticated by the first password. Note that the process for decrypting passwords is left completely to the module. 
<LI><B>try_mapped_pass</B> - This attribute is the same as use_mapped_pass, except that if the primary password is not valid, the module should prompt the user for it. 
<P><B>Shared Map Is Key</B><BR>Single sign-on for multiple Web applications is useful when business transactions cross session context boundaries. The pluggable and stackable login module infrastructure provided by JAAS allows enterprise applications to authenticate users with different login mechanisms and technologies. Exchanging security information between login modules using the shared map is the key to implementing single sign-on. </P></LI></DIV></DIV></DIV><img src ="http://www.blogjava.net/lmsun/aggbug/11029.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-25 13:29 <a href="http://www.blogjava.net/lmsun/articles/11029.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Cross-Domain Single Sign-On Authentication with JAAS </title><link>http://www.blogjava.net/lmsun/articles/11028.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Thu, 25 Aug 2005 05:23:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/11028.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/11028.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/11028.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/11028.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/11028.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD>
<DIV class=articleTitle>Cross-Domain Single Sign-On Authentication with JAAS</DIV>
<DIV class=articleDek><BR>Leverage your existing JAAS enterprise security system to provide SSO across multiple subsystems. Implementing this J2EE security model will take your security architecture to the next level.&nbsp; 
<DIV>
<DIV class=articleAuthor>by Kyle Gabhart </DIV></DIV></DIV></TD></TR>
<TR>
<TD><IMG src="http://www.devx.com/assets/dropcaps/3590.gif">ingle sign-on (SSO) is a very hot topic. Businesses in every industry are eager to integrate legacy systems into newer applications, and SSO can alleviate the headaches users experience when trying to manage a long list of user names and passwords for various systems. Enter the Java Authentication and Authorization Service (JAAS). 
<P>As I wrote in a DevX 10-Minute Solution, "<A href="http://www.devx.com/getHelpOn/Article/9915" target=new>JAAS Security in Action</A>": JAAS “is a flexible, standardized API that supports runtime pluggability of security modules.” If you are unfamiliar with JAAS, I recommend reading that article and reviewing the downloadable code before continuing, as this article assumes an understanding of JAAS. It takes the next logical step from a security architecture standpoint: integrating your J2EE security model to provide SSO across multiple subsystems by leveraging your existing LDAP directory server, database server, or any other enterprise security system. 
<P>Before going any further, let's clarify how this article uses the term "domain": It refers to security domains (LDAP, database, etc.) and not Web domains. If you are interested in using JAAS to share authentication information between multiple Web applications, read the article "<A href="http://www.devx.com/Java/Article/7865/1763" target=new>Implement Single Sign-on with JAAS</A>" written by James Tao in October of 2002. Additionally, if you are interested in Web applications that exist across firewalls and participate in some sort of Web service exchange, read the joint <A href="http://xml.coverpages.org/ni2005-05-16-a.html" target=new>Web Single Sign-On Identify specifications</A> that Microsoft and Sun recently published. 
<P>
<P>
<H4>Securing the Enterprise</H4>Single sign-on allows users to enter security credentials once (typically by logging into a workstation or a Web application) and have those credentials propagated to each local and network application the user accesses during his or her session. Local applications exchange authentication information directly, while remote network applications exchange authentication information across the network via encrypted security tokens. 
<P>Regardless of whether the deployment scenario is local, across a network, or a combination of the two, the security challenges are the same: sharing credentials between domains, correctly interpreting the credentials once received, and managing different sets of privileges across these domains (e.g., a user could be a manager within one system, a power user in another system, and a normal user in a third). 
<P>Finally, the heterogeneous nature of most enterprise systems creates some unique challenges for SSO security architectures. Each application within the enterprise could be comprised of different technologies, operate on different platforms, access disparate data sources, and except slightly different authentication credentials for the same principal (user). In spite of these overwhelming obstacles, JAAS combined with LDAP provides a solid framework for designing and implementing a robust SSO enterprise security framework. 
<P>
<P><BR><BR></P></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD></TD></TR>
<TR>
<TD>
<H4>The Architecture</H4>The backbone of a J2EE SSO architecture is the standard J2EE security model, which is well documented in other places (see Related Resources in the left-hand column). In a nutshell, J2EE security consists of principals (users) who are associated with roles (groups) that are given privileges (authorization). These roles with assigned privileges are further organized under the concept of a realm (domain). Each realm maps users and groups to privileges within its own scope. The key to providing SSO is seamlessly connecting these different realms (and corresponding enterprise systems) without requiring the user to enter authentication information each time he or she wishes to access another system. 
<P>Consider the following example: A user logs in to an application via HTTP, authenticating herself against the server's security realm (MemoryRealm, JDBCRealm, JAASRealm, etc). The user then uses the Web application's search feature, querying the database and returning a resultlist. The database could then require that the middleware platform authenticate against the DB before performing the transaction. Finally, the user wants to update information stored in her directory server (LDAP). This is a privileged action, requiring the user to first authenticate against the LDAP realm before modifying any directory data. All three of these realms likely require slightly different authentication schemes (different user IDs, passwords, additional security tokens, etc.), but the same principal (user) is accessing them each time. 
<P>Java can provide an elegant SSO solution for the above scenario (and any number of similar scenarios) using JAAS's pluggable login module architecture. JAAS login modules facilitate the smooth integration of J2EE's security framework with various systems and their respective heterogeneous authentication mechanisms (OS, LDAP, database, etc.). These modules can be configured to share authentication data and designed to correctly identify users and roles by mapping principals and roles—even across domains with differing security schemas. 
<P>
<H4>The Components</H4>The application components required for a JAAS SSO solution include the following: 
<UL>
<LI>Two or more enterprise systems that need a common, integrated security framework 
<LI>Two or more JAAS login module classes to drive the authentication exchange between agent (user or subsystem) and callback handler 
<LI>One or more JAAS callback handler classes to respond to callback events in order to perform the actual authentication procedure(s) 
<LI>A login configuration file to define how JAAS will manage authentication across multiple security realms (configuration could even be stored in an XML file or database) </LI></UL>
<P>Assembling these components and connecting all of the pieces correctly can be a bit daunting the first time. Be sure to thoroughly test your JAAS authentication components individually with each system prior to attempting to link them and share authentication information. The process of packaging, deploying, and testing your solution should go something like this: 
<OL>
<LI>Write a login module (implement <CODE>LoginModule</CODE>, a subtype of <CODE>LoginContext</CODE>) and a callback handler (implement <CODE>CallbackHandler</CODE> interface) for authenticating against a single enterprise system (LDAP, database, etc.). 
<LI>Define the configuration for your login module (this could be as simple as an XML file containing a single statement). 
<LI>Define a UI (Web, console, or rich GUI) to capture authentication data, and then pass it to your login module. 
<LI>If this is a server-based solution (HTTP, sockets, RMI, etc.), define the J2EE security (constraints and roles) on the server in the usual way (<CODE>web.xml</CODE> or <CODE>application.xml</CODE>), and then define a realm on the server (<CODE>server.xml</CODE>) that references the JAAS login module configuration (accomplished via the <CODE>appName</CODE> attribute). Local (non-server) solutions will simply rely upon JAAS and a J2SE policy file to define security constraints and permissions. 
<LI>Start the server (specifying the login configuration file via a Java command line attribute), launch the client, and provide authentication credentials. Debug and modify as necessary to resolve any errors. 
<LI>Rinse and repeat. Continue this process as necessary until each enterprise system can successfully be authenticated via a JAAS login module. 
<LI>Finally, hook all of the individual authentication pieces together. The following section addresses this issue. </LI></OL>
<P>The above list simply gives you a brief overview of the process. For more details on how to actually accomplish these steps, please consult the links in the Related Resources space. 
<P>
<P><BR><BR></P></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD></TD></TR>
<TR>
<TD>
<H4>Sharing Authentication Across Domains</H4>The JAAS configuration file mentioned earlier defines configuration IDs, which contain one or more <CODE>LoginModule</CODE> definitions and corresponding attributes. The key to sharing authentication information across security domains is to have a single JAAS configuration ID that lists multiple login modules, with the second, third, and following modules specifying the <CODE>useSharedState</CODE> attribute as <CODE>true</CODE> (allowing security credentials to be shared). 
<P>The following is a sample configuration involving two systems, LDAP and an Oracle database, included within the same SSO architecture: <PRE><CODE>
BasicAuth {
	com.xyz.ldap.LDAPLoginModule 
required name=LDAPSecurityDomain;
};

DBAccessAuth {
	com.xyz.ldap.LDAPLoginModule 
required name=LDAPSecurityDomain;
com.xyz.db.OracleLoginModule
required name=OracleSecurityDomain
useSharedState=true;
};
</CODE></PRE>
<P>Two configurations are defined (BasicAuth and DBAccessAuth) to provide the flexibility of authenticating a user against one or both systems. 
<P>To implement this, the first system (LDAP) is treated as the primary system. The corresponding login module should be setup as the security realm for the J2EE container (using the BasicAuth configuration). Once a user has authenticated against the primary system (see <A href="javascript: showSupportItem('figure1');">Figure 1</A>), she can have her security credentials propagated to the other system(s) in the chain (using the DBAccessAuth) that require authenticated access (see <A href="javascript: showSupportItem('figure2');">Figure 2</A>). 
<P>
<TABLE cellSpacing=0 cellPadding=5 width=313 border=0>
<TBODY>
<TR>
<TD vAlign=top><A href="javascript: showSupportItem('figure1');"><IMG height=165 alt="Click to enlarge" src="http://www.devx.com/assets/articlefigs/13542.gif" width=175 border=0></A></TD>
<TD width=12></TD></TR>
<TR>
<TD class=smallfont><A href="javascript: showSupportItem('figure1');">Figure 1</A>: Initial System Authentication/Authorization Process Through JAAS</TD></TR></TBODY></TABLE>
<P>
<TABLE cellSpacing=0 cellPadding=5 width=313 border=0>
<TBODY>
<TR>
<TD vAlign=top><A href="javascript: showSupportItem('figure2');"><IMG height=165 alt="Click to enlarge" src="http://www.devx.com/assets/articlefigs/13543.gif" width=175 border=0></A></TD>
<TD width=12></TD></TR>
<TR>
<TD class=smallfont><A href="javascript: showSupportItem('figure2');">Figure 2</A>: Subsequent System Authentication/Authorization Process Through JAAS</TD></TR></TBODY></TABLE>
<P>This simple example contains only two subsystems, but a more complex system could include as many JAAS login modules as systems that need to share security credentials. The key difference between how authentication occurs with the two subsystems is that the primary system has JAAS authentication handled automatically (the container manages the process since the login module is configured as a security realm). The secondary subsystem (as well as any subsequent systems) must be called programmatically via the <CODE>login()</CODE> method of LoginContext: <PRE><CODE>
LoginContext ctx = new LoginContext( "DBAccessAuth", new SimpleCallbackHandler() );
</CODE></PRE>
<P>The above example assumed a fairly ideal situation in which the user's security credentials were the same for both subsystems. In real life, this is rarely the case. You often find yourself needing to integrate legacy systems with new applications, each requiring different credentials. You can accomplish this by using the original authentication information to unlock a secured datastore that houses secondary authentication information for the specified principal (one or more sets of credentials). Once you've obtained this other authentication information, you then can use it to authenticate transparently against any secondary systems. (For more details on this approach, read Vipin Samar and Charlie Lai's article (PDF): "<A href="http://www.sun.com/software/solaris/pam/pam.external.pdf" target=new>Making Login Services Independent of Authentication Technologies</A>".) 
<P>Voila! Single sign-on across multiple security domains by mapping primary credentials gathered from the user to secondary credentials stored on the server and used to authenticate transparently against other enterprise systems. 
<P>
<H4>Single SSO in Your Enterprise Framework</H4>SSO is a popular feature of modern enterprise systems. Unfortunately, implementing SSO can be difficult and error-prone. This brief article provides a high-level overview and guide for architects, developers, and/or managers who are interested in implementing a SSO security architecture within their current enterprise frameworks. 
<P>
<P>
<DIV class=""><I><B>Kyle Gabhart</B> is a Senior Principal Information Systems Architect with L-3 Communications, Link Simulation and Training Division. Author of dozens of articles and books, Kyle has served as a consultant, trainer, and mentor for Fortune 500 companies, including American Express, J.P. Morgan-Chase, Goldman Sachs, and Verizon. Find Kyle on the Web at <A href="http://www.gabhart.com/" target=new>http://www.gabhart.com</A> and reach him by email at <A href="mailto:rkgabhart@link.com">rkgabhart@link.com</A>. </I></DIV><BR></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/lmsun/aggbug/11028.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-25 13:23 <a href="http://www.blogjava.net/lmsun/articles/11028.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JCIFS NTLM HTTP Authentication</title><link>http://www.blogjava.net/lmsun/articles/10585.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Sat, 20 Aug 2005 05:45:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10585.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10585.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10585.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10585.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10585.html</trackback:ping><description><![CDATA[A common requirement of websites on corporate Intranets is NTLM HTTP authentication also sometimes referred to as Single Sign On (SSO). Microsoft Internet Explorer has the ability to negotiate NTLM password hashes over an HTTP session using base 64 encoded NTLMSSP messages. This is a staple feature of IIS but Java application servers too can use jCIFS to authenticate MSIE clients against a domain controller. This is a useful feature because many of the tasks surrounding user management now fall back to computer support and HR. It is not necessary to add and remove users as they join and leave the company. Perhaps most important from a user's perspective; they do not need to enter a username or password if their workstation is a member of the domain. The password hashes generated when they logged on to their workstation will be negotiated during the initial request for a session, passed through jCIFS, and validated against a PDC or BDC. This also makes the users domain, username, and password available for managing session information, profiles, preferences, etc. Using the jCIFS Servlet Filter it is trivial to add NTLM HTTP authentication support to your site. It is also possible to build custom authentication modules using the <TT>NtlmSsp</TT> classes directly. This Filter scales very well primarily because sessions are multiplexed over transports. But this functionality is not without caveats. 
<UL>
<LI><A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#install"><STRONG><FONT face=Arial color=#000080>Installation and Setup</FONT></STRONG></A> 
<LI><A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#basic"><STRONG><FONT face=Arial color=#000080>Non MSIE Clients and "Basic" Authentication</FONT></STRONG></A> 
<LI><A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#props"><STRONG><FONT face=Arial color=#000080>JCIFS Properties Meaningful to NTLM HTTP Authentication</FONT></STRONG></A> 
<LI><A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#restart"><STRONG><FONT face=Arial color=#000080>Must Restart The Container</FONT></STRONG></A> 
<LI><A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#tomcat"><STRONG><FONT face=Arial color=#000080>Tomcat</FONT></STRONG></A> 
<LI><A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#url"><STRONG><FONT face=Arial color=#000080>MalformedURLException: unknown protocol: smb</FONT></STRONG></A> 
<LI><A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#transparent"><STRONG><FONT face=Arial color=#000080>Transparent Authentication and the Network Password Dialog</FONT></STRONG></A> 
<LI><A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#adpolicy"><STRONG><FONT face=Arial color=#000080>Personal Workstation AD Security Policy</FONT></STRONG></A> 
<LI><A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#post"><STRONG><FONT face=Arial color=#000080>HTTP POST and Protecting Sub-Content</FONT></STRONG></A> 
<LI><A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#signing"><STRONG><FONT face=Arial color=#000080>SMB Signatures and Windows 2003</FONT></STRONG></A> 
<LI><A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#proto"><STRONG><FONT face=Arial color=#000080>NTLM HTTP Authentication Protocol Details</FONT></STRONG></A> </LI></UL><I><B>Note:</B> This functionality is a non-conformant extension to HTTP conceived entirely by Microsoft. It inappropriately uses HTTP headers and therefore may not work with all Servlet containers or may stop working with a new release of your application server. Also, this flavor of password encryption is not very secure so under no circumstances should it be used to authenticate clients on the Internet.</I> 
<P></P><I><B>Note:</B> Don't forget to restart the container after changing jCIFS init-parameters. JCIFS must use the container class loader and jCIFS properties are only read once when jCIFS classes are initialized.</I> <A name=install></A>
<H2>Installation and Setup</H2>Put the <A href="http://jcifs.samba.org/src/"><STRONG><FONT face=Arial color=#000080>latest jCIFS jar</FONT></STRONG></A> file in the <TT>lib/</TT> directory of your webapp [1]. Because jCIFS properties are loaded once when the jCIFS classes are first accessed, it is necessary to actually stop and restart the container if any jCIFS properties have been changed. Below are two web.xml configurations. Note that the <TT>jcifs.smb.client.domain</TT> and <TT>jcifs.smb.client.domainController</TT> properties are mutually exclusive. 
<H3>Production web.xml Example</H3>A minimalistic web.xml file with <TT>filter</TT> and <TT>filter-mapping</TT> directives might look like the following: <PRE>&lt;filter&gt;
    &lt;filter-name&gt;NtlmHttpFilter&lt;/filter-name&gt;
    &lt;filter-class&gt;jcifs.http.NtlmHttpFilter&lt;/filter-class&gt;

    &lt;init-param&gt;
        &lt;param-name&gt;jcifs.smb.client.domain&lt;/param-name&gt;
        &lt;param-value&gt;NYC-USERS&lt;/param-value&gt;
    &lt;/init-param&gt;
    &lt;init-param&gt;
        &lt;param-name&gt;jcifs.netbios.wins&lt;/param-name&gt;
        &lt;param-value&gt;10.169.10.77,10.169.10.66&lt;/param-value&gt;
    &lt;/init-param&gt;
&lt;/filter&gt;

&lt;filter-mapping&gt;
    &lt;filter-name&gt;NtlmHttpFilter&lt;/filter-name&gt;
    &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
</PRE><SMALL>This filter section illustrates the setup for authenticating clients against the domain <TT>NYC-USERS</TT>. This is suitable for large numbers of concurrent users as jCIFS will cycle through domain controllers and use an alternate WINS server if necessary.</SMALL> 
<P></P>The above will authenticate users accessing all content against the domain <TT>NYC-USERS</TT>. The WINS server <TT>10.169.10.77</TT> will be queried to resolve <TT>NYC-USERS</TT> to an IP address of a domain controller. If that WINS server is not responding, <TT>10.169.10.66</TT> will be queried. 
<H3>Alternate web.xml Example</H3>The below example filter section illistrates how to specify the IP address of the domain controller specifically using the <TT>jcifs.http.domainController</TT> property. The target machine does not need to be a real domain controller -- it could be just a workstation. Also illustrated below is the <TT>jcifs.smb.client.logonShare</TT> property. This will cause jCIFS to attempt to access the resource <TT>\\192.168.2.15\JCIFSACL</TT> when authenticating users. By creating that share and changing the Access Control List only certain users or groups of users will have access to your website. <PRE>&lt;filter&gt;
    &lt;filter-name&gt;NtlmHttpFilter&lt;/filter-name&gt;
    &lt;filter-class&gt;jcifs.http.NtlmHttpFilter&lt;/filter-class&gt;

    &lt;init-param&gt;
        &lt;param-name&gt;jcifs.http.domainController&lt;/param-name&gt;
        &lt;param-value&gt;192.168.2.15&lt;/param-value&gt;
    &lt;/init-param&gt;
    &lt;init-param&gt;
        &lt;param-name&gt;jcifs.smb.client.logonShare&lt;/param-name&gt;
        &lt;param-value&gt;JCIFSACL&lt;/param-value&gt;
    &lt;/init-param&gt;
&lt;/filter&gt;

&lt;filter-mapping&gt;
    &lt;filter-name&gt;NtlmHttpFilter&lt;/filter-name&gt;
    &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
</PRE><SMALL>This filter section illustrates the setup for authenticating against a <TT>JCIFSACL</TT> share for testing or a site with a small number of concurrent users (e.g. 1000)</SMALL> 
<P></P>Either a <TT>jcifs.smb.client.domain</TT> or <TT>jcifs.smb.client.domainController</TT> property is required. This will be suitable to authenticate clients that are members of the specified domain as well as other domains with which it has trusts relationships. 
<P></P>Running the <TT>NtlmHttpAuthExample.java</TT> example should be a suitable test of the Filter. 
<BLOCKQUOTE>
<H2>NTLM HTTP Authentication Example</H2>NYC-USERS\MIALLEN successfully logged in 
<H3>Please submit some form data using POST</H3>
<FORM action="javascript:alert('No, this isn\'t a real example. Set up your own.')" method=post><INPUT value=hello name=field1> <INPUT type=submit value=提交查询内容> </FORM>field1 = hello </BLOCKQUOTE><SMALL>The significance of the POST test is that after negotiating NTLM HTTP Authentication once, IE will not POST any form data until it has negotiated the password hashes again.</SMALL> 
<P></P>If the NTLM HTTP Authentication Filter is not enabled something like the following will be displayed: 
<BLOCKQUOTE>null successfully logged in </BLOCKQUOTE>Notice the user was permitted access. Unlike this example, developers might add an additional check to make sure <TT>getRemoteUser</TT> does not return <TT>null</TT>. <A name=basic></A>
<H2>Non MSIE Clients and "Basic" Authentication</H2>NTLM HTTP authentication is only supported by MSIE transparently. Mozilla 1.6 supports NTLM HTTP negotiation but it will always prompt the user for credentials by default (although the Mozilla documentation on <A href="http://www.mozilla.org/projects/netlib/integrated-auth.html"><STRONG><FONT face=Arial color=#000080>Integrated Authentication</FONT></STRONG></A> describes how to make it transparent to the user for trusted sites). For other clients it is possible to use basic authentication to pass NTLM password credentials. This is strongly discouraged if SSL is not being used because it sends these credentials in plain text. It would not be difficult for another user to download and install a program to "snoop" LAN traffic and obtain other user's passwords. 
<P></P>Regardless, this functionality has been added to the <TT>NtlmHttpFilter</TT> and <TT>NtlmServlet</TT> (for pre 2.3 servlet containers) although it is disabled by default. To enable this capability set the <TT>jcifs.http.basicRealm</TT>, <TT>jcifs.http.enableBasic</TT>, and <TT>jcifs.http.insecureBasic</TT> properties described in the table below. <A name=props></A>
<H2>JCIFS Properties Meaningful to NTLM HTTP Authentication</H2>All parameters that begin with 'jcifs.' will be set as jCIFS properties which means that any jCIFS properties may be used as init parameters. <B>These properties must be set before jCIFS classes are used</B>. For a complete list of jCIFS properties refer to the <A href="http://jcifs.samba.org/src/docs/api/index.html" target=_top><STRONG><FONT face=Arial color=#000080>overview page of the API documentation</FONT></STRONG></A>. Here is a select subset of jCIFS properties with additional notes in the context of NTLM HTTP Authentication. 
<P></P>
<TABLE>
<TBODY>
<TR>
<TD width="20%"><B>jcifs.smb.client.domain</B></TD>
<TD>The NT domain against which clients should be authenticated. Generally it is necessary to also set the <TT>jcifs.netbios.wins</TT> parameter or a domain controller may not be found. This parameter will be ignored for NTLM HTTP authentication purposes if a <TT>jcifs.http.domainController</TT> property is specified (although they can be used together for "preauthenctication" as described in the <A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#signing"><STRONG><FONT face=Arial color=#000080>SMB Signatures and Windows 2003</FONT></STRONG></A> section below). </TD></TR>
<TR>
<TD width="20%"><B>jcifs.http.domainController</B></TD>
<TD>The IP address of any SMB server that should be used to authenticate HTTP clients with the <TT>NtlmHttpFilter</TT> class. If this is not specified the <TT>jcifs.smb.client.domain</TT> 0x1C NetBIOS group name will be queried. If these queries fail an <TT>UnknownHostException</TT> will be thrown. It is not necessary for this to specify a real domain controller. The IP address of a workstation will do for simple purposes. </TD></TR>
<TR>
<TD width="20%"><B>jcifs.http.basicRelm</B></TD>
<TD>The realm for basic authentication. This property defaults to 'jCIFS'. </TD></TR>
<TR>
<TD width="20%"><B>jcifs.http.enableBasic</B></TD>
<TD>Setting this property to <TT>true</TT> enables basic authentication over HTTPS only. </TD></TR>
<TR>
<TD width="20%"><B>jcifs.http.insecureBasic</B></TD>
<TD>Setting this property to <TT>true</TT> enables basic authentication over plain HTTP. This configuration passes user credentials in plain text over the network. It should not be used in environment where security is required. </TD></TR>
<TR>
<TD width="20%"><B>jcifs.http.loadBalance</B></TD>
<TD>If a <TT>jcifs.smb.client.domain</TT> property is specified (and <TT>domainController</TT> is <I>not</I> specified) the <TT>NtlmHttpFilter</TT> will query for domain controllers by name. If this property is <TT>true</TT> the Filter will rotate through the list of domain controllers when authenticating users. The default value is <TT>true</TT>. The <TT>jcifs.netbios.lookupRespLimit</TT> property can also be used to limit the number of domain controllers used. </TD></TR>
<TR>
<TD width="20%"><B>jcifs.netbios.lookupRespLimit</B></TD>
<TD>The 0x1C NetBIOS name query returns a list of domain controllers. It is believed that the servers at the top of this list should be favored. This property limits the range of servers returned by name queries. The default value is 5 meaning the top 5 domain controllers will be used. </TD></TR>
<TR>
<TD width="20%"><B>jcifs.netbios.wins</B></TD>
<TD>The IP address of the WINS server. This is required when accessing hosts on different subnets (like a domain controller by name) and it is highly recommended if a wins server is available. </TD></TR>
<TR>
<TD width="20%"><B>jcifs.smb.client.laddr</B></TD>
<TD>The ip address of the local interface the client should bind to if it is different from the default. For example if jCIFS is used to authenticate clients on one interface and the domain controller for those clients is accessible only on another interface of a webserver with two NICs it may be necessary to specify which interface jCIFS should use. </TD></TR>
<TR>
<TD width="20%"><B>jcifs.netbios.laddr</B></TD>
<TD>The ip address of the local interface the client should bind to for name queries if it is different from the default. Likely set to the same as the above property. </TD></TR>
<TR>
<TD width="20%"><B>jcifs.smb.client.attrExpirationPeriod</B></TD>
<TD>Attributes of a file are cached for <CODE>attrExpirationPeriod</CODE> milliseconds. The default is 5000 but the <TT>NetworkExplorer</TT> servlet will attempt to set this property to 120000. Otherwise, when listing large directories, the attributes of <TT>SmbFiles</TT> may expire within the default period resulting in a large number of additional network messages and severe performance degradation. </TD></TR>
<TR>
<TD width="20%"><B>jcifs.smb.client.soTimeout</B></TD>
<TD>To prevent the client from holding server resources unnecessarily, sockets are closed after this time period if there is no activity. This time is specified in milliseconds. The default is 15000 however when NTLM HTTP Authentication is used, the <TT>NtlmHttpFilter</TT> will attempt to set this value to 5 minutes so that frequent calls to <TT>SmbSession.logon()</TT> do not provoke redundant messages being submitted to the domain controller. If it is not desirable to cache password hashes set this value back to 15000. </TD></TR>
<TR>
<TD width="20%"><B>jcifs.netbios.cachePolicy</B></TD>
<TD>When a NetBIOS name is resolved with the NbtAddress class it is cached to reduce redundant name queries. This property controls how long, in seconds, these names are cached. The default is 30 seconds, 0 is no caching, and -1 is forever. When NTLM HTTP Authentication is used, <TT>NtlmHttpFilter</TT> will attempt to set this value to 20 minutes so that frequent queries for a domain controller will be cached. </TD></TR></TBODY></TABLE><A name=restart></A>
<H2>Must Restart The Container</H2>If you change any jcifs properties or replace an existing jcifs jar file with a different one, the container must be restarted. This is because most jcifs properties are retrieved only once when classes are first loaded. <A name=tomcat></A>
<H2>Tomcat</H2>Tomcat requires that all filter directives be adjacent to one another, all filter-mapping directives appear adjacent to one another, all servlet directives ... and so on. This is because Tomcat validates the web.xml against the deployment descriptor DTD. <A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html#url"></A>
<H2>MalformedURLException: unknown protocol: smb</H2>If you get the following exception try upgrading to jcifs-0.7.0b12 or later. Also read the <A href="http://jcifs.samba.org/src/docs/faq.html"><STRONG><FONT face=Arial color=#000080>FAQ</FONT></STRONG></A>. <PRE>Exception MalformedURLException: unknown protocol: smb
      at java.net.URL.(URL.java:480)
      at java.net.URL.(URL.java:376)
      at java.net.URL.(URL.java:330)
      at jcifs.smb.SmbFile.(SmbFile.java:355)
      ...
</PRE><A name=transparent></A>
<H2>Transparent Authentication and the Network Password Dialog</H2>If the Filter is working properly the Network Password Dialog should never appear. However there are several requirements that must be met for a web browser to transparently negotiate credentials using NTLM HTTP authenication. If any of these requirements are not met, the default behavior is to present the user with the Network Password dialog. The requirements are: 
<P></P>
<OL>
<LI>The client must be logged into the Windows NT domain identified by the jcifs.smb.client.domain parameter (or the domain of the host identified by the jcifs.smb.client.domainController parameter if it is used instead). The client may also be logged into a domain that has a trust relationship with the target domain. Indeed it is not uncommon to configure workstations to join a different domain from those of users. Note that Windows 95/98/ME systems cannot really join a domain but can be configured to do so enough to participate in transparent NTLM HTTP authentication. 
<LI>Only Internet Explorer will negotiate NTLM HTTP authentication transparently. Mozilla will always prompt the user for credentials (someone please notify us when/if this is not true anymore). At the time this FAQ was written it was not known which other browsers, if any, can negotiate NTLM HTTP authenication transparently. 
<LI>Either the target URL must contain a server in the local domain (e.g. ws1.mycompany.com) or the client's security settings must be changed (e.g. Tools &gt; Internet Options &gt; Security &gt; Local Intranet &gt; Sites &gt; Advanced &gt; add your site). If the URL does not contain a URL in the defined IntrAnet zone (e.g. not an IP address), Internet Explorer will assume that the server is in the IntErnet zone and present the user with the Network Password dialog. It would be very bad if a server on the Internet could convince IE to send it your NTLM password hashes. These hashes are easily cracked with brute force dictionary attacks. To prevent this scenario, IE tries to distinguish between Intranet sites and Internet sites. Here are some important notes to consider when deploying a site with NTLM HTTP Authentication regardless of whether or not jCIFS is used to do it. 
<UL>
<LI>Internet Explorer May Prompt You for a Password<BR><A href="http://support.microsoft.com/default.aspx?scid=kb;en-us;Q258063"><STRONG><FONT face=Arial color=#000080>http://support.microsoft.com/default.aspx?scid=kb;en-us;Q258063</FONT></STRONG></A> 
<LI>How to Use Security Zones in Internet Explorer<BR><A href="http://support.microsoft.com/default.aspx?scid=kb;en-us;Q174360"><STRONG><FONT face=Arial color=#000080>http://support.microsoft.com/default.aspx?scid=kb;en-us;Q174360</FONT></STRONG></A> 
<LI>An Intranet Site Is Identified as an Internet Site When You Use an FQDN or IP Address<BR><A href="http://support.microsoft.com/default.aspx?scid=kb;en-us;Q303650"><STRONG><FONT face=Arial color=#000080>http://support.microsoft.com/default.aspx?scid=kb;en-us;Q303650</FONT></STRONG></A> </LI></UL>
<LI>The user's credentials must be valid. For example if the account has expired, been disabled or is locked out the Network Password dialog will appear. To determine which error was at fault it will be necessary to modify the NtlmHttpFilter to inspect the SmbAuthException in doFilter. 
<LI>The jCIFS client must support the lmCompatibility level necessary for communication with the domain controller. If the server does not permit NTLMv1 try to set jcifs.smb.lmCompatibility = 3. </LI></OL><A name=adpolicy></A>
<H2>Personal Workstation AD Security Policy</H2>If your Active Directory security policy requires that users only log into the domain from their personal workstations JCIFS will fail to authenticate and the server security log will have entries like "\\JCIFS10_40_4A cannot be authorized". This occurs because the domain controller is failing to resolve the dynamically generated "calling name" submitted by the client during protocol negotiation. To get around this it is necessary to set the <TT>jcifs.netbios.hostname</TT> property to a valid NetBIOS name that can be resolved by the NetBIOS name service (e.g. WINS) and add that name to the AD security policy as a permitted client. 
<P></P>For example, you can set this property using an init-paremeter in the web.xml file for the NTLM HTTP filter as follows: <PRE>&lt;init-parameter&gt;
    &lt;parameter-name&gt;jcifs.netbios.hostname&lt;/parameter-name&gt;
    &lt;parameter-value&gt;MYHOSTNAME&lt;/parameter-value&gt;
&lt;/init-parameter&gt;
</PRE><A name=post></A>
<H2>HTTP POST and Protecting Sub-Content</H2>Once IE has negotiated NTLM HTTP authentication it will proactively renegotiate NTLM for POST requests for all content associated with the server (based on IP?). Therefore when using HTTP POST requests it is not possible to restrict access to some content on the server as IE will attempt and fail to negotiate NTLM (standard IE error page?). This is a protocol limitation and there does not appear to be a way to convince IE to stop proactively negotiating for POST requests once it has been determined that the server is capable of negotiating NTLM authentication. <A name=signing></A>
<H2>SMB Signatures and Windows 2003</H2>If the domain controller against which you are authenticating clients requires SMB signatures (Windows 2003 does by default), it is recommended that you provide init-parameters for the <TT>jcifs.smb.client.{domain,username,password}</TT> to perform "preauthentication" for each transport to a domain contoller so that a proper SMB signing key will be generated. In fact, this may be necessary for proper operation; it has been observed that NT 4.0 does not check the signatures of authentication requests but the behavior has not been confirmed in all environments. If the Filter works for the first authentication but fails with a <I>second</I> user shortly thereafter this would suggest that signing was established but subsequent authentications are failing due to the lack of a good signing key. Additionally, without a proper signing key certain requests (<TT>SMB_COM_TREE_DISCONNECT</TT> and <TT>SMB_COM_LOGOFF_ANDX</TT>) will cause signature verification failures (although they are harmless to the client). 
<P></P>A third solution for signature issues is to change the <TT>jcifs.smb.client.ssnLimit</TT> to 1. This will require that every authentication uses a separate transport. Because the MAC signing key is only used on SMB communication occuring after the initial authentication, signing will be effectively ignored. However, this solution will significantly reduce scalability as each authentication will open it's own transport. For this reason the second solution of using a "workstation account" to preauthenticate transports is considered the superior method and should be used by default for servers that requires signatures. <A name=proto></A>
<H2>NTLM HTTP Authentication Protocol Details</H2>The NTLM HTTP Authentication process is described well in these documents: 
<P><A href="http://davenport.sourceforge.net/ntlm.html"><STRONG><FONT face=Arial color=#000080>http://davenport.sourceforge.net/ntlm.html</FONT></STRONG></A> <BR><A href="http://www.innovation.ch/java/ntlm.html"><STRONG><FONT face=Arial color=#000080>http://www.innovation.ch/java/ntlm.html</FONT></STRONG></A> </P>The process can be summarized as a 3 request/response "handshake". So <TT>doGet()</TT> will be called three times. The first is the initial request. A <TT>401 Unauthorized</TT> is sent back to which IE submits a special message encoded in a header. Another <TT>401 Unauthorized</TT> is sent back after which IE submits the password hashes. This is where jCIFS comes in. The password hashes alone are useless. You must check their authenticity against the password database on a server somewhere (actually you can specify the IP of a plain workstation or any other SMB server). Otherwise a user who's workstation is not a member of the domain will get a password dialog into which they could put anything and it would let them in. This is what pretty much all the examples seen in various forums do. Don't be fooled. 
<P></P><SMALL>[1] Due to restrictions in how protocol handlers are loaded, if the SMB URL protocol handler is to be used (meaning you want to access SMB resources with smb:// URLs) within your application it is necessary for the jCIFS jar to be loaded by the <TT>System</TT> class loader. This can usually be achived by placing it in the container <TT>lib/</TT> directory. However, for containers that load servlet classes in a child classloaders (Tomcat) this too will cause problems as jCIFS will not be able to load <TT>javax.servlet.*</TT> classes. To get the filter and the URL protocol handler to operate together requires some experimentation and depends on the container being used.</SMALL> <img src ="http://www.blogjava.net/lmsun/aggbug/10585.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-20 13:45 <a href="http://www.blogjava.net/lmsun/articles/10585.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NTLM Authentication Scheme for HTTP</title><link>http://www.blogjava.net/lmsun/articles/10507.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Fri, 19 Aug 2005 05:54:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10507.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10507.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10507.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10507.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10507.html</trackback:ping><description><![CDATA[<H1><A name=intro>Introduction</A></H1>
<P>This is an attempt at documenting the undocumented NTLM authentication scheme used by M$'s browsers, proxies, and servers (MSIE and IIS); this scheme is also sometimes referred to as the NT challenge/response (NTCR) scheme. Most of the info here is derived from three sources (see also the <A href="http://www.innovation.ch/java/ntlm.html#resources">Resources</A> section at the end of this document): Paul Ashton's work on the <A href="http://www.argo.demon.co.uk/nt/ntie.html">NTLM security holes</A>, the <A href="http://de.samba.org/samba/ftp/docs/htmldocs/ENCRYPTION.html">encryption documentation</A> from <A href="http://samba.anu.edu.au/samba/">Samba</A>, and network snooping. Since most of this info is reverse-engineered it is bound to contain errors; however, at least one client and one server have been implemented according to this data and work successfully in conjunction with M$'s browsers, proxies and servers. 
<P>Note that this scheme is not as secure as <A href="http://www.ietf.org/rfc/rfc2617.txt">Digest</A> and some other schemes; it is slightly better than the Basic authentication scheme, however. 
<P>Also note that this scheme is <STRONG>not</STRONG> an http authentication scheme - it's a connection authentication scheme which happens to (mis-)use http status codes and headers (and even those incorrectly). 
<H2><A name=handshake>NTLM Handshake</A></H2>
<P>When a client needs to authenticate itself to a proxy or server using the NTLM scheme then the following 4-way handshake takes place (only parts of the request and status line and the relevant headers are shown here; "C" is the client, "S" the server): <PRE>    1: C  --&gt; S   GET ...
    
    2: C &lt;--  S   401 Unauthorized
                  WWW-Authenticate: NTLM
    
    3: C  --&gt; S   GET ...
                  Authorization: NTLM &lt;base64-encoded type-1-message&gt;
    
    4: C &lt;--  S   401 Unauthorized
                  WWW-Authenticate: NTLM &lt;base64-encoded type-2-message&gt;
    
    5: C  --&gt; S   GET ...
                  Authorization: NTLM &lt;base64-encoded type-3-message&gt;
    
    6: C &lt;--  S   200 Ok
</PRE>
<H2><A name=messages>Messages</A></H2>The three messages sent in the handshake are binary structures. Each one is described below as a pseudo-C struct and in a memory layout diagram. <VAR>byte</VAR> is an 8-bit field; <VAR>short</VAR> is a 16-bit field. All fields are unsigned. Numbers are stored in little-endian order. Struct fields named <VAR>zero</VAR> contain all zeroes. An array length of "*" indicates a variable length field. Hexadecimal numbers and quoted characters in the comments of the struct indicate fixed values for the given field. 
<P>The field <VAR>flags</VAR> is presumed to contain flags, but their significance is unknown; the values given are just those found in the packet traces. 
<H3><A name=type1msg>Type-1 Message</A></H3>
<P>This message contains the host name and the NT domain name of the client. <PRE>    struct {
        byte    protocol[8];     // 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'
        byte    type;            // 0x01
        byte    zero[3];
        short   flags;           // 0xb203
        byte    zero[2];

        short   dom_len;         // domain string length
        short   dom_len;         // domain string length
        short   dom_off;         // domain string offset
        byte    zero[2];

        short   host_len;        // host string length
        short   host_len;        // host string length
        short   host_off;        // host string offset (always 0x20)
        byte    zero[2];

        byte    host[*];         // host string (ASCII)
        byte    dom[*];          // domain string (ASCII)
    } type-1-message
</PRE><PRE>                 0       1       2       3
             +-------+-------+-------+-------+
         0:  |  'N'  |  'T'  |  'L'  |  'M'  |
             +-------+-------+-------+-------+
         4:  |  'S'  |  'S'  |  'P'  |   0   |
             +-------+-------+-------+-------+
         8:  |   1   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
        12:  | 0x03  | 0xb2  |   0   |   0   |
             +-------+-------+-------+-------+
        16:  | domain length | domain length |
             +-------+-------+-------+-------+
        20:  | domain offset |   0   |   0   |
             +-------+-------+-------+-------+
        24:  |  host length  |  host length  |
             +-------+-------+-------+-------+
        28:  |  host offset  |   0   |   0   |
             +-------+-------+-------+-------+
        32:  |  host string                  |
             +                               +
             .                               .
             .                               .
             +             +-----------------+
             |             | domain string   |
             +-------------+                 +
             .                               .
             .                               .
             +-------+-------+-------+-------+
</PRE>The host and domain strings are ASCII (or possibly ISO-8859-1), are uppercased, and are not nul-terminated. The host name is only the host name, not the FQDN (e.g. just "GOOFY", not "GOOFY.DISNEY.COM"). The offsets refer to the offset of the specific field within the message, and the lengths are the length of specified field. For example, in the above message <CODE>host_off = 32</CODE> and <CODE>dom_off = host_off + host_len</CODE>. Note that the lengths are included twice (for some unfathomable reason). 
<H3><A name=type2msg>Type-2 Message</A></H3>
<P>This message contains the server's NTLM challenge. <PRE>    struct {
        byte    protocol[8];     // 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'
        byte    type;            // 0x02
        byte    zero[7];
        short   msg_len;         // 0x28
        byte    zero[2];
        short   flags;           // 0x8201
        byte    zero[2];

        byte    nonce[8];        // nonce
        byte    zero[8];
    } type-2-message
</PRE><PRE>                 0       1       2       3
             +-------+-------+-------+-------+
         0:  |  'N'  |  'T'  |  'L'  |  'M'  |
             +-------+-------+-------+-------+
         4:  |  'S'  |  'S'  |  'P'  |   0   |
             +-------+-------+-------+-------+
         8:  |   2   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
        12:  |   0   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
        16:  |  message len  |   0   |   0   |
             +-------+-------+-------+-------+
        20:  | 0x01  | 0x82  |   0   |   0   |
             +-------+-------+-------+-------+
        24:  |                               |
             +          server nonce         |
        28:  |                               |
             +-------+-------+-------+-------+
        32:  |   0   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
        36:  |   0   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
</PRE>The nonce is used by the client to create the LanManager and NT responses (see <A href="http://www.innovation.ch/java/ntlm.html#hashes">Password Hashes</A>). It is an array of 8 arbitrary bytes. The message length field contains the length of the complete message, which in this case is always 40. 
<H3><A name=type3msg>Type-3 Message</A></H3>
<P>This message contains the username, host name, NT domain name, and the two "responses". <PRE>    struct {
        byte    protocol[8];     // 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'
        byte    type;            // 0x03
        byte    zero[3];

        short   lm_resp_len;     // LanManager response length (always 0x18)
        short   lm_resp_len;     // LanManager response length (always 0x18)
        short   lm_resp_off;     // LanManager response offset
        byte    zero[2];

        short   nt_resp_len;     // NT response length (always 0x18)
        short   nt_resp_len;     // NT response length (always 0x18)
        short   nt_resp_off;     // NT response offset
        byte    zero[2];

        short   dom_len;         // domain string length
        short   dom_len;         // domain string length
        short   dom_off;         // domain string offset (always 0x40)
        byte    zero[2];

        short   user_len;        // username string length
        short   user_len;        // username string length
        short   user_off;        // username string offset
        byte    zero[2];

        short   host_len;        // host string length
        short   host_len;        // host string length
        short   host_off;        // host string offset
        byte    zero[6];

        short   msg_len;         // message length
        byte    zero[2];

        short   flags;           // 0x8201
        byte    zero[2];

        byte    dom[*];          // domain string (unicode UTF-16LE)
        byte    user[*];         // username string (unicode UTF-16LE)
        byte    host[*];         // host string (unicode UTF-16LE)
        byte    lm_resp[*];      // LanManager response
        byte    nt_resp[*];      // NT response
    } type-3-message
</PRE><PRE>                 0       1       2       3
             +-------+-------+-------+-------+
         0:  |  'N'  |  'T'  |  'L'  |  'M'  |
             +-------+-------+-------+-------+
         4:  |  'S'  |  'S'  |  'P'  |   0   |
             +-------+-------+-------+-------+
         8:  |   3   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
        12:  |  LM-resp len  |  LM-Resp len  |
             +-------+-------+-------+-------+
        16:  |  LM-resp off  |   0   |   0   |
             +-------+-------+-------+-------+
        20:  |  NT-resp len  |  NT-Resp len  |
             +-------+-------+-------+-------+
        24:  |  NT-resp off  |   0   |   0   |
             +-------+-------+-------+-------+
        28:  | domain length | domain length |
             +-------+-------+-------+-------+
        32:  | domain offset |   0   |   0   |
             +-------+-------+-------+-------+
        36:  |  user length  |  user length  |
             +-------+-------+-------+-------+
        40:  |  user offset  |   0   |   0   |
             +-------+-------+-------+-------+
        44:  |  host length  |  host length  |
             +-------+-------+-------+-------+
        48:  |  host offset  |   0   |   0   |
             +-------+-------+-------+-------+
        52:  |   0   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
        56:  |  message len  |   0   |   0   |
             +-------+-------+-------+-------+
        60:  | 0x01  | 0x82  |   0   |   0   |
             +-------+-------+-------+-------+
        64:  | domain string                 |
             +                               +
             .                               .
             .                               .
             +           +-------------------+
             |           | user string       |
             +-----------+                   +
             .                               .
             .                               .
             +                 +-------------+
             |                 | host string |
             +-----------------+             +
             .                               .
             .                               .
             +   +---------------------------+
             |   | LanManager-response       |
             +---+                           +
             .                               .
             .                               .
             +            +------------------+
             |            | NT-response      |
             +------------+                  +
             .                               .
             .                               .
             +-------+-------+-------+-------+
</PRE>
<P>The host, domain, and username strings are in Unicode (UTF-16, little-endian) and are not nul-terminated; the host and domain names are in upper case. The lengths of the response strings are 24. 
<H3><A name=hashes>Password Hashes</A></H3>
<P>To calculate the two response strings two password hashes are used: the LanManager password hash and the NT password hash. These are described in detail at the beginning of the Samba <A href="http://de.samba.org/samba/ftp/docs/htmldocs/ENCRYPTION.html">ENCRYPTION.html</A> document. However, a few things are not clear (such as what the magic constant for the LanManager hash is), so here is some almost-C code which calculates the two responses. Inputs are <VAR>passw</VAR> and <VAR>nonce</VAR>, the results are in <VAR>lm_resp</VAR> and <VAR>nt_resp</VAR>. <PRE>    /* setup LanManager password */

    char  lm_pw[14];
    int   len = strlen(passw);
    if (len &gt; 14)  len = 14;

    for (idx=0; idx&lt;len; idx++)
        lm_pw[idx] = toupper(passw[idx]);
    for (; idx&lt;14; idx++)
        lm_pw[idx] = 0;


    /* create LanManager hashed password */

    unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
    unsigned char lm_hpw[21];
    des_key_schedule ks;

    setup_des_key(lm_pw, ks);
    des_ecb_encrypt(magic, lm_hpw, ks);

    setup_des_key(lm_pw+7, ks);
    des_ecb_encrypt(magic, lm_hpw+8, ks);

    memset(lm_hpw+16, 0, 5);


    /* create NT hashed password */

    int   len = strlen(passw);
    char  nt_pw[2*len];
    for (idx=0; idx&lt;len; idx++)
    {
        nt_pw[2*idx]   = passw[idx];
        nt_pw[2*idx+1] = 0;
    }

    unsigned char nt_hpw[21];
    MD4_CTX context;
    MD4Init(&amp;context);
    MD4Update(&amp;context, nt_pw, 2*len);
    MD4Final(nt_hpw, &amp;context);

    memset(nt_hpw+16, 0, 5);


    /* create responses */

    unsigned char lm_resp[24], nt_resp[24];
    calc_resp(lm_hpw, nonce, lm_resp);
    calc_resp(nt_hpw, nonce, nt_resp);
</PRE>
<P>Helpers: <PRE>    /*
     * takes a 21 byte array and treats it as 3 56-bit DES keys. The
     * 8 byte plaintext is encrypted with each key and the resulting 24
     * bytes are stored in the results array.
     */
    void calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results)
    {
        des_key_schedule ks;

        setup_des_key(keys, ks);
        des_ecb_encrypt((des_cblock*) plaintext, (des_cblock*) results, ks, DES_ENCRYPT);

        setup_des_key(keys+7, ks);
        des_ecb_encrypt((des_cblock*) plaintext, (des_cblock*) (results+8), ks, DES_ENCRYPT);

        setup_des_key(keys+14, ks);
        des_ecb_encrypt((des_cblock*) plaintext, (des_cblock*) (results+16), ks, DES_ENCRYPT);
    }


    /*
     * turns a 56 bit key into the 64 bit, odd parity key and sets the key.
     * The key schedule ks is also set.
     */
    void setup_des_key(unsigned char key_56[], des_key_schedule ks)
    {
        des_cblock key;

        key[0] = key_56[0];
        key[1] = ((key_56[0] &lt;&lt; 7) &amp; 0xFF) | (key_56[1] &gt;&gt; 1);
        key[2] = ((key_56[1] &lt;&lt; 6) &amp; 0xFF) | (key_56[2] &gt;&gt; 2);
        key[3] = ((key_56[2] &lt;&lt; 5) &amp; 0xFF) | (key_56[3] &gt;&gt; 3);
        key[4] = ((key_56[3] &lt;&lt; 4) &amp; 0xFF) | (key_56[4] &gt;&gt; 4);
        key[5] = ((key_56[4] &lt;&lt; 3) &amp; 0xFF) | (key_56[5] &gt;&gt; 5);
        key[6] = ((key_56[5] &lt;&lt; 2) &amp; 0xFF) | (key_56[6] &gt;&gt; 6);
        key[7] =  (key_56[6] &lt;&lt; 1) &amp; 0xFF;

        des_set_odd_parity(&amp;key);
        des_set_key(&amp;key, ks);
    }
</PRE>
<H2><A name=connections>Keeping the connection alive</A></H2>
<P>As mentioned above, this scheme authenticates <EM>connections</EM>, not requests. This manifests itself in that the network connection must be kept alive during the second part of the handshake, i.e. between the receiving of the type-2 message from the server (step 4) and the sending of the type-3 message (step 5). Each time the connection is closed this second part (steps 3 through 6) must be repeated over the new connection (i.e. it's not enough to just keep sending the last type-3 message). Also, once the connection is authenticated, the Authorization header need not be sent anymore while the connection stays open, no matter what resource is accessed. 
<P>For implementations wishing to work with M$'s software this means that they must make sure they use either HTTP/1.0 keep-alive's or HTTP/1.1 persistent connections, and that they must be prepared to do the second part of the handshake each time the connection was closed and is reopened. Server implementations must also make sure that HTTP/1.0 responses contain a Content-length header (as otherwise the connection must be closed after the response), and that HTTP/1.1 responses either contain a Content-length header or use the chunked transfer encoding. 
<H2><A name=example>Example</A></H2>
<P>Here is an actual example of all the messages. Assume the host name is "LightCity", the NT domain name is "Ursa-Minor", the username is "Zaphod", the password is "Beeblebrox", and the server sends the nonce "SrvNonce". Then the handshake is: <PRE>    C -&gt; S   GET ...
    
    S -&gt; C   401 Unauthorized
             WWW-Authenticate: NTLM
    
    C -&gt; S   GET ...
             Authorization: NTLM TlRMTVNTUAABAAAAA7IAAAoACgApAAAACQAJACAAAABMSUdIVENJVFlVUlNBLU1JTk9S
    
    S -&gt; C   401 Unauthorized
             WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==
    
    C -&gt; S   GET ...
             Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABQAFABAAAAADAAMAFQAAAASABIAYAAAAAAAAACiAAAAAYIAAFUAUgBTAEEALQBNAEkATgBPAFIAWgBhAHAAaABvAGQATABJAEcASABUAEMASQBUAFkArYfKbe/jRoW5xDxHeoxC1gBmfWiS5+iX4OAN4xBKG/IFPwfH3agtPEia6YnhsADT
    
    S -&gt; C   200 Ok
</PRE>
<P>and the unencoded messages are: 
<P>Type-1 Message: <PRE>       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
   0:  4e 54 4c 4d 53 53 50 00 01 00 00 00 03 b2 00 00  "NTLMSSP........."
  10:  0a 00 0a 00 29 00 00 00 09 00 09 00 20 00 00 00  "....)....... ..."
  20:  4c 49 47 48 54 43 49 54 59 55 52 53 41 2d 4d 49  "LIGHTCITYURSA-MI"
  30:  4e 4f 52                                         "NOR"
</PRE>
<P>Type-2 Message: <PRE>       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
   0:  4e 54 4c 4d 53 53 50 00 02 00 00 00 00 00 00 00  "NTLMSSP........."
  10:  28 00 00 00 01 82 00 00 53 72 76 4e 6f 6e 63 65  "(.......SrvNonce"
  20:  00 00 00 00 00 00 00 00                          "........"
</PRE>
<P>Type-3 Message: <PRE>       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
   0:  4e 54 4c 4d 53 53 50 00 03 00 00 00 18 00 18 00  "NTLMSSP........."
  10:  72 00 00 00 18 00 18 00 8a 00 00 00 14 00 14 00  "r..............."
  20:  40 00 00 00 0c 00 0c 00 54 00 00 00 12 00 12 00  "@.......T......."
  30:  60 00 00 00 00 00 00 00 a2 00 00 00 01 82 00 00  "`..............."
  40:  55 00 52 00 53 00 41 00 2d 00 4d 00 49 00 4e 00  "U.R.S.A.-.M.I.N."
  50:  4f 00 52 00 5a 00 61 00 70 00 68 00 6f 00 64 00  "O.R.Z.a.p.h.o.d."
  60:  4c 00 49 00 47 00 48 00 54 00 43 00 49 00 54 00  "L.I.G.H.T.C.I.T."
  70:  59 00 ad 87 ca 6d ef e3 46 85 b9 c4 3c 47 7a 8c  "Y....m..F...&lt;Gz."
  80:  42 d6 00 66 7d 68 92 e7 e8 97 e0 e0 0d e3 10 4a  "B..f}h.........J"
  90:  1b f2 05 3f 07 c7 dd a8 2d 3c 48 9a e9 89 e1 b0  "...?....-&lt;H....."
  a0:  00 d3                                            ".."
</PRE>
<P>For reference, the intermediate hashed passwords are: 
<DL>
<DT>lm_hpw (LanManager hashed password): 
<DD>91 90 16 f6 4e c7 b0 0b a2 35 02 8c a5 0c 7a 03 00 00 00 00 00 
<DT>nt_hpw (NT hashed password): 
<DD>8c 1b 59 e3 2e 66 6d ad f1 75 74 5f ad 62 c1 33 00 00 00 00 00 </DD></DL>
<H2><A name=resources>Resources</A></H2>
<DL>
<DT><IMG alt=* src="http://www.innovation.ch/images/greenball.gif"> LM authentication in SMB/CIFS 
<DD><A href="http://www.ubiqx.org/cifs/SMB.html#SMB.8.3">http://www.ubiqx.org/cifs/SMB.html#SMB.8.3</A> 
<DT><IMG alt=* src="http://www.innovation.ch/images/greenball.gif"> A document on cracking NTLMv2 authentication 
<DD><A href="http://www.blackhat.com/presentations/win-usa-02/urity-winsec02.ppt">http://www.blackhat.com/presentations/win-usa-02/urity-winsec02.ppt</A> <!--
<DT> <IMG ALT="*" src="http://www.blogjava.net/images/greenball.gif">
     A description and comparison of various http authentication schemes
<DD> <A HREF="http://www.cs.odu.edu/~asf/is2/2/paper.html">http://www.cs.odu.edu/~asf/is2/2/paper.html</A>
-->
<DT><IMG alt=* src="http://www.innovation.ch/images/greenball.gif"> Squid's NLTM authentication project 
<DD><A href="http://squid.sourceforge.net/ntlm/">http://squid.sourceforge.net/ntlm/</A> <!--
<DT> <IMG ALT="*" src="http://www.blogjava.net/images/greenball.gif">
     A tutorial on authentication schemes available on IIS
<DD> <A HREF="http://www.aspalliance.com/flicks/">http://www.aspalliance.com/flicks/</A>
-->
<DT><IMG alt=* src="http://www.innovation.ch/images/greenball.gif"> Encryption description for Samba 
<DD><A href="http://de.samba.org/samba/ftp/docs/htmldocs/ENCRYPTION.html">http://de.samba.org/samba/ftp/docs/htmldocs/ENCRYPTION.html</A> <!--
<DT> <IMG ALT="*" src="http://www.blogjava.net/images/greenball.gif">
     Paul Leach's presentation on NT security
<DD> <A HREF="http://www.cifs.com/2ndcifsconf/Microsoft-Leach3/index.html">http://www.cifs.com/2ndcifsconf/Microsoft-Leach3/index.html</A>
--><!--
<DT> <IMG ALT="*" src="http://www.blogjava.net/images/greenball.gif">
     Paul Ashton's page on the MSIE security hole (includes a link to his
     sources for an Apache module which exploits this hole)
<DD> <A HREF="http://www.argo.demon.co.uk/nt/ntie.html">http://www.argo.demon.co.uk/nt/ntie.html</A>
-->
<DT><IMG alt=* src="http://www.innovation.ch/images/greenball.gif"> Info on the MSIE security hole 
<DD><A href="http://oliver.efri.hr/~crv/security/bugs/NT/ie6.html">http://oliver.efri.hr/~crv/security/bugs/NT/ie6.html</A> 
<DT><IMG alt=* src="http://www.innovation.ch/images/greenball.gif"> FAQ: NT Cryptographic Password Attacks &amp; Defences 
<DD><A href="http://www.ntbugtraq.com/default.asp?sid=1&amp;pid=47&amp;aid=17">http://www.ntbugtraq.com/default.asp?sid=1&amp;pid=47&amp;aid=17</A> 
<DT><IMG alt=* src="http://www.innovation.ch/images/greenball.gif"> M$'s hotfix to disable the sending of the LanManager response 
<DD><A href="ftp://ftp.microsoft.com/bussys/winnt/winnt-public/fixes/usa/NT40/hotfixes-postSP3/lm-fix">ftp://ftp.microsoft.com/bussys/winnt/winnt-public/fixes/usa/NT40/hotfixes-postSP3/lm-fix</A> 
<DT><IMG alt=* src="http://www.innovation.ch/images/greenball.gif"> A description of M$'s hotfix 
<DD><A href="http://www.tryc.on.ca/archives/bugtraq/1997_3/0070.html">http://www.tryc.on.ca/archives/bugtraq/1997_3/0070.html</A> </DD></DL>
<H2><A name=acks>Acknowledgements</A></H2>Special thanks to the following people who helped with the collection and debugging of the above information: 
<UL>
<LI><A href="mailto:jlennard@dsg.com">Jon Lennard</A> 
<LI><A href="mailto:paul@argo.demon.co.uk">Paul Ashton</A> 
<LI><A href="mailto:samba-bugs@samba.anu.edu.au">Jeremy Allison</A> </LI></UL>
<ADDRESS>&nbsp;</ADDRESS><img src ="http://www.blogjava.net/lmsun/aggbug/10507.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-19 13:54 <a href="http://www.blogjava.net/lmsun/articles/10507.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The NTLM Authentication Protocol</title><link>http://www.blogjava.net/lmsun/articles/10503.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Fri, 19 Aug 2005 05:52:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10503.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10503.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10503.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10503.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10503.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: AbstractThis article seeks to describe NTLM at an intermediate to advanced level of detail, suitable as a reference for implementors. It is hoped that this document will evolve into a comprehensive ...&nbsp;&nbsp;<a href='http://www.blogjava.net/lmsun/articles/10503.html'>阅读全文</a><img src ="http://www.blogjava.net/lmsun/aggbug/10503.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-19 13:52 <a href="http://www.blogjava.net/lmsun/articles/10503.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Java程序中访问Windows共享文件系统 </title><link>http://www.blogjava.net/lmsun/articles/10487.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Fri, 19 Aug 2005 03:18:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10487.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10487.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10487.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10487.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10487.html</trackback:ping><description><![CDATA[<TABLE class=tableBorder cellSpacing=4 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD noWrap>&nbsp; </TD>
<TD align=right>&nbsp;</TD></TR>
<TR>
<TD colSpan=2 height=1>
<HR color=#cccccc noShade SIZE=1>
</TD></TR>
<TR>
<TD style="WORD-BREAK: break-all" colSpan=2>
<P>本文涉及的几个关键字解释：&nbsp;</P>
<P>SMB: Server Message Block, 用于共享例如文件、打印机、串口或者是命名管道等用于通讯的抽象对象；<BR><A href="http://www.microsoft.com/windows2000/techinfo/reskit/en-us/default.asp?url=/windows2000/techinfo/reskit/en-us/cnet/cnad_arc_endh.asp">CIFS</A>:&nbsp; Common Internet File System,&nbsp; SMB的增强版，Windows 2000/XP实现了该协议；<BR>JCIFS: 一个实现了CIFS的纯Java项目，无须任何的本地库。</P>
<P>JCIFS的网址： <A href="http://jcifs.samba.org/">http://jcifs.samba.org/</A></P>
<P>下面我们看一个非常简单的例子，在运行这个例子之前必须准备两台机器A、B，其中我们A是我们程序运行所在的机器，而B则是被访问的机器，仅用B上的Guest用户，而且A当前的用户不能存在于B机器中，也就是说当我们通过资源管理器访问 \\B&nbsp;的时候，会要求输入用户名以及口令，如下图所示：</P>
<P><IMG alt="" hspace=0 src="http://www.javayou.com/uploads/200408240313340031.jpg" align=left border=0></P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>这个时候A机器上的程序就不能通过例如 \\B\folder\1.txt 这样的路径来访问B机器上共享文件夹folder中的1.txt文件，也就是说Java中自带的File,FileInputStream类已经不起作用了，不信？ 不信你丫试试 <IMG height=15 src="http://www.javayou.com/faces/04.gif" width=15 border=0></P>
<P>但是借助于JCIFS你就可以很容易的访问到文件1.txt的内容，我们先来看这个简单的例子：</P>
<P>import jcifs.smb.*;</P>
<P>public class Demo{<BR>&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //将user和password换成是B机器上的用户名以及口令<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SmbFileInputStream in = new SmbFileInputStream("smb://user:password@B/folder/1.txt" );<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] b = new byte[8192];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int n;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(( n = in.read( b )) &gt; 0 ) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.write( b, 0, n );<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>}<BR><BR>编译并运行这面的例子便可以打印文件 1.txt 的内容。<BR>把上面例子中的密码填写成一个错误的密码再运行程序，便会得到 jcifs.smb.SmbAuthException 异常。<BR><BR>写文件也是一个道理，关于文件的操作JCIFS提供了这么几个类：SmbFile,SmbFileInputStream,SmbFileOutputStream，具体的用户跟Java中对应的类差不多。</P>
<P>JCIFS中文件的URL也就是smb_url，格式为：smb://{user}:{password}@{host}/{path} ，只要填好这个URL，JCIFS就会帮你搞定身份验证的事，粉简单的。</P></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/lmsun/aggbug/10487.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-19 11:18 <a href="http://www.blogjava.net/lmsun/articles/10487.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用JAVA访问共享文件系统</title><link>http://www.blogjava.net/lmsun/articles/10485.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Fri, 19 Aug 2005 03:16:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10485.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10485.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10485.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10485.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10485.html</trackback:ping><description><![CDATA[<DIV class=textbox-title>
<H4>[ 2004-8-10 21:49:00 | By: roof ]</H4></DIV>
<DIV class=textbox-content>
<P><B>前言</B></P>
<P class=normal>在Microsoft 网 络 系 统 中，SMB（Server Message Block， 服 务 信 息 块） 协 议 是Windows for Workgroup(WfWg)、Windows 95、Windows NT 和LanManager 用 来 实 现 共 享 局 域 网 上 文 件 和 打 印 机 的 协 议。 对 于 利 用Linux 和Windows NT 构 建 的 局 域 网 来 说，Samba 就 是 为Linux 提 供 的SMB 客 户 程 序/ 服 务 器 程 序 的 软 件 包， 其 功 能 是 实 现Windows 和Linux 互 相 共 享 对 方 的 磁 盘 空 间 和 打 印 机。通用网络文件系统简称CIFS,它事实上是windows平台文件共享的标准协议，它是windows explorer,网络邻居和映射网络驱动器的底层实现协议。JAVA具有天然的平台无关性，使用JAVA可以访问任何类型的服务器或客户机上的共享文件系统，并且编写的软件产品可以运行于任何平台，因此用JAVA访问共享文件系统在企业应用中具有得天独厚的优势。</P>
<P><B>JAVA中的CIFS实现</B></P>
<P class=normal>Jcifs是CIFS在JAVA中的一个实现，是samba组织本着linux的精神，负责维护开发的一个开源项目。这个项目专注于使用java语言对cifs协议的设计和实现。他们将jcifs设计成为一个完整的，丰富的，具有可扩展能力且线程安全的客户端库。这一库可以应用于各种java虚拟机访问遵循CIFS/SMB网络传输协议的网络资源。类似于java.io.File的接口形式，在多线程的工作方式下被证明是有效而容易使用的。目前jcifs的最新版本是jcifs-0.8.0b，你可以在本文最后列出的参考资料中获得下载这一类库的网址，这一版本还支持分布式的文件系统，本文尚不涉及这一内容。</P>
<P><B>JAVA/CIFS程序设计</B></P>
<P class=normal>如果你曾经使用过java的文件操作功能，那么你将很容易掌握jcifs的开发方法。Jcifs通过类似如下的资源url定位一个资源： 
<P class=normal>smb://guest:1234@192.168.3.56/share/a.txt 
<P class=normal>这个url的开始部分smb:// 说明了这是一个smb类型的url；接下来的guest和1234分别是访问共享资源的用户名称和密码；@后面是要访问的资源的主机名或IP地址。最后是资源的共享文件夹名称和共享资源名。 
<P class=normal>在JAVA程序中，使用如下方式获得一个远程共享文件的句柄： 
<P class=normal>SmbFile file = new SmbFile("smb://guest:1234@192.168.3.56/share/a.txt"); 
<P class=normal>这里的句柄不仅限于远程的共享文件，还可能是共享文件夹。isFile()方法和isDirectory()用来判断这个句柄对应的资源的真实属性。如果是共享文件夹，通过调用它的list()方法将获得其中资源的列表。List方法支持过滤器机制，有两种过滤器可供使用，一种是SmbFileFilter,另一种是SmbFilenameFilter，这两个在jcifs中作为接口出现，你可以根据自己的需要派生出个性化的过滤器，实现接口中的accept方法，以满足不同业务的需求。 
<P class=normal>SmbFileInputStream是smb文件的输入流，它的功能是以流的方式打开一个SmbFile： 
<P class=normal>SmbFileInputStream in = new SmbFileInputStream(file); 
<P class=normal>SmbFileInputStream提供read方法，你可以从这个流中读出远程文件全部的内容。 
<P class=normal>至此，你已经掌握了java访问smb文件系统的基本方法。 
<P class=normal>SmbFileOutputStream是smb文件的输入流，可以向远程文件系统通过smb写入数据，方法与上面类似，不再赘述。 
<P class=normal>本文后面附带的源代码是一个完整的例子，它完成功能很简单，就是将另一台电脑上指定共享文件夹下的某些文件拷贝到本机的指定目录下。通过这个例子，相信你很容易将它移植到你的开发产品中。</P>
<P class=normal>第一步，设置运行环境。将源代码解压缩，将lib目录下的名称为jcifs-0.8.0b.jar的文件加入到你的操作系统的classpath中，使示例程序运行时能够找到这个库。</P>
<P class=normal>第二步，在另一台计算机上建立名称为share的共享文件夹,用户名为guest,密码也为guest。假设这台计算机的ip地址是192.168.0.2。</P>
<P class=normal>第三步，在刚才建立的共享文件夹下放置两个文件，名称分别为hello.txt，bye.txt。文件的内容无所谓。</P>
<P class=normal>第三步，在本地计算机上的C盘跟目录下建立一个名称为tmp的空目录，置此目录可写。</P>
<P class=normal>第四步，编译运行Sample1.java，并运行：</P>
<P class=normal>Java Sample1 192.168.3.52 guest guest /share/ c:/tmp/</P>
<P class=normal>检查c:\tmp文件夹,会发现hello.txt这个文件被复制到了本机，而bye.txt没有被复制，因为Sample1.java中使用了过滤器，仅允许名称为hello开头的文件被拷贝。</P>
<P><B>后记</B></P>
<P class=normal>对共享文件系统的访问是内部办公系统等涉及到文件迁移的软件产品开发过程中不可回避的课题，jCifs是一套针对这一课题完整而强大的解决方案，通过它你可以实现对任何共享文件系统的访问。</P>
<P><B>一些有用的资源和参考资料</B></P>
<P class=normal>本文的全部源代码，可编译运行，供读者研究，<A href="http://gceclub.sun.com.cn/staticcontent/html/2004-03-12/CIFS_Sample.zip">下载源代码</A>。</P>
<P class=normal>如欲了解更多关于jcifs的信息，请访问其官方网站 <A href="http://jcifs.samba.org/">http://jcifs.samba.org/</A>。</P>
<P class=normal>您可以在 <A href="http://users.erols.com/mballen/jcifs/">http://users.erols.com/mballen/jcifs/</A> 获得jcifs库的最新版本。</P>
<P class=normal>如果你对smb还不是十分熟悉，这里有一篇不错的文章将向你介绍什么是smb：<A href="http://samba.anu.edu.au/cifs/docs/what-is-smb.html">http://samba.anu.edu.au/cifs/docs/what-is-smb.html</A>。</P></DIV><img src ="http://www.blogjava.net/lmsun/aggbug/10485.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-19 11:16 <a href="http://www.blogjava.net/lmsun/articles/10485.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Easy Windows Authentication with Tomcat 4.x</title><link>http://www.blogjava.net/lmsun/articles/10398.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Thu, 18 Aug 2005 03:07:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10398.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10398.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10398.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10398.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10398.html</trackback:ping><description><![CDATA[<P minmax_bound="true"><A id=easy_windows_authentication_with_tomcat name=easy_windows_authentication_with_tomcat minmax_bound="true"></A><A style="COLOR: black" href="http://raibledesigns.com/page/rd?anchor=easy_windows_authentication_with_tomcat" minmax_bound="true">Easy Windows Authentication with Tomcat 4.x</A> <SPAN class=dateStamp style="FLOAT: right" minmax_bound="true">Category: Java</SPAN> <BR minmax_bound="true"><BR minmax_bound="true">The <A href="http://rasmussen.homeip.net:8080/javablog/archives/000005.html" minmax_bound="true">original blog entry</A> by Robert Rasmussen has disappeared from the Internet (cannot find server) so I'm reproducing it here via <A href="http://216.239.51.100/search?q=cache:aHa1GIGXnLsC:rasmussen.homeip.net:8080/javablog/archives/000005.html+JAAS+Tomcat+4.x+NT&amp;hl=en&amp;ie=UTF-8" minmax_bound="true">Google's caching feature</A>. I've made a few changes to pretty up the formatting, but that's about it. 
<HR style="MARGIN: 0px 30px 10px; WIDTH: 300px" minmax_bound="true">

<P minmax_bound="true">I've been pulled into a little internal project, and one of the requirements is that users should be able to authenticate with their Windows login and password. IIS may or may not be in the picture. </P>
<P minmax_bound="true">Since the server is a Windows 2000 machine, this turns out to be extremely simple to do thanks to Andy Armstrong's <A href="http://java.sun.com/products/jaas/" minmax_bound="true">JAAS</A> <A href="http://free.tagish.net/jaas/doc.html" minmax_bound="true">login modules</A>.</P>
<P minmax_bound="true">Once you've downloaded the login modules, set your classpath accordingly and make sure that the directory holding NTSystem.dll is in your %PATH% variable. Next, in the "Sample config" folder you'll find a <CODE minmax_bound="true"><FONT size=2>tagish.login</FONT></CODE> file and a <CODE minmax_bound="true"><FONT size=2>java.security.sample</FONT></CODE> file. The last line in the .sample file is significant, and it needs to be in your $JAVA_HOME/jre/lib/security folder (in a file named <CODE minmax_bound="true"><FONT size=2>java.security</FONT></CODE>). You should copy the <CODE minmax_bound="true"><FONT size=2>tagish.login</FONT></CODE> file there as well. If your users will always be logging into the same domain (which is the case in my situation), just set the defaultDomain property in tagish.login, like this:</P><PRE minmax_bound="true">NTLogin
{
    com.tagish.auth.win32.NTSystemLogin required returnNames=true returnSIDs=false defaultDomain=YOUR_DOMAIN_HERE;
};
</PRE>
<P minmax_bound="true">Now, all you need to do to use Windows authentication in your webapps is to make one addition to your <CODE minmax_bound="true"><FONT size=2>server.xml</FONT></CODE> file (or to your specific context's definition):</P><PRE minmax_bound="true">&lt;Realm className="org.apache.catalina.realm.JAASRealm" debug="99"
       appName="NTLogin"
       userClassNames="com.tagish.auth.win32.NTPrincipal"
       roleClassNames="com.tagish.auth.win32.NTPrincipal" /&gt;
</PRE>
<P minmax_bound="true">I'll admit this config is slightly hokey. If you look at the Catalina <A href="http://cvs.apache.org/viewcvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/JAASCallbackHandler.java" minmax_bound="true">JAASCallbackHandler</A> (which is hardwired to <A href="http://cvs.apache.org/viewcvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/JAASRealm.java" minmax_bound="true">JAASRealm</A>), the way that I have the realm configured above pretty much counts on the User principal (in effect, the user name) being the first principal returned. This is evil, but it works. It would be nice if either Catalina allowed a pluggable CallbackHandler so that I could take advantage of the NTPrincipal.getType() method or if Andy's code returned subclasses of NTPrincipal like UserPrincipal or GroupPrincipal that I could specify in server.xml.</P>
<P minmax_bound="true">Once you've got this all configured, the various groups your users belong to equate to role names (so if I belong to an administrators group, my authenticated user will be in role "administrators"), and you can configure security in your webapps using these roles.</P>
<HR style="MARGIN: 0px 30px 10px; WIDTH: 300px" minmax_bound="true">

<P minmax_bound="true"><SPAN class=dateStamp minmax_bound="true">二月 17, 2003 04:11 下午 MST</SPAN> <A class=entrypermalink title="Permanent link to this weblog entry" href="http://raibledesigns.com/page/rd?anchor=easy_windows_authentication_with_tomcat" minmax_bound="true">Permalink</A> </P>
<DIV class=comments minmax_bound="true">
<DIV class=commentTwisty id=commentTwisty065039163189104552351257000004 minmax_bound="true"><A class=plain href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comments" minmax_bound="true">15 留言 </A></DIV></DIV>
<DIV style="HEIGHT: 10px" minmax_bound="true"></DIV>
<DIV class=trackbackUrl minmax_bound="true">反向跟踪 URL: http://raibledesigns.com/trackback/rd/sunsets/easy_windows_authentication_with_tomcat </DIV>
<DIV class=comments id=comments minmax_bound="true">
<DIV class=comments-head minmax_bound="true">留言:</DIV><BR minmax_bound="true">
<DIV class=comment id=comment1 minmax_bound="true">Thanks for posting this, Matt. 
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A href="mailto:%72%6f%62%65%72%74%5f%72%61%73%6d%75%73%73%65%6e%40%68%6f%74%6d%61%69%6c%2e%63%6f%6d" minmax_bound="true">Robert Rasmussen</A> on 2003年02月17日, 09:18 下午 MST <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment1" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment2 minmax_bound="true">I have tired this module and used the form authenication in the tomcat. Howerver, it seems cannot login in successfully as it always go into the <FORM-ERROR-PAGE minmax_bound="true">pages. Please help!! 
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A href="mailto:%6a%63%6b%77%6f%6e%67%40%63%68%75%6e%77%6f%2e%63%6f%6d" minmax_bound="true">Jimmy Wong</A> on 2003年02月18日, 12:42 上午 MST <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment2" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment3 minmax_bound="true">Make sure the path to <CODE minmax_bound="true"><FONT size=2>NTSystem.dll</FONT></CODE> is in your PATH environment variable and that tagishauth.jar is in your <CODE minmax_bound="true"><FONT size=2>$CATALINA_HOME/common/lib</FONT></CODE>. Currently, I believe this only works on a Windows machine. HTH, Matt 
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <B minmax_bound="true">Matt</B> on 2003年02月18日, 07:00 上午 MST <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment3" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment4 minmax_bound="true">If I am running a JVM under an already authenticated NT user, does anyone know how I can easily get the NT domain that the user authenticated to ? Thanks ! 
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A href="mailto:%6e%77%68%69%74%65%68%65%40%79%61%68%6f%6f%2e%63%6f%6d" minmax_bound="true">Nicholas Whitehead</A> on 2003年02月20日, 11:59 上午 MST <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment4" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment5 minmax_bound="true">How can I get Subject in my web application with JAASRealm? 
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A href="mailto:%62%6c%61%64%65%40%69%76%63%2e%74%61%67%6d%65%74%2e%72%75" minmax_bound="true">Roman Velichko</A> on 2003年08月06日, 12:21 上午 MDT <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment5" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment6 minmax_bound="true">The same way you always have - request.getRemoteUser() 
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <B minmax_bound="true">Matt Raible</B> on 2003年08月06日, 08:10 上午 MDT <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment6" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment7 minmax_bound="true">This tutorial is out of date...Andy Armstrong updated tagish a few months back...it now has more useful types like NTUserPrincipal and NTGroupPrincipal and a few bug fixes. Also, depending on your requirements, the NTLM functionality added in JDK1.4.2 might help. 
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A href="mailto:%72%6f%62%65%72%74%40%6d%6f%6f%6e%6c%69%67%68%74%74%6f%77%65%72%2e%63%6f%6d" minmax_bound="true">Robert Rasmussen</A> on 2003年08月06日, 10:58 上午 MDT <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment7" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment8 minmax_bound="true">request.getRemoteUser() does return a String not JAAS's Subject. 
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A href="mailto:%73%7a%6d%61%74%75%61%66%79%40%77%70%2e%70%6c" minmax_bound="true">Tomasz Luczynski</A> on 2004年03月09日, 03:23 上午 MST <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment8" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment9 minmax_bound="true">[Trackback] This is the solution for my previous post. Samba NTLM Authentication: (Get it here.) This package configures exactly as described. I used the example servlet (NtlmHttpAuthExample) included with the package and set up the filter as in the docs. ... 
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A href="mailto:%73%7a%6d%61%74%75%61%66%79%40%77%70%2e%70%6c" minmax_bound="true">Chris Maeda</A> on 2004年07月18日, 10:24 上午 MDT <BR minmax_bound="true">站点： <A href="http://www.cmaeda.com/index.php?p=22" minmax_bound="true">http://www.cmaeda.com/index.php?p=22</A> <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment9" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment10 minmax_bound="true">My blog has current info for setting up Tagish 1.03 with Tomcat5. 
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A title=66.30.149.19 href="mailto:%63%6d%61%65%64%61%40%63%6d%61%65%64%61%2e%63%6f%6d" minmax_bound="true">Chris Maeda</A> on 2004年07月18日, 10:38 上午 MDT <BR minmax_bound="true">站点： <A href="http://cmaeda.com/index.php?p=22" minmax_bound="true">http://cmaeda.com/index.php?p=22</A> <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment10" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment11 minmax_bound="true">
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A href="mailto:%6a%65%6e%6e%69%66%65%72%63%40%79%61%68%6f%6f%2e%63%6f%6d" minmax_bound="true">69.193.88.30</A> on 2004年11月09日, 03:12 上午 MST <BR minmax_bound="true">站点： <A href="http://www.jenniferconnor.com/" minmax_bound="true">http://www.jenniferconnor.com/</A> <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment11" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment12 minmax_bound="true">
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A href="mailto:%67%6f%74%6f%6d%79%77%6f%72%6c%64%40%79%61%68%6f%6f%2e%63%6f%6d" minmax_bound="true">69.193.88.30</A> on 2004年11月14日, 01:53 上午 MST <BR minmax_bound="true">站点： <A href="http://www.36busty.com/00005602.shtml" minmax_bound="true">http://www.36busty.com/00005602.shtml</A> <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment12" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment13 minmax_bound="true">
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A href="mailto:%6a%6f%68%6e%68%75%72%6f%6e%32%31%40%68%6f%74%6d%61%69%6c%2e%63%6f%6d" minmax_bound="true">69.42.81.244</A> on 2005年01月01日, 02:32 上午 MST <BR minmax_bound="true">站点： <A href="http://www.johnhuron.com/" minmax_bound="true">http://www.johnhuron.com/</A> <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment13" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment14 minmax_bound="true">Hi Matt, Are you still using tagish library with Tomcat 5.x versions?? If yes, could you please point out the final installing directions. With the present blog instructions from Chris Maeda, they doesn't work at all. You can see the problems at http://www.cmaeda.com/index.php?p=22 Please advice. thanks aks 
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A title=217.110.221.139 href="mailto:%70%61%74%73%31%34%33%40%72%65%64%69%66%66%6d%61%69%6c%2e%63%6f%6d" minmax_bound="true">Vicky</A> on 2005年04月01日, 10:45 上午 MST <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment14" minmax_bound="true">#</A> </P></DIV>
<DIV class=comment id=comment15 minmax_bound="true">I prefer not to put my config in $JAVA_HOME/jre/lib/security/java.security instead, use this property when you start tomcat: -Djava.security.auth.login.config=c:/path/to/your/tagish.login 
<P class=comment-details minmax_bound="true">由<B minmax_bound="true">{0}</B>发表于 <A title=209.213.92.25 href="mailto:%6a%6f%65%73%40%63%68%65%63%6b%65%72%6e%65%74%2e%63%6f%6d" minmax_bound="true">Joe Scalise</A> on 2005年08月08日, 02:41 下午 MDT <BR minmax_bound="true">站点： <A href="http://www.einvite.com/" minmax_bound="true">http://www.einvite.com</A> <A class=entrypermalink title=留言的永久链接 href="http://raibledesigns.com/comments/rd/sunsets/easy_windows_authentication_with_tomcat#comment15" minmax_bound="true">#</A> </P></DIV></DIV><img src ="http://www.blogjava.net/lmsun/aggbug/10398.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-18 11:07 <a href="http://www.blogjava.net/lmsun/articles/10398.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Authentication and Authorization </title><link>http://www.blogjava.net/lmsun/articles/10366.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Wed, 17 Aug 2005 09:38:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10366.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10366.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10366.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10366.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10366.html</trackback:ping><description><![CDATA[<P>Introduction<BR>This paper explains how to use the Java Authentication and Authorization API (JAAS). It plugs JAAS into the Struts framework. Though this paper focuses on Struts, and in particular the example application distributed with Struts, the lessons learned should be applicable to any MVC web framework. </P>
<P>In addition, while there are many articles on authentication with JAAS [1], [2] , using the API for authorization is relatively undocumented [3]. This paper will show how to use JAAS to secure resources in an MVC architecture. </P>
<P>There are two points of integration with Struts. During the login process and when the client requests a resource from Struts (which will usually be a URL). At each of these points, the application should defer to JAAS classes to perform the action. </P>
<P>This paper will first examine the JAAS infrastructure and then explain how the integration outlined above took place. </P>
<P>&nbsp;</P>
<P>Who should read this<BR>This article is for developers who are relatively familiar with web applications and the java security framework. A sample application in Struts is used for the examples [4], but familiarity with Struts is not required. For information on java security, check out Java Security by Scott Oaks. For information on web applications, check out Sun's web site [5]. For information on Struts, check out the Struts web site [6]. </P>
<P>&nbsp;</P>
<P>Conventions<BR>For the purposes of printing, text that should be on one line will be broken up into more. This will be indicated by a backslash (\) at the end of the line. </P>
<P>&nbsp;</P>
<P>Authentication<BR>Login Module<BR>The login module receives information about the user and authenticates the user, thereby verifying that he or she is a valid subject. There are several implementations of login modules currently available. If a custom login module is needed, resources are available [8]. </P>
<P>Login Module implementations</P>
<P>Sun provides default implementations for Solaris and NT. </P>
<P><BR>Tagish has several implementations licensed under the GPL [9]. </P>
<P><BR>JBoss provides several implementations [10]. <BR>Note: For WebLogic 6.1 and Tomcat 3.2, both the jaas.jar and the login module classes needed to be in the non webapp specific classpath. </P>
<P>These login modules are identified by a name in a configuration file and then called by a LoginContext class that JAAS provides. The LoginContext class does not appear to be thread safe--the javadoc states that " a LoginContext should not be used to authenticate more than one Subject. A separate LoginContext should be used to authenticate each different Subject" [11]. Most of these modules expect to be run from an application or on the command line, and thus to be able to interact directly with a user. Since a web application resides on a server, it may be necessary to write an adapter to pull the needed user information from where the web application stores it and place it in a form that the login module can process. </P>
<P>&nbsp;</P>
<P>Module Configuration<BR>In addition to putting classes that can do authentication in the correct classpath location, some configuration is required to let the JAAS classes know what type of authentication is possible. JAAS allows complex login schemes [12], however, for most web applications, such complexity is not required. Typically, a username and password will be read from a form, and compared against known server side values. An authentication scheme which verifies a username and password combination against a server side file will be examined below. </P>
<P>Example 1. JAAS login module configuration file </P>
<P>FileLogin<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; com.tagish.auth.FileLogin required debug=true \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pwdFile="/usr/local/tomcat/webapps/struts-example/WEB-INF/passwd";<BR>};</P>
<P>In Example 1, the FileLogin authentication scheme has one required module. FileLogin implemented by the com.tagish.auth.FileLogin class. Both the class name and a token indicating the relationship of the module to the scheme are mandatory. Here the required token indicates that the FileLogin module must validate this login or the scheme as a whole fails. It is also possible to pass additional information to the login module in this configuration file. This module needs to know where its password file is located. </P>
<P>Since this configuration file may be located anywhere on the file system, the authentication classes need to be informed where this file is. There are two ways to do this: adding parameters to a JVM wide general configuration file (java.security), or passing the information in on the command line when starting the JVM. </P>
<P>&nbsp;</P>
<P>Setting Login Configuration Information Via java.security<BR>This file is where the JVM looks for security related configuration parameters. It is typically located in the JAVA_HOME/jre/lib/security directory. It is possible to have an arbitrary number of login configuration files detailing any number of authentication schemes. These are "read and unioned into one single configuration" [13]. </P>
<P>Example 2. java.security entry for login module configuration </P>
<P>login.config.url.1=file:${java.home}/lib/security/tagish.login<BR>login.config.url.2=file:${java.home}/lib/security/struts.login</P>
<P>This entry specifies the location of files containing authentication scheme definitions. Also, note that java system properties may be referenced in java.security. </P>
<P>If the second line looked like login.config.url.3=file:${java.home}/lib/security/struts.login (note the 3), then struts.login would not be searched for login modules. Scanning begins at login.config.url.1 and continues to increment the suffix until no file is found. This is an implementation detail of the default Sun provided authentication classes. For more information, read about the Login Configuration Provider [14]. </P>
<P>&nbsp;</P>
<P>Setting Login Configuration Via the Command Line<BR>It is also possible to set a java property on the command line when starting the JVM that tells it where to look for the JAAS login scheme configuration file. The property name is java.security.auth.login.config. </P>
<P>Example 3. Setting the location of the login scheme configuration file on the command line</P>
<P>$ java ... \<BR>-Djava.security.auth.login.config==$JAVA_HOME/jre/lib/security/tagish.login ...</P>
<P>This command line overrides any previously set value for the login scheme configuration file location. In typical java fashion, if there was just one = in Example 3, an additional location for the login scheme configuration file would be specified. </P>
<P>&nbsp;</P>
<P>Integrating Authentication Into Struts<BR>After the login module is recognized by JAAS, hooks into the web application need to be written. In the example application, an Action class takes a username and password from its Form class and authenticates the user against a database. This is the logical place to hook in the JAAS authentication module. </P>
<P>The Struts example application has a LogonAction class. Initially, the relevant portion of this class looks like this (note that this code is unchanged except to break up lines for ease of printing). </P>
<P>Example 4. Initial LogonAction Authentication </P>
<P>&nbsp;&nbsp; 125&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String username = ((LogonForm) form).getUsername();<BR>&nbsp;&nbsp; 126&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String password = ((LogonForm) form).getPassword();<BR>&nbsp;&nbsp; 127&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hashtable database = (Hashtable)<BR>&nbsp;&nbsp; 128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; servlet.getServletContext().getAttribute( \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Constants.DATABASE_KEY \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );<BR>&nbsp;&nbsp; 129&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (database == null)<BR>&nbsp;&nbsp; 130&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errors.add(ActionErrors.GLOBAL_ERROR,<BR>&nbsp;&nbsp; 131&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ActionError("error.database.missing"));<BR>&nbsp;&nbsp; 132&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {<BR>&nbsp;&nbsp; 133&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user = (User) database.get(username);<BR>&nbsp;&nbsp; 134&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((user != null) &amp;&amp; !user.getPassword().equals(password))<BR>&nbsp;&nbsp; 135&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user = null;<BR>&nbsp;&nbsp; 136&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (user == null)<BR>&nbsp;&nbsp; 137&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errors.add(ActionErrors.GLOBAL_ERROR,<BR>&nbsp;&nbsp; 138&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ActionError("error.password.mismatch"));<BR>&nbsp;&nbsp; 139&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P><BR>On line 125 and 126, the username and password that were submitted on the form are extracted into local variables. The code looks for an authentication database and verifies its existence on lines 127-132. Line 134 is where the actual authentication occurs. If the user exists in the database and the password in the database is the same as the password entered on the form, then the user is authenticated. </P>
<P>This approach works just fine for a sample application. The LogonAction class does all of the authentication in the perform method. But the LogonAction class should be a thin layer deferring the actual work to business objects. In addition, switching the source users are authenticated against requires changes to this class since it is hard coded to expect a password and username. Also, as mentioned in the "Login Module" section, using the JAAS authentication module will be difficult, as most implementations expect some level of user interaction. Putting a business object between the Struts application classes and the JAAS classes can make life easier. </P>
<P>Example 5. Modified LogonAction Authentication </P>
<P>&nbsp; 125&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String username = ((LogonForm) form).getUsername();<BR>&nbsp;&nbsp; 126&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String password = ((LogonForm) form).getPassword();<BR>&nbsp;&nbsp; 127&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hashtable database = (Hashtable)<BR>&nbsp;&nbsp; 128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; servlet.getServletContext().getAttribute(Constants.DATABASE_KEY)<BR>&nbsp;&nbsp; 129&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (database == null)<BR>&nbsp;&nbsp; 130&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errors.add(ActionErrors.GLOBAL_ERROR,<BR>&nbsp;&nbsp; 131&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ActionError("error.database.missing"));<BR>&nbsp;&nbsp; 132&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {<BR>&nbsp;&nbsp; 133&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Auth fa = new com.xor.auth.FileAuth(username,password);<BR>&nbsp;&nbsp; 134&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fa.authenticate()) {<BR>&nbsp;&nbsp; 135&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user = (User) database.get(username);<BR>&nbsp;&nbsp; 136&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpSession sess = request.getSession();<BR>&nbsp;&nbsp; 137&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sess.setAttribute(Auth.SUBJECT_SESSION_KEY, fa.getSubject());<BR>&nbsp;&nbsp; 138&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>Lines 125-132 are the same in this example as they were in Example 4. However, rather than the LogonAction class performing the authentication, it defers to a special Auth class. Note that on line 135, the database is still used to get the User object, since the sample application used it in other code. </P>
<P>Auth is a custom interface specifying the contract that the adapter for the JAAS classes must fulfill to interface with web applications in general and this example application in particular. FileAuth is an implementation of that interface which adapts the com.tagish.auth.FileLogin login module specified in Example 1. </P>
<P>&nbsp;</P>
<P>Calling the Tagish Authentication Module<BR>The FileAuth class defers to the FileLogin class for almost all its functionality. </P>
<P>Example 6. The authenticate Method of the FileAuth Class </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp; public boolean authenticate() {<BR>&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lc = new LoginContext("FileLogin", \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new MyCallBackHandler(username,password));<BR>&nbsp;&nbsp;&nbsp;&nbsp; 4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lc.login();<BR>&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (LoginException le) {<BR>&nbsp;&nbsp;&nbsp;&nbsp; 6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp; 8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp;&nbsp; 9&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>On line 3, the LoginContext object is told to look for the FileLogin authentication scheme, and passed a custom callback handler. Normally, callback handlers interact with the user and retrieve information needed for authentication, but the ActionForm class has already done this. In a way, the form is a "call forward" handler, because the request/response paradigm of the web does not fit well with the client/server architecture of which the callback handler is part. The problem is worked around by passing the needed information to the callback handler on instantiation. </P>
<P>On line 4, the LoginContext attempts to login the user via the modules found in the FileLogin authentication scheme. If the login fails for any reason, a LoginException will be thrown, otherwise flow continues normally. A Subject is instantiated by the login module and exposed as a property of the LoginContext object. The Subject is also populated with the Principals associated with that user by the login module. </P>
<P>&nbsp;</P>
<P>Cache Subject in Session<BR>After successfully authenticating the user, the Subject should be stored in the HttpSession. (The Subject is small; one Subject with one Principal serialized to a file 337 bytes in size.) This caching allows other parts of the application to perform authorization checks without requiring the user to login again. It also ensures that the other parts of the application are aware that the user has been authenticated, and logs out the user when the HttpSession expires. The storage process is shown on line 137 of Example 5; here the portion of the API of the login module that returns the newly authenticated Subject is examined. To retrieve the subject, the FileAuth class again defers to the LoginContext. </P>
<P>Example 7. The FileAuth Class Exposes the Subject </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp; public Subject getSubject() {<BR>&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (lc == null) {<BR>&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new IllegalStateException("either login failed or \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the authenticate method hasn't been called.");<BR>&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<BR>&nbsp;&nbsp;&nbsp;&nbsp; 6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return lc.getSubject();<BR>&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp; 8&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>The getSubject method can only be called after the authenticate method.</P>
<P>Of course, another option would be to store the username and password in the session, and re-authenticate every time. If the Subject were large and the authentication process was fairly fast, this option might be viable. </P>
<P>&nbsp;</P>
<P>Authorization<BR>Permissions<BR>Permissions are the heart of authorization; they control access to resources. However, the JAAS permissions are built on top of the existing java security model. This model is very good for controlling access to resources like sockets and files, but has no concept of URLs. Thus, to apply JAAS to a web application, a new permission class must be created. </P>
<P>&nbsp;</P>
<P>Create permission class<BR>A custom Permission class that understands URLs must be created. There are two ways to do this. </P>
<P>Extending java.security.BasicPermission is one option. Using this would tie permissions to literal URLs (e.g, one could say that the admin principal should have access to the /admin/index.do page). However, the other option would be better: to create a URLPermission class extended the java.security.Permission class and handled wild cards in a manner similar to the java.io.FilePermission class [15]. Then, one could say that the admin principal should have access to the /admin/ directory and all resources below it. </P>
<P>In either case, since URLs are read only, there is no need for any of these permissions to have an action attribute. On the other hand, it may be useful to specify an attribute of a Permission to determine whether a given URL may only be viewed over a secure connection. For more on extending Permissions in novel manners, see the interesting IBM article titled Extend JAAS for class instance-level authorization [16]. </P>
<P>However, since this is a proof of concept, a BasicPermission implementation is fine. For a production system, subclassing Permission would be required. </P>
<P>&nbsp;</P>
<P>Access Control Policy Configuration Files<BR>The default configuration for JAAS permissions looks much like the configuration for normal java security. Java security entries consist of a listing of permissions. The permissions can be limited to either a specific code base, or code that has been signed by a specific person, or both. JAAS permission listings can have none, one or both of these elements. However, at least one Principal association is required. </P>
<P>Example 8. Sample JAAS policy file</P>
<P><BR>grant&nbsp; Principal * * {<BR>&nbsp; permission com.xor.auth.perm.URLPermission \<BR>&nbsp; "/struts-example/logoff.do";<BR>};</P>
<P>grant&nbsp; Principal com.tagish.auth.TypedPrincipal "user" {<BR>&nbsp; permission com.xor.auth.perm.URLPermission \<BR>&nbsp; "/struts-example/editRegistration.do";<BR>};</P>
<P>grant&nbsp; Principal com.tagish.auth.TypedPrincipal "admin" {<BR>&nbsp; permission com.xor.auth.perm.URLPermission \<BR>&nbsp; "/struts-example/editRegistration.do";<BR>&nbsp; permission com.xor.auth.perm.URLPermission \<BR>&nbsp; "/struts-example/adminMenu.do";<BR>};</P>
<P><BR>The first grant allows everyone to view the logoff.do resource. Anyone with the user Principal is allowed to view /struts-example/editRegistration.do. </P>
<P>At times there will be principals that are granted a superset of the permissions granted to other principals. For example, in Example 8, subjects with the admin principal can view all resources that subject with the user principal can. However, the /struts-example/editRegistration.do URL is listed twice (once in the user section and once in the admin section). It would be nice to be able to avoid duplicating permissions and delineating this relationship between principals, but this is not possible. While more than one principal can be listed for a given set of permissions, if that happens, "[t]he current Subject running the code must have all of the specified Principals in its Principal set to be granted the entry's Permissions" [17]. However, this problem may be dealt with by granting all users with the admin Principal the user Principal as well. </P>
<P>On the other hand, it is possible to have permissions be supersets of other permissions. The implies method of the Permission class can be overridden to provide this behavior. For example, there could be an admin Permission which could imply all other URL permissions. </P>
<P>Note: Example 8 is an example of a file based implementation of the policy. It canbe replaced with a RDBMS implementation by changing the value of the auth.policy.provider variable in the java.security file. <BR>Since the policy file may be located anywhere, JAAS needs to be told where to look for it (this problem is similar to that faced by the authentication configuration setup detailed in Section 2.2. There are two ways to do this: adding parameters to a system wide general configuration file (java.security), or passing the information in as a command line option when starting the JVM. </P>
<P><BR>Note: With WebLogic 6.1, only the command line method worked. Tomcat 3.2 seemed to work with both methods. </P>
<P><BR>Setting the JAAS Policy File Location in the java.security file<BR>This file is where the JVM looks for security related configuration parameters. It is typically located in the JAVA_HOME/jre/lib/security directory. It is possible to have arbitrary numbers of JAAS policy files. These are "read and unioned into one single policy" [18]. </P>
<P>Example 9. java.security entry for permission policy configuration </P>
<P>auth.policy.url.1=file:${java.home}/lib/security/struts.policy<BR>auth.policy.url.2=file:${user.home}/.struts.policy</P>
<P>This example should check the policy files in both places. Note also that java system properties can be referenced in the java.security file. </P>
<P>If the second line looked like auth.policy.url.3=file:${user.home}/.struts.policy (note the 3), then the .struts.policy file would not be searched for permission sets. Scanning starts at auth.policy.url.1 and increments the suffix by one until there is no file found. This is an implementation detail of the default Sun permission file parsing class. Obviously, an authorization scheme that used a database would have different behavior. </P>
<P>&nbsp;</P>
<P>Setting the JAAS Policy File Location Via the Command Line<BR>It is also possible to set a java property on the command line when starting the JVM that tells it where to look for the JAAS policy file. The property name is java.security.auth.policy. </P>
<P>Example 10. Setting the location of the JAAS policy file on the command line</P>
<P>$ java ... \<BR>-Djava.security.auth.policy==$JAVA_HOME/jre/lib/security/struts.policy ...</P>
<P>This command line overrides any previously set location of the JAAS policy file. If there was only one =, the property would indicate an additional policy file path. </P>
<P>&nbsp;</P>
<P>Integrating Authorization into Struts<BR>Now that permissions have been set up and JAAS knows about them, it is time to actually apply them in the context of the application. Every java class that accesses a potentially security sensitive resource needs to check to see if the SecurityManager is running, and if so verify that the calling class is running in a context that allows the access. </P>
<P>Example 11. Typical permission check</P>
<P>Permission p = new FilePermission("/tmp/foo","read");<BR>SecurityManager s = System.getSecurityManager();<BR>if ( s != null) s.checkPermission(p);</P>
<P>The code here is trying to read /tmp/foo. If no SecurityManager is installed (typically via the -Djava.security.manager command line switch), System.getSecurityManager() returns null, and access does not need to be verified. </P>
<P>The web application needs to perform a similar check for each URL that the user is trying to view. In an MVC architecture, the logical place to put such access control is the controller. In Struts, the ActionServlet is the controller. For the sample application the controller class, org.apache.struts.action.ActionServlet, was subclassed, and the process method was overridden. </P>
<P>&nbsp;</P>
<P>Installing Access Control Logic into the ActionServlet<BR>First of all, it is important to note that when the ActionServlet is subclassed to provide authorization services, only resources that the ActionServlet controls are protected. Thus, in the example application, only Actions are protected. In a real application, it'd be better to have two methods of access control: </P>
<P>A central servlet which checks authorization before any URL is viewed. For example, all users may need to be logged in before viewing any pages. (If using the 1.3 version of the servlet specification, a filter might be a good choice.) </P>
<P><BR>A JSP tag or other method which may be used to check to see if a user has a given principal before showing content fragments. For example, a menu item may only be accessible to users with the admin permission. <BR>Both of these should delegate to a business class that does the actual security check. </P>
<P>There are at least two pages whose view should not be protected at all: the login page and the login error page. In addition, there are certain security attributes that are peculiar to web applications; for example, some users may need to have all interaction over an SSL connection. The controller needs to do at least three things to provide authorization services for a web application. </P>
<P>Recognize which pages are viewable by every authenticated user and respond accordingly.</P>
<P><BR>Recognize which state, secure or non secure, a request is in and respond accordingly.</P>
<P><BR>Check to see that a user is allowed to view a given URL and respond accordingly. </P>
<P><BR>The ActionServlet Subclass<BR>Example 12. The Overridden process Method</P>
<P><BR>&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp; protected void process(HttpServletRequest request, \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletResponse response)<BR>&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp; throws ServletException, java.io.IOException<BR>&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp; 4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String loginPage = request.getContextPath()+"/logon.do";<BR>&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String pageReq = request.getRequestURI();<BR>&nbsp;&nbsp;&nbsp;&nbsp; 6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Permission perm = \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PermissionFactory.getInstance().getPermission(pageReq);<BR>&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Subject subject = \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((Subject)(request.getSession().getAttribute( \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Auth.SUBJECT_SESSION_KEY)));<BR>&nbsp;&nbsp;&nbsp;&nbsp; 8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (subject == null &amp;&amp; \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (! request.getRequestURI().equals(loginPage))) {<BR>&nbsp;&nbsp;&nbsp;&nbsp; 9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // redirect to login page<BR>&nbsp;&nbsp;&nbsp; 10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (subject == null &amp;&amp;&nbsp; \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.getRequestURI().equals(loginPage)) {<BR>&nbsp;&nbsp;&nbsp; 11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // login page is always permitted<BR>&nbsp;&nbsp;&nbsp; 12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.process(request,response);<BR>&nbsp;&nbsp;&nbsp; 13<BR>&nbsp;&nbsp;&nbsp; 14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<BR>&nbsp;&nbsp;&nbsp; 15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( ! AuthUtils.permitted(subject, perm) ) {<BR>&nbsp;&nbsp;&nbsp; 16&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // subject is not permitted; redirect to error page<BR>&nbsp;&nbsp;&nbsp; 17&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; } else {<BR>&nbsp;&nbsp;&nbsp; 18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.process(request,response);<BR>&nbsp;&nbsp;&nbsp; 19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; 20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; 21&nbsp;&nbsp;&nbsp; }</P>
<P><BR>Lines 6 and 7 get needed information including the Permission that represents the URL the user is trying to access (PermissionFactory is a factory class that returns the appropriate Permission), and the cached Subject. </P>
<P>On lines 8-14, the case of the unauthenticated user is handled by redirecting the user to the login page, where access is always allowed (line 12). The reason that this can't be handled by the wildcard grant in Example 8 is that the Subject is null in this case. If the program catches this and creates a new Subject, that Subject still has no Principals and thus is still denied access. For a production system, it's conceivable this case could be handled with an anonymous Principal. </P>
<P>If this is a request for any other resource than the login page, on line 15 the access control class is called. Access is either disallowed, or the process method of the superclass is called. </P>
<P>The ActionServlet should not know about the particulars of the access control; this should instead be handled by a business class. For this example, such a business class was written; it is examined in the next section. </P>
<P>&nbsp;</P>
<P>The Access Control Class<BR>This class is similar to the java.security.AccessController class [19], and ends defers to that class eventually (via the SecurityManager). The logic in the class can then be reused anywhere that authorization is needed. The class will basically check whether a Subject has a given Permission. </P>
<P>Example 13. An Abridged Permission Checking Class </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;package com.xor.auth;<BR>&nbsp;&nbsp;&nbsp;&nbsp; 2<BR>&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;import java.security.*;<BR>&nbsp;&nbsp;&nbsp;&nbsp; 4&nbsp;import javax.security.auth.*;<BR>&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;import java.util.*;<BR>&nbsp;&nbsp;&nbsp;&nbsp; 6<BR>&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;public class AuthUtils {<BR>&nbsp;&nbsp;&nbsp;&nbsp; 8<BR>&nbsp;&nbsp;&nbsp;&nbsp; 9&nbsp;&nbsp;&nbsp;&nbsp; static public boolean permitted(Subject subj, final Permission p) {<BR>&nbsp;&nbsp;&nbsp; 10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final SecurityManager sm;<BR>&nbsp;&nbsp;&nbsp; 11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (System.getSecurityManager() == null) {<BR>&nbsp;&nbsp;&nbsp; 12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sm = new SecurityManager();<BR>&nbsp;&nbsp;&nbsp; 13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<BR>&nbsp;&nbsp;&nbsp; 14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sm = System.getSecurityManager();<BR>&nbsp;&nbsp;&nbsp; 15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; 16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp; 17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Subject.doAsPrivileged(subj, new PrivilegedExceptionAction() {<BR>&nbsp;&nbsp;&nbsp; 18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Object run() {<BR>&nbsp;&nbsp;&nbsp; 19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sm.checkPermission(p);<BR>&nbsp;&nbsp;&nbsp; 20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<BR>&nbsp;&nbsp;&nbsp; 21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; 22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },null);<BR>&nbsp;&nbsp;&nbsp; 23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; 24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (AccessControlException ace) {<BR>&nbsp;&nbsp;&nbsp; 25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; 26&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (PrivilegedActionException pae) {<BR>&nbsp;&nbsp;&nbsp; 27&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; 28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; 29&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; 30&nbsp;}</P>
<P>The example has had all logging, error checking and comments removed for brevity. Production code should, for example, test to see that neither the Permission nor the Subject are null. </P>
<P>Lines 10-15 create a SecurityManager. If the application happens to be one of the rare java applications that run with a SecurityManager installed, then that SecurityManager should be used. If not, a new one is created to check the permissions on line 12. </P>
<P>Lines 16-23 do the actual permission check. If the Subject does not have a Principal which has been granted the Permission, the SecurityManager will throw an exception. For reasons of cleanliness and clarity, this exception is caught and converted to false, which is returned to the calling class. Otherwise, the action is allowed, and true is returned. </P>
<P>The null on line 22 is very important; it tells the SecurityManager to consider this resource access in an isolated context, ignoring the permissions of code currently on the execution stack. For further information, see chapter 5 of Java Security. </P>
<P>Note: If the application is running with a SecurityManager enabled, make certain that the AuthUtils class has been granted the doAsPrivileged AuthPermission in the standard java security policy file. Otherwise, this permission checker will not be able to run; a SecurityException will be thrown when line 17 is reached. </P>
<P><BR>Conclusion<BR>The authentication piece of JAAS seems fairly bulletproof. The idea of pluggable authentication modules is great and the developer can leverage a number of existing modules to ease development. </P>
<P>Using JAAS to leverage the SecurityManager for authorization is entirely commensurate with the java security model. There are resources that only certain users with certain principals should be able to see. Rather than reinvent an access control layer, it makes sense to use the one that java already provides. </P>
<P>However, there are some caveats. This was an extremely simplistic example, and the reader will have noted the number of places where parts of the system need to be replaced to create a production system; these include a new controller, permission class, and policy implementation. In addition, this permission model does not map well to the concept of different protocols used to view a URL. </P>
<P>&nbsp;</P>
<P><BR>Definitions<BR>user: a real world entity. It can be another computer system or a human being. This is not represented by an object. </P>
<P><BR>subject: the user as seen by the web application. Subject is the class that represents this concept. </P>
<P><BR>principal: one view of the subject. The API states that it "represents the abstract notion of a principal, which can be used to represent any entity, such as an individual, a corporation, and a login id A Principal is a class that represents a principal" [7]. A principal can be thought of as a role or a group, but those terms have special meaning in J2EE (in the servlet container, for one). </P>
<P><BR>resource: anything in a system to which unlimited access is not granted to all. </P>
<P><BR>permission: access to a resource. The Permission class represents a triplet of resource, action and name. Permissions can be granted to a Principal. </P>
<P><BR>Authentication: the act of verifying that a user is a subject and granting the user certain principals; "who you are." </P>
<P><BR>Authorization: the act of verifying that a user is allowed to access a certain resource; "what you may do." </P>
<P><BR>Authentication module: one method of authenticating a user. Examples include verifying against /etc/passwd and examining the contents of a cookie. </P>
<P><BR>Authentication scheme: a combination of authentication modules. </P><img src ="http://www.blogjava.net/lmsun/aggbug/10366.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-17 17:38 <a href="http://www.blogjava.net/lmsun/articles/10366.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Authenticate a Servlet App using Windows Passwords?</title><link>http://www.blogjava.net/lmsun/articles/10362.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Wed, 17 Aug 2005 09:28:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10362.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10362.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10362.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10362.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10362.html</trackback:ping><description><![CDATA[<DIV class=entrytext>
<P>Current instructions for configuring Tomcat for JAAS-based Windows authentication.<BR>This is the solution for my <A href="http://www.cmaeda.com/index.php?p=21">previous post</A>.<BR><A id=more-22></A></P>
<P><STRONG>Samba NTLM Authentication</STRONG>: (Get it <A href="http://jcifs.samba.org/src/docs/ntlmhttpauth.html">here</A>.) This package configures exactly as described. I used the example servlet (NtlmHttpAuthExample) included with the package and set up the filter as in the docs. The web.xml file is <A href="http://cmaeda.com/blogfiles/auth-jcifs-web.xml">here</A>.</P>
<P>Notes: I tested on my home (windows) network which does not have a domain controller; I used workgroup authentication and did not test against a PDC. So YMMV.</P>
<P>There are two main drawbacks of this approach:</P>
<P>The first is that the jcifs filter (as currently implemented) does not return group membership information. If your servlet app uses security roles and security constraints, this is a problem since you need some way of getting a user’s group memberships (so the container can map them to security roles). You could get probably around this problem by extending the jcifs library to return group information; this is more work than I planned to invest. Another approach would be to create a second filter that maps user names to group memberships, perhaps using the tomcat-users.xml file. This would be cumbersome and proprietary, but it would probably work.</P>
<P>The second drawback is that NTLM authentication is deprecated in the Windows world. Windows 2000 and 2003 use Kerberos authentication, and only fall back on NTLM when they have to.</P>
<P>For these reasons, I abandoned the Samba NTLM approach and looked at the Tagish / JAAS approach.</P>
<P><STRONG>JAAS with Tagish SSPI JAAS provider</STRONG>: JAAS with the <A href="http://free.tagish.net/jaas/">Tagish SSPI-based login module</A> is the way to go. The Tagish login module is based on the Windows SSPI API, which provides an authentication service for distributed environments using the best available protocol; i.e. it uses Kerberos when that is available and transparently falls back on NTLM when Kerbos is not available. In addition, SSPI returns the group membership information, which is necessary for servlet apps that use security roles and security constraints.</P>
<P>The first step in setting this up is to configure the Tagish login module according to the instructions that come with it. In a nutshell, the steps are as follows:</P>
<UL>
<LI>Put NTSystem.dll somewhere on your path 
<LI>Put tagishauth.jar on your classpath 
<LI>Copy the tagish.login file to $JAVA_HOME/jre/lib/security 
<LI>Add this line:<BR><TT>login.config.url.1=file:${java.home}/lib/security/tagish.login</TT><BR>to your java.security file (in $JAVA_HOME/jre/lib/security) </LI></UL>
<P>You can test the configuration using the login.bat file that comes with the Tagish package. If you are on a workgroup, you may need to edit a registry setting to get network authentication to work properly. (I had to.) See this <A href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;180548">Microsoft KB article</A> for more information; apparently, Windows XP has a “ForceGuest” parameter that forces all network logins for a workgroup to use the guest account.</P>
<P>The second step is to configure Tomcat to use this login module. Here are the steps I used to configure it in Tomcat 5.0.16. Note that the first 4 steps are the same ones for setting up the Tagish login module, just tweaked a little for Tomcat.</P>
<UL>
<LI>Copy NTSystem.dll to the Tomcat5 bin directory 
<LI>Copy tagishauth.jar to the Tomcat5 common/lib directory 
<LI>Copy tagish.login to the $JAVA_HOME/jre/lib/security directory. I set the defaultDomain parameter to the name of my server since I’m on a workgroup. 
<LI>Add this line:<BR><TT>login.config.url.1=file:${java.home}/lib/security/tagish.login</TT><BR>to your java.security file (in $JAVA_HOME/jre/lib/security) 
<LI>Configure a JAAS Realm in your Tomcat server.xml file using the following element:<BR><TT>&lt;Realm className=”org.apache.catalina.realm.JAASRealm” debug=”10″<BR>&nbsp;&nbsp; appName=”NTLogin”<BR>&nbsp;&nbsp; userClassNames=”com.tagish.auth.win32.typed.NTUserPrincipal”<BR>&nbsp;&nbsp; roleClassNames=”com.tagish.auth.win32.typed.NTGroupPrincipal” /&gt;<BR></TT></LI></UL>
<P>The most important thing to remember is that the userClassNames and roleClassNames have to be exactly the same names as the classes that the Tagish login module returns. This is necessary because the Tomcat JAASRealm class compares the classnames of the principal objects with the class names given in the realm configuration. If they do not match exactly, they are ignored.</P>
<P>You can test the configuration using the same NtlmHttpAuthExample servlet that we used to test Samba NTLM. You need a different web.xml that uses security roles; the one I used is <A href="http://cmaeda.com/blogfiles/auth-jaas-web.xml">here</A>. For this to work, you have to login using an account that is a member of the TESTGROUP group.</P>
<P>To debug it, I had to get log4j working with Tomcat5, which is an adventure in itself. It turns out that the instructions in the Tomcat5 FAQ are incomplete; you need to add commons-logging.jar to common/lib in addition to all the other steps. If you run into trouble, getting log4j debug messages out of the org.apache.catalina.realm package should tell you what is going wrong.</P>
<P class="postmetadata alt"><SMALL>This entry was posted on Sunday, July 18th, 2004 at 9:19 am and is filed under <A title="View all posts in Java" href="http://blog.cmaeda.com/index.php?cat=2" rel="category tag">Java</A>. You can follow any responses to this entry through the <A href="http://blog.cmaeda.com/?feed=rss2&amp;p=22">RSS 2.0</A> feed. You can <A href="http://blog.cmaeda.com/?p=22#respond">leave a response</A>, or <A href="http://blog.cmaeda.com/wp-trackback.php?p=22" rel=trackback>trackback</A> from your own site. </SMALL></P></DIV><!-- You can start editing here. -->
<H3 id=comments>16 Responses to “How To Authenticate a Servlet App with Windows Passwords”</H3>
<OL class=commentlist>
<LI class=alt id=comment-23><CITE>carmen</CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-23">July 19th, 2004 at 8:59 am</A> </SMALL>
<P>hi,<BR>I cannot get tagish working! I don’t know what I’m doing wrong. Someone can help me please? I’ve followed the list above step by step <IMG class=wp-smiley alt=:( src="http://blog.cmaeda.com/wp-images/smilies/icon_sad.gif"><BR>System: Struts and tomcat on W2000 professional (but also tried same config on W2000 server and it doesn’t work either)<BR>Thanks</P>
<P>stack trace:</P>
<P>19-Jul-2004 17:17:12 org.apache.catalina.realm.JAASRealm authenticate<BR>WARNING: Login exception authenticating username Administrator<BR>javax.security.auth.login.LoginException: Error: <A href="mailto:javax.security.auth.callback.TextInputCallback@da3772">javax.security.auth.callback.TextInputCallback@da3772</A> not available to garner authentication information from the user<BR>at com.tagish.auth.win32.NTSystemLogin.login(NTSystemLogin.java:128)<BR>at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)<BR>at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)<BR>at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)<BR>at java.lang.reflect.Method.invoke(Method.java:324)<BR>at javax.security.auth.login.LoginContext.invoke(LoginContext.java:675)<BR>at javax.security.auth.login.LoginContext.access$000(LoginContext.java:129)<BR>at javax.security.auth.login.LoginContext$4.run(LoginContext.java:610)<BR>at java.security.AccessController.doPrivileged(Native Method)<BR>at javax.security.auth.login.LoginContext.invokeModule(LoginContext.java:607)<BR>at javax.security.auth.login.LoginContext.login(LoginContext.java:534)<BR>at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:281)<BR>at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(BasicAuthenticator.java:129)<BR>at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)<BR>at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)<BR>at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)<BR>at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)<BR>at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)<BR>at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)<BR>at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)<BR>at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)<BR>at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)<BR>at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)<BR>at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)<BR>at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)<BR>at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)<BR>at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:793)<BR>at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:702)<BR>at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:571)<BR>at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:644)<BR>at java.lang.Thread.run(Thread.java:534)<BR>19-Jul-2004 17:20:17 org.apache.coyote.http11.Http11Protocol pause<BR>INFO: Pausing Coyote HTTP/1.1 on http-8080 </P>
<LI class="" id=comment-24><CITE><A href="http://cmaeda.com/" rel="external nofollow">Chris Maeda</A></CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-24">July 19th, 2004 at 10:53 am</A> </SMALL>
<P>I saw this problem; it was caused by a mistake in the config files. Does Tomcat throw an earlier exception that complains about parsing the tagish login config file? If the parse fails, the callback handler will not be initialized. </P>
<LI class=alt id=comment-30><CITE>Manju Panjwani</CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-30">August 31st, 2004 at 7:20 am</A> </SMALL>
<P>I am also facing the same issue.<BR>WARNING: Login exception authenticating username Administrator<BR>javax.security.auth.login.LoginException: Error: <A href="mailto:javax.security.auth.callback.TextInputCallback@da3772">javax.security.auth.callback.TextInputCallback@da3772</A> not available to garner authentication information from the user<BR>at com.tagish.auth.win32.NTSystemLogin.login(NTSystemLogin.java:128)<BR>at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)<BR>at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)</P>
<P>Were you able to resolve the above? Please guide. </P>
<LI class="" id=comment-31><CITE><A href="http://www3.telus.net/thepasture/" rel="external nofollow">Louis A Johannson</A></CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-31">September 6th, 2004 at 7:12 pm</A> </SMALL>
<P>I’ve got the Tagish example working fine where I can use the batch login.bat to test a </P>
<P>login/authentication. I can also integrate it with JAAS security and have it authenticate me </P>
<P>against my network in a console application. However, as soon as I try to tie it into </P>
<P>Tomcat, I get stuck. (I’m trying an web-app example based on BASIC authentication)</P>
<P>I think my files are in the correct places (I get different errors when they’re missing) and </P>
<P>I can make my tomcat example web-app work using a different authentication method (the </P>
<P>tomcat manager’s memory-realm user authentication works fine) and I’ve even done the JAAS </P>
<P>example to replace the security realm of the tomcat manager app with JAAS.</P>
<P>The problem I’m getting now is that I get a serious bomb that kills tomcat as soon as I try </P>
<P>to access the protected directory:</P>
<P><CODE>An unexpected exception has been detected in native code outside the VM.<BR>Unexpected Signal : EXCEPTION_ACCESS_VIOLATION (0xc0000005) occurred at PC=0x7BF6256<BR>Function=[Unknown.]<BR>Library=C:\Projects\workspace3\example.Tomcat_NT\lib\NTSystem.dll</P>
<P>NOTE: We are unable to locate the function name symbol for the error<BR>just occurred. Please refer to release documentation for possible<BR>reason and solutions.</P>
<P>Current Java thread:<BR>at com.tagish.auth.win32.NTSystem.logon(Native Method)<BR>- locked &lt;0x10024d98&gt; (a com.tagish.auth.win32.NTSystem)<BR>at com.tagish.auth.win32.NTSystemLogin.login(NTSystemLogin.java:134)<BR>at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)<BR>...<BR></CODE></P>
<P>I’m really rather at a loss as to why this is happening. It ‘feels’ like there is something </P>
<P>wrong with the tagish module, but if others got it working I really don’t know. Did you have </P>
<P>to extend it at all? Or wrap it up in an implemented JAAS interface? (but tagish has done </P>
<P>that already haven’t they?)</P>
<P>Config:<BR>Tomcat 5.0.27/28<BR>Eclipse 3.0<BR>Sysdeo eclipse/tomcat plugin<BR>J2SDK 1.4.2_05<BR>Tagish 1.0.3</P>
<P>I also tried plugging the tagish module straight into a clean tomcat (without using any of </P>
<P>my code) to replace the security realm of the manager web-app. The error is slightly </P>
<P>different here:</P>
<P><CODE>7-Sep-2004 12:46:17 AM org.apache.catalina.realm.JAASRealm authenticate<BR>WARNING: Login exception authenticating username louis<BR>javax.security.auth.login.LoginException: Error: javax.security.auth.callback.Te<BR><A href="mailto:xtInputCallback@354749">xtInputCallback@354749</A> not available to garner authentication information from t<BR>he user<BR>at com.tagish.auth.win32.NTSystemLogin.login(NTSystemLogin.java:128)<BR>at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)<BR>at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.<BR>java:39)<BR>at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces<BR>sorImpl.java:25)<BR>at java.lang.reflect.Method.invoke(Method.java:324)<BR>at javax.security.auth.login.LoginContext.invoke(LoginContext.java:675)<BR>at javax.security.auth.login.LoginContext.access$000(LoginContext.java:1<BR>29)<BR>at javax.security.auth.login.LoginContext$4.run(LoginContext.java:610)<BR>at java.security.AccessController.doPrivileged(Native Method)<BR>at javax.security.auth.login.LoginContext.invokeModule(LoginContext.java<BR>:607)<BR>at javax.security.auth.login.LoginContext.login(LoginContext.java:534)<BR>at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:316)<BR>at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(Bas<BR>icAuthenticator.java:129)<BR></CODE></P>
<P>Does anyone have a clean working example in tomcat they’d be willing to zipup and post?</P>
<P>My proper email prefix is: louis_a_j<BR>Suffix: telus.net </P>
<LI class=alt id=comment-32><CITE>Louis A. Johannson</CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-32">September 6th, 2004 at 7:33 pm</A> </SMALL>
<P>P.S. As per the following post:<BR><A href?http: www.jboss.org index.html?module='bb&amp;op=viewtopic&amp;p=3837312#3837312"'>Tagish and JBOSS</A><BR>I’ve tried substituting a default domain into the tagish.login (my workgroup) but that just brought me back to the previous exception which kills tomcat.<BR>Note: I’ve tried this on both an NT4 domain and on a windows 2000 workgroup with the same results in both. </P>
<LI class="" id=comment-33><CITE>Louis Johannson</CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-33">September 7th, 2004 at 8:15 am</A> </SMALL>
<P>Sorry, the link I included broke:<BR><A href="http://www.jboss.org/index.html?module=bb&amp;op=viewtopic&amp;p=3837312#3837312" rel=nofollow>http://www.jboss.org/index.html?module=bb&amp;op=viewtopic&amp;p=3837312#3837312</A> </P>
<LI class=alt id=comment-121><CITE>Aaron Hawkins</CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-121">November 3rd, 2004 at 3:06 pm</A> </SMALL>
<P>I have the same problem as the #4 comment on this page submited by Louis Johannson. I can authenticate using a console app, but when I try and follow the instructions to authenticate agains Tomcat, my jvm blows up with the same error. It seems that there is a problem with NTSystem.dll. If it is anywhere on my path, my jvm will blow up when I try and use tomcat. If I delete it, then I get errors about it not being found. Has anyone found a solution to this? Any help would be appreciated. </P>
<LI class="" id=comment-124><CITE>Aaron Hawkins</CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-124">November 4th, 2004 at 7:19 am</A> </SMALL>
<P>I have found the solution to the problem described by post #4. The NTSystem.dll doesn’t appear to like a null username. When trying to get this to work with Tomcat, if you use Form based authentication, you can avoid sending a null username, and everything works great. </P>
<LI class=alt id=comment-206><CITE>rafal piotrowski</CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-206">November 19th, 2004 at 5:50 am</A> </SMALL>
<P>Hi<BR>I try to use samba ntlm filter first and I’ve got some problem.<BR>If I try to open some web page from my web app the internet browser logon dialog always shows.<BR>How should I configure my Windows XP workstation to eliminate this dialog. </P>
<LI class="" id=comment-401><CITE>mgr</CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-401">January 14th, 2005 at 7:25 am</A> </SMALL>
<P>Hi,<BR>I have a question about automatic authentication.</P>
<P>I have a windows 2003 server with active directory. Tomcats and JAAS libraries are correctly installed and configured. When I try to access to the web site I protected by the realm, a login/password is requiered, and I can access to the web site after authentication.</P>
<P>My question is: is it possible not to have the login/password dialog box if I access to Web site with a computer that belongs to the domain I create and if i’m logged with the correct login/password to have access.<BR>I would automatically enter to the web site as I’m already authenticated in the Windows session. Is that possible?</P>
<P>The case is the same if I try locally, on the server. I’m logged with an account who belongs to the domain, and this account belongs to the group I defined in the active directory and in the web.xml file of the web site. But the system ask me the login/password and don’t acces directly to the web site.</P>
<P>Thanks </P>
<LI class=alt id=comment-404><CITE><A href="http://jroller.com/page/melriffe/" rel="external nofollow">Mel Riffe</A></CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-404">January 18th, 2005 at 2:23 pm</A> </SMALL>
<P>I’m starting down this path also and having some troubles. One thing I noticed there is a typo in the instructions. I think you should update the java.security file like so:<BR><CODE>login.config.url.1=file:${java.home}<B>/jre</B>/lib/security/tagish.login</CODE></P>
<P>Plus I added the following to Tagish’s login.bat:<BR><CODE>-Djava.security.auth.login.config=C:\j2sdk1.4.2_06\jre\lib\security\tagish.login</CODE></P>
<P>Next step…authenticating in Tomcat…</P>
<P>- Mel </P>
<LI class="" id=comment-522><CITE>Trinition</CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-522">March 4th, 2005 at 5:09 pm</A> </SMALL>
<P>I modified the NTSystemLogin source in the Tagish JAAS module to throw a FailedLoginException for a null username or password,a nd not normal BASIC auth works. I presume the null was blowing up in the Tagish NTSYstem.dll or the call it makes to the Win32 API. I shared my update with the Tagish JAAS author, so I’ll see what he thinks. </P>
<LI class=alt id=comment-575><CITE>vicky</CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-575">April 1st, 2005 at 9:35 am</A> </SMALL>
<P>Hi, I am trying to use tagish with tomcat 5.0.27 and exactly getting all the same problems mentioned by others. Is there any clear way to use tagish??</P>
<P>Please advice.<BR>thanks<BR>aks </P>
<LI class="" id=comment-647><CITE>jh</CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-647">May 4th, 2005 at 2:05 pm</A> </SMALL>
<P>does this also work on websphere server? </P>
<LI class=alt id=comment-657><CITE>Kris Dover</CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-657">July 27th, 2005 at 1:47 pm</A> </SMALL>
<P>Aaron Hawkins, thanks a million. My tomcat 5.0.28 was also crashing with the Basic authentication and i noticed the username null entries in the stdout.log and wondered if that was causing it, but never made an attempt to resolve it using form base authentication until reading your message. seemed very unusual that tomcat’s basic authentication was returning nulls even when the correct username and password were entered on the first try. go figure. Trinition, i haven’t seen an update with your recommended fix, so i might just hack the java code myself. thanks. </P>
<LI class="" id=comment-658><CITE><A href="http://www.einvite.com/" rel="external nofollow">Joe</A></CITE> Says: <BR><SMALL class=commentmetadata><A title="" href="http://blog.cmaeda.com/?p=22#comment-658">August 4th, 2005 at 9:09 am</A> </SMALL>
<P>The TextInputCallback is issued when you do not have a defaultdomain=”yourdomain” in your tagish.login file, there is no way for a TextInputCallback to work through the servlet, the source should be changed so that it could parse the domain from the username callback if no default domain is specified, however some people may want to have a text callback for applications instead of servlets.</P>
<P>The Null username does indeed crash the NTSystem.dll, simply change the login attempt:<BR><CODE><BR>succeeded = false<BR>ntSystem.logon(username, password, domain); // may throw<BR>succeeded = true;<BR></CODE><BR>to:<BR><CODE><BR>succeeded = false;<BR>if (username == null || password == null) {<BR>throw new LoginException("Error: " + username == null ? "username" : "password" + ", null, not allowed");<BR>}<BR>ntSystem.logon(username, password, domain); // may throw<BR>succeeded = true;<BR></CODE><BR>and recompile the tagish src to a jar file, deploying it in the Tomcat/bin directory like explained above and everything will work correctly even with Basic auth.</P>
<P>This is great and all, but I don’t see how tagish is using NTLM, unless you mean it is talking to my domain to get my roles using kerberos or NTLM, it does not however provide the transparent login that jCIFS does. I looked throught the tagish source and don’t see anything in there either, did I misread your article or did I overlook something? </P></LI></OL><img src ="http://www.blogjava.net/lmsun/aggbug/10362.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-17 17:28 <a href="http://www.blogjava.net/lmsun/articles/10362.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tagish.net JAAS LoginModules</title><link>http://www.blogjava.net/lmsun/articles/10344.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Wed, 17 Aug 2005 07:48:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10344.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10344.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10344.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10344.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10344.html</trackback:ping><description><![CDATA[JAAS ( Java Authentication and Authorization Service ) 在 JDK 1.4 正式加入 Java 标准的 Security 模块, 简单来说, JAAS 就是让我们把身份验证与权限管控使用标准的方法来开发, 由于大家对 JAAS 的陌生度非常的高, 也不太了解 Application Server 的安全性架构, 所以这一部分往往会被忽略 .. <BR><BR><BR>这期先介绍有关 Authentication 的部分, JAAS 提供了 PAM ( Pluggable Authentication Module ) 的模块, 可 以通过标准的 API 建立属于自己的 LoginModule, 根据 stackable 原理, 进而相关相关的身份验证程序, 达到 SSO ( Single Sign-On ) 的 目的. <BR><BR><BR><FONT color=red><B>SECTION 02 </B>JAAS 中几个比较常见的 classes <BR><BR></FONT>本节详细解说请参考 <A href="http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASRefGuide.html">http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASRefGuide.html </A><BR><BR><BR>普通对象 
<UL>
<LI>Subject 
<LI>Principals 
<LI>Credentials </LI></UL>身份验证相关的对象 
<UL>
<LI>LoginContext 
<LI>LoginModule 
<LI>CallbackHandler 
<LI>Callback </LI></UL>权限管控相关的对象 
<UL>
<LI>Policy 
<LI>AuthPermission 
<LI>PrivateCredentialPermission </LI></UL><BR><FONT color=red><B>SECTION 03 </B>Tagish.net 的 LoginModules <BR><BR></FONT>现在地点 <A href="http://free.tagish.net/jaas/">http://free.tagish.net/jaas/</A> <BR><BR><BR>最新版本 1.0.3 <BR><BR><BR>目前 tagish.net 提供了几种 LoginModules, 包含了 
<UL>
<LI>com.tagish.auth.DBLogin 
<LI>com.tagish.auth.FileLogin 
<LI>com.tagish.auth.win32.NTSystemLogin </LI></UL>一般人大多比较熟悉数据库操作, 首先先建立一个 login.config, 內容为 <PRE class=code>JAASLogin
{
	com.tagish.auth.DBLogin required 
	dbDriver="sun.jdbc.odbc.JdbcOdbcDriver" dbURL="jdbc:odbc:DBLogin";
};
</PRE>将 Principal 设置为 com.tagish.auth.TypedPrincipal ( 如果是 NTSystemLogin 则设置为 com.tagish.auth.win32.NTPrincipal ). 接着, 你的数据库需要一些表, <IMG src="http://www.sentom.net/img/tagish_erd.png" border=0> <BR><BR>分别在数据库內设置完成. 当你启动你的程序的时候, 你需要在 classpath 中设置相关的 JDBC Driver, 让 SecurityManager 参考 login.config, 去调用 DBLogin api, 取得合法或不合法的状态. <BR><BR><BR><FONT color=red><B>SECTION 04 </B>关于 PAM stack <BR><BR></FONT><PRE class=code>    Login2 {
       sample.SampleLoginModule required;
       com.sun.security.auth.module.NTLoginModule sufficient;
       com.foo.SmartCard requisite debug=true;
       com.foo.Kerberos optional debug=true;
    };
</PRE>假如我们用 Login2 的这种登陆stack, 可以设置 required, sufficient, requisite, optional 四种状态. 
<UL>
<LI>required : 验证必须成功, 但是不论成功或失败都继续执行下面的登陆模块, 执行所有之后才丟出验证失败. 
<LI>requisite : 验证必须成功, 但是失败就马上回去不做其他验证, 必须成功才继续执行下面的登陆模块. 
<LI>sufficient : 验证可以不要成功, 但是成功了就马上回去不做其他验证, 失败可以继续执行其他的登陆模块. 
<LI>optional : 验证可以不要成功, 但是不论成功或失败都继续执行下面的登陆模块. </LI></UL>所以, Login2 的登陆, 首先我们会先使用 sample.SampleLoginModule 来验证,<BR><BR>不论成功或失败都会执行 com.sun.security.auth.module.NTLoginModule,<BR><BR>如果 NTLoginModule 验证成功, 因为是 sufficient, 系统就认定这个人是合法的使用者,<BR><BR>当 NTLoginModule 验证失败, 就会进行 com.foo.SmartCard 的验证,<BR><BR>如果 SmartCard 验证失败, 就直接宣告你不是合法的使用者,<BR><BR>如果 SmartCard 验证成功, 就继续到 Kerberos 的验证模块,<BR><BR>因为 Kerberos 是属于 optional, 所以根本对身份验证的结果没有影响.<BR><BR>
<TABLE cellSpacing=0 cellPadding=3 summary="Login2 Authentication Status" border=1>
<THEAD>
<TR>
<TH colSpan=10><B>Login2 验证的各种状况列表</B></FONT> </TR></TR></THEAD>
<TBODY>
<TR>
<TD>SampleLoginModule</TD>
<TD>required</TD>
<TD>pass</TD>
<TD>pass</TD>
<TD>pass</TD>
<TD>pass</TD>
<TD>fail</TD>
<TD>fail</TD>
<TD>fail</TD>
<TD>fail</TD></TR>
<TR>
<TD>NTLoginModule</TD>
<TD>sufficient</TD>
<TD>pass</TD>
<TD>fail</TD>
<TD>fail</TD>
<TD>fail</TD>
<TD>pass</TD>
<TD>fail</TD>
<TD>fail</TD>
<TD>fail</TD></TR>
<TR>
<TD>SmartCard</TD>
<TD>requisite</TD>
<TD>*</TD>
<TD>pass</TD>
<TD>pass</TD>
<TD>fail</TD>
<TD>*</TD>
<TD>pass</TD>
<TD>pass</TD>
<TD>fail</TD></TR>
<TR>
<TD>Kerberos</TD>
<TD>optional</TD>
<TD>*</TD>
<TD>pass</TD>
<TD>fail</TD>
<TD>*</TD>
<TD>*</TD>
<TD>pass</TD>
<TD>fail</TD>
<TD>*</TD></TR>
<TR>
<TD colSpan=2>Overall Authentication</TD>
<TD>pass</TD>
<TD>pass</TD>
<TD>pass</TD>
<TD>fail</TD>
<TD>fail</TD>
<TD>fail</TD>
<TD>fail</TD>
<TD>fail</TD></TR></TBODY></TABLE>* = 不会被执行. 直接回应验证成或失败<BR><BR><BR><FONT color=red><B>SECTION 05 </B>套用 Tomcat 4/5 的 JAASRealm <BR><BR></FONT>建立 login.config 放到 $CATALINA_HOME/conf/ 之中, 范例采用 MS SQLServer, jTds.sf.net 的 jdbc driver <PRE class=code>JAASLoginModule
{
com.tagish.auth.DBLogin required dbDriver="net.sourceforge.jtds.jdbc.Driver" 
dbURL="jdbc:jtds:sqlserver://localhost:1433/JAASDB" 
dbUser="sa" 
dbPassword="sa_password"
userTable="Users"
roleTable="Roles"
roleMapTable="RoleMap";
};
</PRE>在 tomcat 启动脚本中加入<BR> <B>JAVA_OPTS=-Djava.security.auth.login.config==C:\tomcat4\conf\login.config</B> 并且修改 server.xml, 让 appName 去对应 login.config 中的 JAASLoginModule, 以及设置 User/Group 相关的 Principal <PRE class=code>&lt;Realm className="org.apache.catalina.realm.JAASRealm"                 
			 appName="JAASLoginModule"
		 userClassNames="com.tagish.auth.TypedPrincipal"       
		 roleClassNames="com.tagish.auth.TypedPrincipal" 
			debug="99"/&gt;
</PRE>最后设置 web.xml 中的 login-config 以及要保护的数据, 例如 <PRE class=code>		
  &lt;security-constraint&gt;
    &lt;web-resource-collection&gt;
      &lt;web-resource-name&gt;User Protected&lt;/web-resource-name&gt;
      &lt;url-pattern&gt;/protected/*&lt;/url-pattern&gt;
      &lt;url-pattern&gt;/protected.jsp&lt;/url-pattern&gt;
    &lt;/web-resource-collection&gt;
    &lt;auth-constraint&gt;
       &lt;role-name&gt;user&lt;/role-name&gt;
    &lt;/auth-constraint&gt;
  &lt;/security-constraint&gt;
  &lt;login-config&gt;
    &lt;auth-method&gt;BASIC&lt;/auth-method&gt;
    &lt;realm-name&gt;MyJAASRealm&lt;/realm-name&gt;
  &lt;/login-config&gt;
</PRE><FONT color=red><B>SECTION 06 </B>结论 <BR><BR></FONT>JAAS 除了在一般 Desktop Application 应用之外, 对 J2EE 支持将会是一个主流, 无论是 <A href="http://www.jcp.org/en/jsr/detail?id=196">JSR 196: Java Authentication Service Provider Interface for Containers</A> 还 是 <A href="http://www.jcp.org/en/jsr/detail?id=115">JSR 115: Java Authorization Contract for Containers</A> ( 已经纳入 J2EE 1.4 之中 ) 都是对 container 提供者要求标准的 provider 界面, 因此, 将来开发相关的程序最好能够遵循 JAAS, 在异构平台的整合 上, 才能具备完整的相容性. <img src ="http://www.blogjava.net/lmsun/aggbug/10344.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-17 15:48 <a href="http://www.blogjava.net/lmsun/articles/10344.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WEB应用中的基本身份验证和表单身份验证(中文)</title><link>http://www.blogjava.net/lmsun/articles/10307.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Wed, 17 Aug 2005 02:07:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10307.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10307.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10307.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10307.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10307.html</trackback:ping><description><![CDATA[<P>Translated by Caiyi0903(Willpower)，2004.4.23 </P>
<P>在任何一种WEB应用开发中，不论大中小规模的，每个开发者都会遇到一些需要保护程序数据的问题，涉及到用户的LOGIN ID和PASSWORD。那么如何执行验证方式更好呢？实际上，有很多方式来实现。在本文里，我们不会把所有的验证方法都考虑到，我们的目的是让你学会如何以最简单最方便的验证方法来完成。下面将讨论基本的（BASIC）和基于表单的（FORM-BASED）验证方式。我们考虑使用TOMCAT作为WEB SERVER，它通过server.xml和web.xml文件提供基本的和基于表单的验证。JSP页面中的j_security_check 表单(for FORM-based) 需要两个参数：j_username和j_password。它们指定了在SQL数据库中的登陆角色。你能够看到，它的弹性化，可用性和必要性。</P>
<P>第一步，我们要下载TOMCAT和MYSQL，前者用来做WEB SERVER，后者用来做SQL SERVER。还要下载JDBCRealm工具，它在TOMCAT中使用，用来做MYSQL连接器，连接MYSQL数据库的。</P>
<P>我们假设你已经安装了TOMCAT和MYSQL，那么我们开始从SERVER的配置入手了。当然，你还需要安装JAVA的MYSQL连接驱动，我强烈建议只使用稳定的驱动版本，因为在有些情况下，alpha/beta版本的驱动不能正常工作。</P>
<P>下面我们来操作SQL数据库。老实说，MYSQL和TOMCAT是相当好的工具，它们都是跨平台的，不管你的操作系统是WINDOWS还是类似UNIX/LINUX的，它们都能正常运行。因此，不论运行环境，它们的配置过程都是绝对一样的。</P>
<P>MySQL<BR>在命令行中执行mysql 客户端命令，然后输入：</P>
<P>create database weblogin;<BR>这个将为你创建一个weblogin数据库，它将保存用户名和密码以及角色等一切信息。你对数据库所做的任何改变都会直接立即反映出来。比如说添加用户，改变用户密码和角色等。</P>
<P><BR>create table users (<BR>&nbsp;&nbsp; login varchar (15) not null,<BR>&nbsp;&nbsp; pass varchar (15) not null,<BR>&nbsp;&nbsp; primary key (login)<BR>);</P>
<P>我们创建一个users表用来保存用户的LOGIN和PASSWORD：</P>
<P><BR>create tables groups (<BR>&nbsp;&nbsp; login varchar (15) not null,<BR>&nbsp;&nbsp; group varchar (15) not null,<BR>&nbsp;&nbsp; primary key (login, group)<BR>);</P>
<P>如你看到的，我们要在group表里保存login属于哪个group的信息。下面，我们要插于一些数据用来测试使用，并完成MYSQL的配置工作：</P>
<P>insert into users&nbsp; ('green', 'testpwd');<BR>insert into groups ('green', 'testgroup');</P>
<P><BR>现在，我们创建了一个用户叫green，他的密码是testpwd，他属于testgroup这个用户组。接着，轮到TOMCAT的配置了。</P>
<P>Tomcat<BR>TOMCAT本身并没有能力操作数据库来实现身份验证。但是可以依靠JDBCRealm。下面我们来使用它。</P>
<P>下面我们从TOMCAT的\conf\server.xml文件来开始我们的配置。打开这个文件并找到下面的内容:</P>
<P>&lt;Realm className="org.apache.catalina.realm.MemoryRealm" /&gt;<BR>删除这一行，或者用&lt;!-- ... --&gt; 注释掉它,我们要使用JDBCRealm。所以输入下面的内容:</P>
<P><BR>&lt;Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"<BR>&nbsp;&nbsp; driverName="org.gjt.mm.mysql.Driver"<BR>&nbsp;&nbsp; connectionURL="jdbc:mysql://localhost/weblogin?user=test&amp;password=test"<BR>&nbsp;&nbsp; userTable="users" userNameCol="login" userCredCol="pass"<BR>&nbsp;&nbsp; userRoleTable="groups" roleNameCol="group" /&gt;</P>
<P>下面我们对field参数做详细讲解:</P>
<P>debug—这是我们设置的debug参数，数字越高显示信息越详细。 <BR>driverName—这个是MYSQL驱动的名字。要确保这个驱动的JAR包在TOMCAT的CLASSPATH中能够找到它。 <BR>connectionURL—这个是用来建立JDBC连接的数据库URL。在这个field里，weblogin是我们数据库的名字。user和password 是我们登陆数据库的用户数据。 <BR>userTable—一个定义有userNameCol和userCredCol字段的表。 <BR>userNameCol和userCredCol—users表里定义的login和pass。 <BR>现在，我们完成了配置过程。下面，我们要配置WEB应用程序来被这样一个身份验证方式保护起来。我们要举两个例子。最简单的是基本身份验证方式，然后就是基于表单的身份验证。在第一种情况里，我们尝试访问受保护的数据，将会有一个POP-UP窗口弹出提示你输入你的login和password。在第二种情况里，我们会通过页面的方式来让你通过身份验证。这个页面的内容可以是任意的，这个取决于你要使用怎么样的验证方式了。</P>
<P>基本身份验证方式（BASIC authorization method）<BR>我们假设应用程序在TOMCAT的\webapps\webdemo, 我们要保护所有在admin 子目录里的文件。我们必须打开它的\webapps\webdemo\WEB-INF\web.xml文件，输入下列内容:</P>
<P><BR>&lt;security-constraint&gt;<BR>&nbsp;&nbsp; &lt;web-resource-collection&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;web-resource-name&gt;Web Demo&lt;/web-resource-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/admin/*&lt;/url-pattern&gt;<BR>&nbsp;&nbsp; &lt;/web-resource-collection&gt;<BR>&nbsp;&nbsp; &lt;auth-constraint&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;role-name&gt;testgroup&lt;/role-name&gt;<BR>&nbsp;&nbsp; &lt;/auth-constraint&gt;<BR>&lt;/security-constraint&gt;<BR>&lt;login-config&gt;<BR>&nbsp;&nbsp; &lt;auth-method&gt;BASIC&lt;/auth-method&gt;<BR>&nbsp;&nbsp; &lt;realm-name&gt;Web Demo&lt;/realm-name&gt;<BR>&lt;/login-config&gt;</P>
<P>让我们来看看刚才输入的内容。我们为应用程序创建了一个web-resource-name并映射到login-config 。我们还定义了url-pattern, 它指明你受保护程序的路径。在login-conf中，我们定义了一个BASIC auth-method。</P>
<P>很简单，对吗？不要忘记了，在使改变生效前要停止并重启TOMCAT。</P>
<P>表单身份验证方式（FORM-based authorization method）<BR>对于这种方式，我们仅仅只需要:</P>
<P>修改\webapps\webdemo\WEB-INF\web.xml <BR>创建一个登陆用的JSP页面, 用户将在这里的HTML表单中输入他的登陆ID和密码 <BR>创建一个JSP error页面，一旦验证失败，用户将跳到该页面<BR>如果你先尝试使用BASIC验证方式，你只需要改变login-config 为下面那一段代码。否则，你需要输入security-constraint代码段。使用下面的login-config:</P>
<P><BR>&lt;login-config&gt;<BR>&nbsp;&nbsp; &lt;auth-method&gt;FORM&lt;/auth-method&gt;<BR>&nbsp;&nbsp; &lt;realm-name&gt;Web Demo&lt;/realm-name&gt;<BR>&nbsp;&nbsp; &lt;form-login-config&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;form-login-page&gt;/admin/login.jsp&lt;/form-login-page&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;form-error-page&gt;/admin/error.jsp&lt;/form-error-page&gt;<BR>&nbsp;&nbsp; &lt;/form-login-config&gt;<BR>&lt;/login-config&gt;</P>
<P>我们设置表单的auth-method并定义了form-login-config。这个将使得TOMCAT使用 \admin\login.jsp页面来让用户登陆，使用\admin\error.jsp页面来处理登陆失败。</P>
<P>你可以使用任何你想要的出错信息。页面唯一需要的就是下面的HTML表单标签，你要插到页面中：</P>
<P><BR>...<BR>&lt;form method="POST" action="j_security_check"&gt;<BR>&nbsp;&nbsp; &lt;input type="text" name="j_username"&gt;<BR>&nbsp;&nbsp; &lt;input type="text" name="j_password"&gt;<BR>&nbsp;&nbsp; &lt;input type="submit" value="Log in"&gt;<BR>&lt;/form&gt;<BR>...</P>
<P>布局，风格，或其他所有你喜欢的。这个error页面能够做成任何你想要的。无非就是通知用户，验证失败了。</P>
<P>OK，全部完成了。你需要停止和重启一遍TOMCAT使得改变生效。</P>
<P>© Olexiy Prokhorenko, <A href="http://www.7dots.com/resume/">http://www.7dots.com/resume/</A><BR>Co-author: Alexander Prohorenko<BR></P><img src ="http://www.blogjava.net/lmsun/aggbug/10307.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-17 10:07 <a href="http://www.blogjava.net/lmsun/articles/10307.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Tocmat安全域实现安全认证</title><link>http://www.blogjava.net/lmsun/articles/10304.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Wed, 17 Aug 2005 01:57:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10304.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10304.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10304.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10304.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10304.html</trackback:ping><description><![CDATA[<P>安全域功能是Tomcat内置功能,在org.apache.catalina.Realm接口中声明了把一组用户名、口令及所关联的角色集成到Tocmat中的方法。</P>
<P>内存域：MemoryRealm 从XML文件中读取安全验证信息并存入内存中。<BR>JDBC域：JDBCRealm 通过JDBC驱动程序访问存放在数据库中的信息。<BR>数据源域：DataSourceRealm 通过JDBC数据源访问存放在数据库中的信息。<BR>JNDI域：JNDIRealm 通过JNDI provider访问存放在基于LDAP的目录服务器中的安全验证信息。</P>
<P>设置资源安全约束</P>
<P>在web.xml中加入&lt;security-constraint&gt;元素</P>
<P>&lt;security-constraint&gt;<BR>　&lt;display-name&gt;MZT&lt;/display-name&gt;<BR>　&lt;web-resource-collection&gt;<BR>　　　&lt;web-resource-name&gt;protected test&lt;/web-resource-name&gt;<BR>　　　&lt;url-pattern&gt;/test/*&lt;/url-pattern&gt;<BR>　　　&lt;http-method&gt;POST&lt;/http-method&gt;<BR>　　　&lt;http-method&gt;GET&lt;/http-method&gt;<BR>　&lt;/web-resource-collection&gt;<BR>　&lt;auth-constraint&gt;<BR>　　&lt;role-name&gt;mztadmin&lt;/role-name&gt;<BR>　&lt;/auth-constraint&gt;<BR>&lt;/security-constraint&gt;<BR>&lt;login-config&gt;<BR>　&lt;auth-method&gt;BASIC&lt;/auth-method&gt;<BR>　&lt;realm-name&gt;test realm&lt;/realm-name&gt;<BR>&lt;/login-config&gt;</P>
<P><BR>设置JDBC域</P>
<P>&lt;Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"<BR>driverName="org.gjt.mm.mysql.Driver"<BR>connectionURL="jdbc:mysql://localhost/mzt"<BR>connectionName="root" connectionPassword=""<BR>userTable="users" userNameCol="user_name" userCredCol="user_pass"<BR>userRoleTable="user_roles" roleNameCol="role_name" /&gt;</P>
<P><BR>&lt;Realm className="org.apache.catalina.realm.DataSourceRealm" debug="99"<BR>dataSourceName="jdbc/tomcatusers"<BR>userTable="users" userNameCol="user_name" userCredCol="user_pass"<BR>userRoleTable="user_roles" roleNameCol="role_name"/&gt;</P>
<P><BR>在MySQL中执行以下SQL语句:</P>
<P>#########</P>
<P>#用户表<BR>create table users(<BR>user_name varchar(15) not null primary key,<BR>user_pass varchar(15) not null<BR>);</P>
<P>#用户角色表<BR>create table user_roles(<BR>user_name varchar(15) not null,<BR>role_name varchar(15) not null,<BR>primary key(user_name, role_name)<BR>);</P>
<P>insert into users values('mzt','test');<BR>insert into user_roles values('mzt','mztadmin');<BR></P><img src ="http://www.blogjava.net/lmsun/aggbug/10304.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-17 09:57 <a href="http://www.blogjava.net/lmsun/articles/10304.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Web应用中使用BASIC和基于Form的验证</title><link>http://www.blogjava.net/lmsun/articles/10301.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Wed, 17 Aug 2005 01:45:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10301.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10301.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10301.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10301.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10301.html</trackback:ping><description><![CDATA[<P>大家司空见惯了使用自己的机制进行用户的验证，其实，Tomcat本身就对用户的认证提供了支持，使用Tomcat自身的认证功能，只需要进行一些简单的配置就可以完成用户的验证功能。如果还没有使用过，读读这篇文章吧。</P>
<P>BASIC and FORM-based Authorization in Your Web Application<BR>By Olexiy &amp; Alexander Prokhorenko</P>
<P>In the development of any, more-or-less big Web application, every developer collides at times with the problem of how to bear certain parts of the application in the protected area and to divide access to them by login and password. How do you carry out authentication? Actually, there are a lot of variants. In this article, we do not present a problem to consider all possibilities; our purpose is to learn how to work with the simplest yet rather convenient method of authorization. We will talk about BASIC and FORM-based authorizations. As a Web server, we will consider Tomcat, which provides BASIC and FORM-based authentication through server.xml and web.xml files; the use of a j_security_check form (for FORM-based) in a JSP page that requires two parameters j_username and j_password; and specifying roles (groups) within the SQL database. As you can see, it's a flexible, useful, and necessary set of capabilities.</P>
<P>To begin with, you need to download Tomcat, which we will use as a Web server and MySQL, which we will use as a SQL server. Also, you need to download the JDBCRealm tool which will be used with Tomcat, and the MySQL Connector/J to use with MySQL.</P>
<P>We assume you have installed Tomcat and MySQL properly, so we can start right from the server's configuration. Of course, you also need to install the MySQL Connector/J driver, and I strongly recommend using only stable releases of the driver because, in some cases, alpha/beta versions of the driver do not work in the given sheaf.</P>
<P>First of all, we will work with the SQL database. Honestly speaking, MySQL, as well as Tomcat, is pretty universal, and doesn't depend on the OS in which you are using it (Windows or Unix-like system), so the process of configuration will be absolutely the same; it doesn't matter where you run it.</P>
<P><BR>MySQL</P>
<P>Execute the mysql client from the installation binary directory and type:</P>
<P>create database weblogin;<BR>This will create the weblogin database in which we will keep user names, passwords, roles?everything. Thus, any changes you have made to the database directly (new users, changed passwords or roles, and so forth) will be reflected immediately.</P>
<P><BR>create table users (<BR>&nbsp;&nbsp; login varchar (15) not null,<BR>&nbsp;&nbsp; pass varchar (15) not null,<BR>&nbsp;&nbsp; primary key (login)<BR>);</P>
<P>We will keep the user's login and password in this users table.</P>
<P><BR>create tables groups (<BR>&nbsp;&nbsp; login varchar (15) not null,<BR>&nbsp;&nbsp; group varchar (15) not null,<BR>&nbsp;&nbsp; primary key (login, group)<BR>);</P>
<P>As you can see, we will keep information about which login belongs to which group in this groups table. Let's fill our tables with some test data and finish the process of MySQL configuration:</P>
<P><BR>insert into users&nbsp; ('green', 'testpwd');<BR>insert into groups ('green', 'testgroup');</P>
<P>So, we created the user green with the password testpwd in the group testgroup. And now, it's Tomcat's turn to be configured.</P>
<P><BR>Tomcat</P>
<P>Tomcat itself has no ability to work with the database to carry out authentication. However, there is JDBCRealm for these purposes; we are going to use that.</P>
<P>We will start our configuration from Tomcat's \conf\server.xml file. Open this file and find the following string:</P>
<P>&lt;Realm className="org.apache.catalina.realm.MemoryRealm" /&gt;<BR>Remove this line or just comment it by using &lt;!-- ... --&gt; Instead of it, we will use JDBCRealm. Type the following:</P>
<P><BR>&lt;Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"<BR>&nbsp;&nbsp; driverName="org.gjt.mm.mysql.Driver"<BR>&nbsp;&nbsp; connectionURL="jdbc:mysql://localhost/weblogin?user=test&amp;password=test"<BR>&nbsp;&nbsp; userTable="users" userNameCol="login" userCredCol="pass"<BR>&nbsp;&nbsp; userRoleTable="groups" roleNameCol="group" /&gt;</P>
<P>We will consider all mentioned fields in a bit more detail:</P>
<P>debug?Here, we set the debug level. A higher number generates more detailed output. <BR>driverName?The name of our MySQL driver. You need to be sure that the driver's JAR file is located in Tomcat's CLASSPATH. <BR>connectionURL?The database URL that is used to establish a JDBC connection. In this field, weblogin is the name of our database; user and password are login data with which you are connecting to the database. In MySQL, such a user is created by default, so you can use it. In case you don't have such a user, you need to create your own user and make it capable of working with your weblogin database. <BR>userTable?A table with at least two fields, defined in userNameCol and userCredCol. <BR>userNameCol and userCredCol?The fields with the name of login field from the users table and pass. <BR>Now, we are at the stage of finishing the configuration process. We need to configure your Web application to be protected with such an authentication. Below, we show examples of two configurations. The simplest is a BASIC authentification method, and a little more original method is a FORM-based one. In the first case at attempting to access the protected area, a pop-up window will appear with the requirement to enter your login and password. In the second case, we will get a page on which we will pass authentification on our defined JSP. The contents of a page can be anything; it should meet only few simple requirements on the contents of a HTML &lt;form&gt; tag. It is up to you what authorization methods you will use.</P>
<P><BR>Basic authorization method</P>
<P>Let's assume that our Web application is located in Tomcat's \webapps\webdemo, and we need to protect all files placed in the admin subdirectory. We need to open its \webapps\webdemo\WEB-INF\web.xml file and type the following text:</P>
<P><BR>&lt;security-constraint&gt;<BR>&nbsp;&nbsp; &lt;web-resource-collection&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;web-resource-name&gt;Web Demo&lt;/web-resource-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/admin/*&lt;/url-pattern&gt;<BR>&nbsp;&nbsp; &lt;/web-resource-collection&gt;<BR>&nbsp;&nbsp; &lt;auth-constraint&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;role-name&gt;testgroup&lt;/role-name&gt;<BR>&nbsp;&nbsp; &lt;/auth-constraint&gt;<BR>&lt;/security-constraint&gt;<BR>&lt;login-config&gt;<BR>&nbsp;&nbsp; &lt;auth-method&gt;BASIC&lt;/auth-method&gt;<BR>&nbsp;&nbsp; &lt;realm-name&gt;Web Demo&lt;/realm-name&gt;<BR>&lt;/login-config&gt;</P>
<P>Let me say a few words about what we just did. We created web-resource-name for our application and mapped login-config to this resource. We defined url-pattern, which has information about which sub-directory of our entire application will be protected, and which role-name is allowed to access the protected area. In login-conf, we defined a BASIC auth-method.</P>
<P>Pretty easy, isn't it? Do not forget to stop and re-start Tomcat to make these our changes work.</P>
<P>&nbsp;</P>
<P>FORM-based authorization method</P>
<P>For this method, we will only need to:</P>
<P>Modify \webapps\webdemo\WEB-INF\web.xml <BR>Create a login JSP page, on which the user will get a HTML form to enter his login and password <BR>Create a JSP error page that the user will get if an error happened during authorization <BR>So, let's start from the very beginning. In case you tried the BASIC authorization method first, you need just to change the login-config section to the one listed below. Otherwise, you need to type the security-constraint section from the BASIC method (it's absolutely the same), but use the following login-config:</P>
<P><BR>&lt;login-config&gt;<BR>&nbsp;&nbsp; &lt;auth-method&gt;FORM&lt;/auth-method&gt;<BR>&nbsp;&nbsp; &lt;realm-name&gt;Web Demo&lt;/realm-name&gt;<BR>&nbsp;&nbsp; &lt;form-login-config&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;form-login-page&gt;/admin/login.jsp&lt;/form-login-page&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;form-error-page&gt;/admin/error.jsp&lt;/form-error-page&gt;<BR>&nbsp;&nbsp; &lt;/form-login-config&gt;<BR>&lt;/login-config&gt;</P>
<P>We set the FORM's auth-method and defined the form-login-config section; this will force Tomcat to use the \admin\login.jsp page as the page with the HTML form for the user to sign in, and use \admin\error.jsp in case the login failed.</P>
<P>You can have any login and error screen you like; the only requirement is that HTML &lt;form&gt; should be the following (to be more exact, it should have fields defined as such):</P>
<P><BR>...<BR>&lt;form method="POST" action="j_security_check"&gt;<BR>&nbsp;&nbsp; &lt;input type="text" name="j_username"&gt;<BR>&nbsp;&nbsp; &lt;input type="text" name="j_password"&gt;<BR>&nbsp;&nbsp; &lt;input type="submit" value="Log in"&gt;<BR>&lt;/form&gt;<BR>...</P>
<P>The layout, styles, or whatever else could be anything you like. The error page could be anything you want; you will need to inform the user that there that something is wrong with the authentication.</P>
<P>That is all. You need to stop and re-start Tomcat to make these changes work.</P>
<P>© Olexiy Prokhorenko, <A href="http://www.7dots.com/resume/">http://www.7dots.com/resume/</A><BR>Co-author: Alexander Prohorenko<BR></P><img src ="http://www.blogjava.net/lmsun/aggbug/10301.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-17 09:45 <a href="http://www.blogjava.net/lmsun/articles/10301.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>应用TOMCAT基于JDBC的的Realm（1）</title><link>http://www.blogjava.net/lmsun/articles/10300.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Wed, 17 Aug 2005 01:41:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10300.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10300.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10300.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10300.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10300.html</trackback:ping><description><![CDATA[<P>摘要<BR>　　Realm是一个用户数据库的概念，类似于Unix中的用户群组，它通过用户名和密码来标识一个用户，这个用户属于一定的角色（role）。而一个特殊的web应用资源，可以限定某个角色的用户才被许可访问。这种许可策略，使得web应用的整体权限控制与应用细节相剥离，从而获得更好的可配置性。下面我们通过比较常见的基于数据库，使用直接JDBC连接的Realm的配置使用情况，看看它是如何实现粗粒度的ACL的。(2004-03-13 11:21:34)</P>
<P>--------------------------------------------------------------------------------<BR>By lanf</P>
<P>应用TOMCAT基于JDBC的的Realm （1） <BR>作（译）者：Lanf From LinuxAID </P>
<P>Realm是一个用户数据库的概念，类似于Unix中的用户群组，它通过用户名和密码来标识一个用户，这个用户属于一定的角色（role）。而一个特殊的web应用资源，可以限定某个角色的用户才被许可访问。这种许可策略，使得web应用的整体权限控制与应用细节相剥离，从而获得更好的可配置性。下面我们通过比较常见的基于数据库，使用直接JDBC连接的Realm的配置使用情况，看看它是如何实现粗粒度的ACL的。 </P>
<P>JDBCRealm </P>
<P>JDBCRealm是使用JDBC连接关系数据库的一个Tomcat 4 Realm接口的实现。它可以直接使用你现有的用户数据库表，来获取角色用户的信息，完成验证。你必须满足以下条件：</P>
<P>必须有个有效的数据表，里面有所有你需要通过Realm来认证的用户。这张表必须至少有两个字段，可以用来标示用户名和密码。 <BR>需要有一张表来标明用户与角色的对应关系，用户可以有任意个角色，没有角色也是合法的，这是和UNIX用户群组的不同之处。同样这个表也需要两个字段，来映射用户名与角色名的对应关系。 <BR>数据库准备 </P>
<P>在我们的例子中，我们建两张新表来处理realm的认证。 <BR>create table users (<BR>&nbsp; user_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; varchar(15) not null primary key,<BR>&nbsp; user_pass&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; varchar(15) not null<BR>);</P>
<P>create table user_roles (<BR>&nbsp; user_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; varchar(15) not null,<BR>&nbsp; role_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; varchar(15) not null,<BR>&nbsp; primary key (user_name, role_name)<BR>); <BR>&nbsp;</P>
<P><BR>JDBC驱动 </P>
<P>你需要将你的JDBC启动包放在 $CATALINA_HOME/server/lib 目录或者 $CATALINA_HOME/common/lib 目录下，确保Tomcat能通过CLASSPATH找到它。使用mysql数据库的话，你可以使用类似 mm.mysql-2.0.4-bin.jar 的驱动包；Oracle 9i你可以使用ojdbc14.jar等Oracle自带的驱动；PostgreSQL可以在<A href="http://jdbc.postgresql.org/">http://jdbc.postgresql.org/</A> 取得合适的驱动程序。 </P>
<P>编辑server.xml </P>
<P>编辑$CATALINA_HOME/conf/server.xml文件，在host里添加如下片段（以MySQL为例） <BR>&nbsp;&lt;Realm className = 'org.apache.catalina.realm.JDBCRealm' debug='0'<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driverName = 'org.gjt.mm.mysql.Driver'<BR>connectionURL = 'jdbc:mysql://localhost/authority?user=dbuser&amp;password=dbpass'<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; userTable='users' userNameCol='user_name' userCredCol='user_pass'<BR>&nbsp;&nbsp; userRoleTable='user_roles' roleNameCol='role_name'/&gt;</P>
<P>&nbsp;</P>
<P><BR>其中 jdbc:mysql://localhost/authority?user=dbuser&amp;password=dbpass 是Mysql的连接串，你可以根据你的需要进行修改。其有关属性介绍如下： 属性 描述 <BR>className Realm的实现类，这里必须是 'org.apache.catalina.realm.JDBCRealm' <BR>&nbsp;<BR>connectionName 数据库用户名<BR>&nbsp;<BR>connectionPassword 数据库用户的密码<BR>&nbsp;<BR>connectionURL 数据库的JDBC连接串<BR>&nbsp;<BR>debug Debug的程度，它和Logger相关配置配合使用，值越高信息越详细，缺省为0<BR>&nbsp;<BR>digest 存储密码的加密方式，如果不指定则是明文存储。指定为 java.security.MessageDigest 之类的类名则要看数据库里表中用户密码的存放格式。 <BR>&nbsp;<BR>driverName 数据库驱动程序类<BR>&nbsp;<BR>roleNameCol 角色表的存放角色名的字段名.<BR>&nbsp;<BR>userCredCol 用户表里存放密码的字段名<BR>&nbsp;<BR>userNameCol 用户表中存放用户名的字段名<BR>&nbsp;<BR>userRoleTable 角色表的表名（类似/etc/group）<BR>&nbsp;<BR>userTable 用户表的表名<BR>&nbsp;</P>
<P><BR>注意点 </P>
<P>如果你对用户表进行了新增操作和修改操作，那么会实时作用于正要进行登陆操作的用户； <BR>用户已经完成登陆后，你对它进行的删除修改操作，并不能实时作用于用户的当前状态，只能在此用户下次登陆的时候生效；（如果是基于表单认证的用户，是在会话结束或者他注销后当前认证失效；如果是基础认证的用户则需要等到当前窗口关闭） <BR>对数据库里那两个表的增删改管理，你需要自行编写合适的业务代码，Tomcat并没有提供标准的实现，这是没有意义的。 <BR>编译者注：这部分内容是帮助newbie理解Realm而直接从Realm Configuration HOW-TO中摘译的，是我们完整例子所必须要了解并正确配置的部分，不过似乎没有看到类似的译文，就做了这件累赘的事情。这系列文章对熟手基本没有什么帮助，请见谅。 </P>
<P>&nbsp;</P><img src ="http://www.blogjava.net/lmsun/aggbug/10300.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-17 09:41 <a href="http://www.blogjava.net/lmsun/articles/10300.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tomcat5.0+mysql配置JDBCRealm,DBCP,ssl,及中文乱码解决详解</title><link>http://www.blogjava.net/lmsun/articles/10299.html</link><dc:creator>my java</dc:creator><author>my java</author><pubDate>Wed, 17 Aug 2005 01:38:00 GMT</pubDate><guid>http://www.blogjava.net/lmsun/articles/10299.html</guid><wfw:comment>http://www.blogjava.net/lmsun/comments/10299.html</wfw:comment><comments>http://www.blogjava.net/lmsun/articles/10299.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lmsun/comments/commentRss/10299.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lmsun/services/trackbacks/10299.html</trackback:ping><description><![CDATA[<P>准备环境:<BR>1.j2sdk-1_4_2-windows-i586.exe&nbsp;&nbsp;&nbsp; //jdk<BR>2.mysql-4.0.20d-win.zip&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //mysql数据库<BR>3.mysqlcc-0.9.4-win32.zip&nbsp;&nbsp;&nbsp; //mysqlGUI控制<BR>4.jakarta-tomcat-5.0.27.exe&nbsp;&nbsp;&nbsp; //tomcat服务器<BR>5.mysql-connector-java-3.0.14-production.zip //内含mysql驱动</P>
<P>安装步骤:<BR>1.安装jdk<BR>2.安装tomcat<BR>3.安装mysql<BR>4.安装mysqlcc<BR>5.将驱动包解压,拷贝mysql-connector-java-3.0.14-production-bin.jar到tomcat/common/lib下<BR>或者下载mm.mysql-2.0.14-you-must-unjar-me.jar,解压后拷贝其中的mm.mysql-2.0.14-bin.jar</P>
<P>Tomcat5.0配置 本例使用安装密码 198277<BR>1.配置manager 管理应用程序<BR>在conf/server.xml 中<BR>添加如下</P>
<P>&lt;Service name="Catalina"&gt;<BR>...</P>
<P>&nbsp;&nbsp;&nbsp; &lt;Context path="/manager" debug="0" privileged="true"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; docBase="/usr/local/kinetic/tomcat5/server/webapps/manager"&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/Context&gt;</P>
<P>&lt;/Service&gt; </P>
<P>限制ip访问配置<BR>&lt;Context path="/manager" debug="0" privileged="true"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; docBase="/usr/local/kinetic/tomcat5/server/webapps/manager"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Valve className="org.apache.catalina.valves.RemoteAddrValve"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; allow="127.0.0.1"/&gt;<BR>&lt;/Context&gt;<BR>测试为:http://localhost:8080/manager/html</P>
<P>2.配置JDBCRealm容器管理安全,以mysql-4.0数据库为例<BR>a.拷贝驱动mm.mysql-2.0.14-bin.jar到common/lib/下<BR>b.在数据库ycg中建表<BR>&nbsp;&nbsp; <BR>&nbsp;create table users (<BR>&nbsp; user_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; varchar(15) not null primary key,<BR>&nbsp; user_pass&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; varchar(15) not null<BR>);</P>
<P>create table user_roles (<BR>&nbsp; user_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; varchar(15) not null,<BR>&nbsp; role_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; varchar(15) not null,<BR>&nbsp; primary key (user_name, role_name)<BR>);</P>
<P>c.修改server.xml如下(默认数据库为root,无密码,如果有形如:connectionURL="jdbc:mysql://localhost/authority?</P>
<P>user=dbuser&amp;password=dbpass")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Realm&nbsp; className="org.apache.catalina.realm.JDBCRealm" debug="99"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; driverName="org.gjt.mm.mysql.Driver"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connectionURL="jdbc:mysql://localhost/ycg?user=root"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connectionName="" connectionPassword=""<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; userTable="users" userNameCol="user_name" userCredCol="user_pass"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; userRoleTable="user_roles" roleNameCol="role_name" /&gt;</P>
<P>d.在数据库中添加入tomcat的默认配置数据:</P>
<P>+-----------+-----------+<BR>| user_name | role_name |<BR>+-----------+-----------+<BR>| admin&nbsp;&nbsp;&nbsp;&nbsp; | admin&nbsp;&nbsp;&nbsp;&nbsp; |<BR>| admin&nbsp;&nbsp;&nbsp;&nbsp; | manager&nbsp;&nbsp; |<BR>| both&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | role1&nbsp;&nbsp;&nbsp;&nbsp; |<BR>| both&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | tomcat&nbsp;&nbsp;&nbsp; |<BR>| role1&nbsp;&nbsp;&nbsp;&nbsp; | role1&nbsp;&nbsp;&nbsp;&nbsp; |<BR>| tomcat&nbsp;&nbsp;&nbsp; | tomcat&nbsp;&nbsp;&nbsp; |<BR>+-----------+-----------+<BR>+-----------+-----------+<BR>| user_name | user_pass |<BR>+-----------+-----------+<BR>| tomcat&nbsp;&nbsp;&nbsp; | tomcat&nbsp;&nbsp;&nbsp; |<BR>| both&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | tomcat&nbsp;&nbsp;&nbsp; |<BR>| role1&nbsp;&nbsp;&nbsp;&nbsp; | tomcat&nbsp;&nbsp;&nbsp; |<BR>| admin&nbsp;&nbsp;&nbsp;&nbsp; | 198277&nbsp;&nbsp;&nbsp; |<BR>+-----------+-----------+</P>
<P>e.启动mysql,启动tomcat,此后tomcat将从数据库中读用户规则认证.默认的conf/tomcat-users.xml失效</P>
<P>3.DBCP的配置<BR>a.设置<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;removeAbandoned&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;true&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;</P>
<P>&nbsp;可使失效的数据连接重新启用.<BR>配套设置<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;removeAbandonedTimeout&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;60&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<BR>失效时间<BR>如果要写入日志<BR>设置<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;logAbandoned&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;true&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<BR>以上三个默认都是false<BR>b.以mysql为例,配置数据连接池<BR>c.配置新的用户与数据库,必须设定密码,空密码将导致连接失败<BR>e.<BR>指定root密码:mysqladmin -u root -h localhost password "198277"<BR>(需修改上面的jdbcrealm设置connectionURL="jdbc:mysql://localhost/ycg?user=root&amp;password=198277")<BR>命令mysql进入匿名连接到服务器<BR>密码访问<BR>shell&gt; mysql -h host -u user -p<BR>Enter password: ********</P>
<P>//如果root没有密码,以下是不成功的.(试过了)<BR>&nbsp;mysql&gt; GRANT ALL PRIVILEGES ON *.* TO <A href="mailto:javauser@localhost">javauser@localhost</A> <BR>&nbsp;&nbsp;&nbsp; -&gt;&nbsp;&nbsp; IDENTIFIED BY 'javadude' WITH GRANT OPTION;<BR>mysql&gt; create database javatest;<BR>mysql&gt; use javatest;<BR>mysql&gt; create table testdata (<BR>&nbsp;&nbsp;&nbsp; -&gt;&nbsp;&nbsp; id int not null auto_increment primary key,<BR>&nbsp;&nbsp;&nbsp; -&gt;&nbsp;&nbsp; foo varchar(25), <BR>&nbsp;&nbsp;&nbsp; -&gt;&nbsp;&nbsp; bar int);</P>
<P>在conf/server.xml中&lt;host&gt;&lt;/host&gt;中添加<BR>&lt;Context path="/DBTest" docBase="DBTest"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; debug="5" reloadable="true" crossContext="true"&gt;</P>
<P>&nbsp; &lt;Logger className="org.apache.catalina.logger.FileLogger"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prefix="localhost_DBTest_log." suffix=".txt"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timestamp="true"/&gt;</P>
<P>&nbsp; &lt;Resource name="jdbc/TestDB"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auth="Container"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type="javax.sql.DataSource"/&gt;</P>
<P>&nbsp; &lt;ResourceParams name="jdbc/TestDB"&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;factory&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;org.apache.commons.dbcp.BasicDataSourceFactory&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;</P>
<P>&nbsp;&nbsp;&nbsp; &lt;!-- Maximum number of dB connections in pool. Make sure you<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; configure your mysqld max_connections large enough to handle<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; all of your db connections. Set to 0 for no limit.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;maxActive&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;100&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;</P>
<P>&nbsp;&nbsp;&nbsp; &lt;!-- Maximum number of idle dB connections to retain in pool.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set to 0 for no limit.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;maxIdle&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;30&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;</P>
<P>&nbsp;&nbsp;&nbsp; &lt;!-- Maximum time to wait for a dB connection to become available<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in ms, in this example 10 seconds. An Exception is thrown if<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this timeout is exceeded.&nbsp; Set to -1 to wait indefinitely.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;maxWait&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;10000&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;</P>
<P>&nbsp;&nbsp;&nbsp; &lt;!-- MySQL dB username and password for dB connections&nbsp; --&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;username&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;javauser&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;password&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;javadude&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;</P>
<P>&nbsp;&nbsp;&nbsp; &lt;!-- Class name for the old mm.mysql JDBC driver - uncomment this entry and comment next<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if you want to use this driver - we recommend using Connector/J though<BR>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;driverClassName&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;org.gjt.mm.mysql.Driver&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; &lt;!-- Class name for the official MySQL Connector/J driver --&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;driverClassName&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;com.mysql.jdbc.Driver&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; &lt;!-- The JDBC connection url for connecting to your MySQL dB.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The autoReconnect=true argument to the url makes sure that the<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mm.mysql JDBC Driver will automatically reconnect if mysqld closed the<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connection.&nbsp; mysqld by default closes idle connections after 8 hours.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;url&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;jdbc:mysql://localhost:3306/javatest?autoReconnect=true&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;</P>
<P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;removeAbandoned&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;true&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;removeAbandonedTimeout&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;60&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;logAbandoned&lt;/name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;true&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<BR>&nbsp; &lt;/ResourceParams&gt;<BR>&lt;/Context&gt;</P>
<P>f.在web服务中调用.配置web.xml 如:<BR>&lt;web-app xmlns="<A href="http://java.sun.com/xml/ns/j2ee">http://java.sun.com/xml/ns/j2ee</A>"<BR>&nbsp;&nbsp;&nbsp; xmlns:xsi="<A href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</A>"<BR>&nbsp;&nbsp;&nbsp; xsi:schemaLocation="<A href="http://java.sun.com/xml/ns/j2ee">http://java.sun.com/xml/ns/j2ee</A><BR><A href="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd</A>"<BR>&nbsp;&nbsp;&nbsp; version="2.4"&gt;<BR>&nbsp; &lt;description&gt;MySQL Test App&lt;/description&gt;<BR>&nbsp; &lt;resource-ref&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;description&gt;DB Connection&lt;/description&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;res-ref-name&gt;jdbc/TestDB&lt;/res-ref-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;res-type&gt;javax.sql.DataSource&lt;/res-type&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;res-auth&gt;Container&lt;/res-auth&gt;<BR>&nbsp; &lt;/resource-ref&gt;<BR>&lt;/web-app&gt;<BR>g.测试用test.jsp <BR>&lt;%@ taglib uri="<A href="http://java.sun.com/jsp/jstl/sql">http://java.sun.com/jsp/jstl/sql</A>" prefix="sql" %&gt;<BR>&lt;%@ taglib uri="<A href="http://java.sun.com/jsp/jstl/core">http://java.sun.com/jsp/jstl/core</A>" prefix="c" %&gt;</P>
<P>&lt;sql:query var="rs" dataSource="jdbc/TestDB"&gt;<BR>select id, foo, bar from testdata<BR>&lt;/sql:query&gt;</P>
<P>&lt;html&gt;<BR>&nbsp; &lt;head&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;title&gt;DB Test&lt;/title&gt;<BR>&nbsp; &lt;/head&gt;<BR>&nbsp; &lt;body&gt;</P>
<P>&nbsp; &lt;h2&gt;Results&lt;/h2&gt;<BR>&nbsp; <BR>&lt;c:forEach var="row" items="${rs.rows}"&gt;<BR>&nbsp;&nbsp;&nbsp; Foo ${row.foo}&lt;br/&gt;<BR>&nbsp;&nbsp;&nbsp; Bar ${row.bar}&lt;br/&gt;<BR>&lt;/c:forEach&gt;</P>
<P>&nbsp; &lt;/body&gt;<BR>&lt;/html&gt;</P>
<P>h.新建web应用<BR>下载jakarta-taglibs-standard-1.1.0<BR>copy jstl.jar and standard.jar to your web app's WEB-INF/lib </P>
<P>DBTest/<BR>&nbsp;&nbsp;&nbsp; WEB-INF/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; web.xml<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lib/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jstl.jar<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; standard.jar<BR>&nbsp;&nbsp;&nbsp; test.jsp<BR>拷贝到webapps/ 下<BR>i.启动mysql,tomcat <BR>访问:<BR><A href="http://localhost:8080/DBTest/test.jsp">http://localhost:8080/DBTest/test.jsp</A><BR>显示:<BR>&nbsp;&nbsp;&nbsp; Results<BR>&nbsp;&nbsp;&nbsp; Foo hello<BR>&nbsp;&nbsp;&nbsp; Bar 12345</P>
<P>4.ssl的配置,以jdk1.4.2为例<BR>a.进入%JAVA_HOME%\bin<BR>运行命令:keytool -genkey -alias tomcat -keyalg RSA<BR>以tomcat 安装密码为198277,ketool设置密码为198277为例<BR>输入keystore密码：&nbsp; 198277<BR>您的名字与姓氏是什么？<BR>&nbsp; [Unknown]：&nbsp; ycg<BR>您的组织单位名称是什么？<BR>&nbsp; [Unknown]：&nbsp; nju<BR>您的组织名称是什么？<BR>&nbsp; [Unknown]：&nbsp; nju<BR>您所在的城市或区域名称是什么？<BR>&nbsp; [Unknown]：&nbsp; nanjing<BR>您所在的州或省份名称是什么？<BR>&nbsp; [Unknown]：&nbsp; jiangsu<BR>该单位的两字母国家代码是什么<BR>&nbsp; [Unknown]：&nbsp; nd<BR>CN=ycg, OU=nju, O=nju, L=nanjing, ST=jiangsu, C=nd 正确吗？<BR>&nbsp; [否]：&nbsp; y</P>
<P>输入&lt;tomcat&gt;的主密码<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （如果和 keystore 密码相同，按回车）：&nbsp; 198277<BR>b.在你的D:\Documents and Settings\的当前用户目录下可以找到.keystore文件.将其拷贝到conf/文件夹下.<BR>c.在server.xml 中找到</P>
<P>&nbsp;&nbsp;&nbsp; &lt;!--<BR>&nbsp;&nbsp;&nbsp; &lt;Connector port="8443" <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxThreads="150" minSpareThreads="25" maxSpareThreads="75"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enableLookups="false" disableUploadTimeout="true"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acceptCount="100" debug="0" scheme="https" secure="true"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clientAuth="false" sslProtocol="TLS" /&gt;<BR>&nbsp;&nbsp;&nbsp; --&gt;<BR>&nbsp;&nbsp;&nbsp; 去掉注释</P>
<P>添加配置字段:keystoreFile="/conf/.keystore" keystorePass="198277"<BR>如: &lt;!-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 --&gt;<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; &lt;Connector port="8443" <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxThreads="150" minSpareThreads="25" maxSpareThreads="75"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enableLookups="false" disableUploadTimeout="true"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acceptCount="100" debug="0" scheme="https" secure="true"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clientAuth="false" sslProtocol="TLS" keystoreFile="/conf/.keystore"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystorePass="198277"/&gt;<BR>d.测试为:<BR><A href="https://localhost:8443">https://localhost:8443</A><BR>e.在自己的程序中添加ssl认证方式为:<BR>在web.xml 中&lt;web-app&gt;&lt;/web-app&gt;添加<BR>&lt;security-constraint&gt;<BR>&lt;web-resource-collection&gt;<BR>&lt;web-resource-name&gt;Success&lt;/web-resource-name&gt;<BR>&lt;url-pattern&gt;/&lt;/url-pattern&gt;<BR>&lt;http-method&gt;GET&lt;/http-method&gt;<BR>&lt;http-method&gt;POST&lt;/http-method&gt;<BR>&lt;/web-resource-collection&gt;<BR>&lt;user-data-constraint&gt;<BR>&lt;transport-guarantee&gt;CONFIDENTIAL&lt;/transport-guarantee&gt;<BR>&lt;/user-data-constraint&gt;<BR>&lt;/security-constraint&gt;<BR>f.用上提为例就是<BR>修改web.xml 为<BR>&lt;web-app xmlns="<A href="http://java.sun.com/xml/ns/j2ee">http://java.sun.com/xml/ns/j2ee</A>"<BR>&nbsp;&nbsp;&nbsp; xmlns:xsi="<A href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</A>"<BR>&nbsp;&nbsp;&nbsp; xsi:schemaLocation="<A href="http://java.sun.com/xml/ns/j2ee">http://java.sun.com/xml/ns/j2ee</A><BR><A href="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd</A>"<BR>&nbsp;&nbsp;&nbsp; version="2.4"&gt;</P>
<P>&nbsp;&nbsp;&nbsp; &lt;description&gt;MySQL Test App&lt;/description&gt;</P>
<P>&lt;security-constraint&gt;<BR>&lt;web-resource-collection&gt;<BR>&lt;web-resource-name&gt;Success&lt;/web-resource-name&gt;<BR>&lt;url-pattern&gt;/&lt;/url-pattern&gt;<BR>&lt;http-method&gt;GET&lt;/http-method&gt;<BR>&lt;http-method&gt;POST&lt;/http-method&gt;<BR>&lt;/web-resource-collection&gt;<BR>&lt;user-data-constraint&gt;<BR>&lt;transport-guarantee&gt;CONFIDENTIAL&lt;/transport-guarantee&gt;<BR>&lt;/user-data-constraint&gt;<BR>&lt;/security-constraint&gt;</P>
<P>&nbsp; <BR>&nbsp; &lt;resource-ref&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;description&gt;DB Connection&lt;/description&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;res-ref-name&gt;jdbc/TestDB&lt;/res-ref-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;res-type&gt;javax.sql.DataSource&lt;/res-type&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;res-auth&gt;Container&lt;/res-auth&gt;<BR>&nbsp; &lt;/resource-ref&gt;<BR>&lt;/web-app&gt;<BR>访问:<BR><A href="https://localhost:8443/DBTest/test.jsp">https://localhost:8443/DBTest/test.jsp</A></P>
<P>g.如果与2配置的jdbcRealm结合起来进行表单认证<BR>先在user_roles表中添加user_name:ycg role_name:web-user<BR>在users表中添加user_name:ycg user_pass:198277</P>
<P>然后在web.xml中添加<BR>&lt;auth-constraint&gt;<BR>&lt;role-name&gt;web-user&lt;/role-name&gt;<BR>&lt;/auth-constraint&gt;</P>
<P>&lt;login-config&gt;<BR>&nbsp;&lt;auth-method&gt;BASIC&lt;/auth-method&gt;<BR>&nbsp;&lt;realm-name&gt;My Member Area&lt;/realm-name&gt;<BR>&lt;/login-config&gt;</P>
<P>修改后的web.xml如:<BR>&lt;web-app xmlns="<A href="http://java.sun.com/xml/ns/j2ee">http://java.sun.com/xml/ns/j2ee</A>"<BR>&nbsp;&nbsp;&nbsp; xmlns:xsi="<A href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</A>"<BR>&nbsp;&nbsp;&nbsp; xsi:schemaLocation="<A href="http://java.sun.com/xml/ns/j2ee">http://java.sun.com/xml/ns/j2ee</A><BR><A href="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd</A>"<BR>&nbsp;&nbsp;&nbsp; version="2.4"&gt;</P>
<P>&nbsp;&nbsp;&nbsp; &lt;description&gt;MySQL Test App&lt;/description&gt;</P>
<P>&lt;security-constraint&gt;<BR>&lt;web-resource-collection&gt;<BR>&lt;web-resource-name&gt;Success&lt;/web-resource-name&gt;<BR>&lt;url-pattern&gt;/&lt;/url-pattern&gt;<BR>&lt;http-method&gt;GET&lt;/http-method&gt;<BR>&lt;http-method&gt;POST&lt;/http-method&gt;<BR>&lt;/web-resource-collection&gt;<BR>&lt;auth-constraint&gt;<BR>&lt;role-name&gt;web-user&lt;/role-name&gt;<BR>&lt;/auth-constraint&gt;<BR>&lt;user-data-constraint&gt;<BR>&lt;transport-guarantee&gt;CONFIDENTIAL&lt;/transport-guarantee&gt;<BR>&lt;/user-data-constraint&gt;<BR>&lt;/security-constraint&gt;<BR>&lt;login-config&gt;<BR>&nbsp;&lt;auth-method&gt;BASIC&lt;/auth-method&gt;<BR>&nbsp;&lt;realm-name&gt;My Member Area&lt;/realm-name&gt;<BR>&lt;/login-config&gt;<BR>&nbsp; <BR>&nbsp; &lt;resource-ref&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;description&gt;DB Connection&lt;/description&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;res-ref-name&gt;jdbc/TestDB&lt;/res-ref-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;res-type&gt;javax.sql.DataSource&lt;/res-type&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;res-auth&gt;Container&lt;/res-auth&gt;<BR>&nbsp; &lt;/resource-ref&gt;<BR>&lt;/web-app&gt;</P>
<P>测试:<BR><A href="http://localhost:8080/DBTest/test.jsp">http://localhost:8080/DBTest/test.jsp</A><BR>将通过ssl连接,并进行表单认证.用户密码可在user_roles,和users中添加.</P>
<P>5.中文乱码问题:<BR>mysql 默认编码 iso<BR>tomcat request 传输编码 iso <BR>如果要显示中文<BR>在*.jsp中添加<BR>&lt;head&gt;<BR>&lt;%@ page <BR>language="java"<BR>contentType="text/html; charset=GB18030"<BR>pageEncoding="GB18030"<BR>%&gt;<BR>&lt;/head&gt;<BR>如果是数据传输中的乱码(如用servlet从mysql数据库读出的数据)<BR>用以下两个转码函数转码,如果不清楚由哪种编码转成哪种编码,就多尝试.<BR>&nbsp;&nbsp;&nbsp; //转码GBK转ISO<BR>&nbsp;&nbsp;&nbsp; public String toISO(String input) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] bytes = input.getBytes("GBK");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new String(bytes,"ISO8859-1");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception ex) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return input;</P>
<P>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; //转码IS0转GBK<BR>&nbsp;&nbsp;&nbsp; public String toGBK(String input) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] bytes = input.getBytes("ISO8859-1");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new String(bytes,"GBK");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception ex) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return input;<BR>&nbsp;&nbsp;&nbsp; }</P>
<P><BR>以上配置都测试通过.主要参考tomcat5.0的帮助文档.将过程写出来与大家共享.如果发现其中错误,请指出.<BR>欢迎给我来信<A href="mailto:ycg01@software.nju.edu.cn">ycg01@software.nju.edu.cn</A>共同探讨. </P><img src ="http://www.blogjava.net/lmsun/aggbug/10299.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lmsun/" target="_blank">my java</a> 2005-08-17 09:38 <a href="http://www.blogjava.net/lmsun/articles/10299.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>