spring-security-2.0.7.RELEASE/0000755000000000000000000000000011766764244012655 5ustar spring-security-2.0.7.RELEASE/docs/0000755000000000000000000000000011766764657013615 5ustar spring-security-2.0.7.RELEASE/docs/reference/0000755000000000000000000000000011766764657015553 5ustar spring-security-2.0.7.RELEASE/docs/reference/samples.xml0000644000000000000000000001752611766764657017754 0ustar Sample Applications There are several sample web applications that are available with the project. To avoid an overly large download, only the "tutorial" and "contacts" samples are included in the distribution zip file. You can either build the others yourself, or you can obtain the war files individually from the central Maven repository. We'd recommend the former. You can get the source as described in the introduction and it's easy to build the project using Maven. There is more information on the project web site at http://www.springframework.org/spring-security/ if you need it. All paths referred to in this chapter are relative to the source directory, once you have checked it out from subversion.
Tutorial Sample The tutorial sample is a nice basic example to get you started. It uses simple namespace configuration throughout. The compiled application is included in the distribution zip file, ready to be deployed into your web container (spring-security-samples-tutorial-2.0.x.war). The form-based authentication mechanism is used in combination with the commonly-used remember-me authentication provider to automatically remember the login using cookies. We recommend you start with the tutorial sample, as the XML is minimal and easy to follow. Most importantly, you can easily add this one XML file (and its corresponding web.xml entries) to your existing application. Only when this basic integration is achieved do we suggest you attempt adding in method authorization or domain object security.
Contacts The Contacts Sample is quite an advanced example in that it illustrates the more powerful features of domain object access control lists in addition to basic application security. To deploy, simply copy the WAR file from Spring Security distribution into your container’s webapps directory. The war should be called spring-security-samples-contacts-2.0.0.war (the appended version number will vary depending on what release you are using). After starting your container, check the application can load. Visit http://localhost:8080/contacts (or whichever URL is appropriate for your web container and the WAR you deployed). Next, click "Debug". You will be prompted to authenticate, and a series of usernames and passwords are suggested on that page. Simply authenticate with any of these and view the resulting page. It should contain a success message similar to the following: Authentication object is of type: org.springframework.security.providers.UsernamePasswordAuthenticationToken Authentication object as a String: org.springframework.security.providers.UsernamePasswordAuthenticationToken@1f127853: Principal: org.springframework.security.userdetails.User@b07ed00: Username: rod; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_SUPERVISOR, ROLE_USER; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.ui.WebAuthenticationDetails@0: RemoteIpAddress: 127.0.0.1; SessionId: k5qypsawgpwb; Granted Authorities: ROLE_SUPERVISOR, ROLE_USER Authentication object holds the following granted authorities: ROLE_SUPERVISOR (getAuthority(): ROLE_SUPERVISOR) ROLE_USER (getAuthority(): ROLE_USER) SUCCESS! Your web filters appear to be properly configured! Once you successfully receive the above message, return to the sample application's home page and click "Manage". You can then try out the application. Notice that only the contacts available to the currently logged on user are displayed, and only users with ROLE_SUPERVISOR are granted access to delete their contacts. Behind the scenes, the MethodSecurityInterceptor is securing the business objects. The application allows you to modify the access control lists associated with different contacts. Be sure to give this a try and understand how it works by reviewing the application context XML files.
LDAP Sample The LDAP sample application provides a basic configuration and sets up both a namespace configuration and an equivalent configuration using traditional beans, both in the same application context file. This means there are actually two identical authentication providers configured in this application.
CAS Sample The CAS sample requires that you run both a CAS server and CAS client. It isn't included in the distribution so you should check out the project code as described in the introduction. You'll find the relevant files under the sample/cas directory. There's also a Readme.txt file in there which explains how to run both the server and the client directly from the source tree, complete with SSL support. You have to download the CAS Server web application (a war file) from the CAS site and drop it into the samples/cas/server directory.
Pre-Authentication Sample This sample application demonstrates how to wire up beans from the pre-authentication framework to make use of login information from a J2EE container. The user name and roles are those setup by the container. The code is in samples/preauth .
spring-security-2.0.7.RELEASE/docs/reference/taglibs.xml0000644000000000000000000000405311766764657017724 0ustar Tag Libraries
Overview Spring Security comes bundled with several JSP tag libraries that eases JSP writing. The tag libraries provide a range of different services.
Configuration All taglib classes are included in the core spring-security-xx.jar file, with the security.tld located in the JAR's META-INF directory. This means for JSP 1.2+ web containers you can simply include the JAR in the WAR's WEB-INF/lib directory and it will be available. If you're using a JSP 1.1 container, you'll need to declare the JSP taglib in your web.xml file, and include security.tld in the WEB-INF/lib directory. The following fragment is added to web.xml: <taglib> <taglib-uri>http://www.springframework.org/security/tags</taglib-uri> <taglib-location>/WEB-INF/security.tld</taglib-location> </taglib>
Usage Now that you've configured the tag libraries, refer to the individual reference guide sections for details on how to use them. Note that when using the tags, you should include the taglib reference in your JSP: <%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %>
spring-security-2.0.7.RELEASE/docs/reference/siteminder-auth-provider.xml0000644000000000000000000001140711766764657023232 0ustar Siteminder Authentication Mechanism
Overview Siteminder is a commercial single sign on solution by Computer Associates. Spring Security provides a filter, SiteminderAuthenticationProcessingFilter and provider, SiteminderAuthenticationProvider that can be used to process requests that have been pre-authenticated by Siteminder. This filter assumes that you're using Siteminder for authentication, and that you're using Spring Security for authorization. The use of Siteminder for authorization is not yet directly supported by Spring Security. When using Siteminder, an agent is setup on your web server to intercept a principal's first call to your application. The agent redirects the web request to a single sign-on login page, and once authenticated, your application receives the request. Inside the HTTP request is a header - such as SM_USER - which identifies the authenticated principal (please refer to your organization's "single sign-on" group for header details in your particular configuration).
Configuration The first step in setting up Spring Security's Siteminder support is to define the authentication mechanism that will inspect the HTTP header discussed earlier. It will be responsible for generating a UsernamePasswordAuthenticationToken that is later sent to the SiteminderAuthenticationProvider. Let's look at an example: <bean id="authenticationProcessingFilter" class="org.springframework.security.ui.webapp.SiteminderAuthenticationProcessingFilter"> <property name="authenticationManager"><ref bean="authenticationManager"/></property> <property name="authenticationFailureUrl"><value>/login.jsp?login_error=1</value></property> <property name="defaultTargetUrl"><value>/security.do?method=getMainMenu</value></property> <property name="filterProcessesUrl"><value>/j_spring_security_check</value></property> <property name="siteminderUsernameHeaderKey"><value>SM_USER</value></property> <property name="formUsernameParameterKey"><value>j_username</value></property> </bean> In our example above, the bean is being provided an AuthenticationManager, as is normally needed by authentication mechanisms. Several URLs are also specified, with the values being self-explanatory. It's important to also specify the HTTP header that Spring Security should inspect. If you additionally want to support form-based authentication (i.e. in your development environment where Siteminder is not installed), specify the form's username parameter as well - just don't do this in production! Note that you'll need a SiteminderAuthenticationProvider configured against your ProviderManager in order to use the Siteminder authentication mechanism. Normally an AuthenticationProvider expects the password property to match what it retrieves from the UserDetailsSource, but in this case, authentication has already been handled by Siteminder, so password property is not even relevant. This may sound like a security weakness, but remember that users have to authenticate with Siteminder before your application ever receives the requests, so the purpose of your custom UserDetailsService should simply be to build the complete Authentication object (ie with suitable GrantedAuthority[]s). Advanced tip and word to the wise: If you additionally want to support form-based authentication in your development environment (where Siteminder is typically not installed), specify the form's username parameter as well. Just don't do this in production!
spring-security-2.0.7.RELEASE/docs/reference/authorization-common.xml0000644000000000000000000007337311766764657022500 0ustar Common Authorization Concepts
Authorities As briefly mentioned in the Authentication section, all Authentication implementations are required to store an array of GrantedAuthority objects. These represent the authorities that have been granted to the principal. The GrantedAuthority objects are inserted into the Authentication object by the AuthenticationManager and are later read by AccessDecisionManagers when making authorization decisions. GrantedAuthority is an interface with only one method: String getAuthority(); This method allows AccessDecisionManagers to obtain a precise String representation of the GrantedAuthority. By returning a representation as a String, a GrantedAuthority can be easily "read" by most AccessDecisionManagers. If a GrantedAuthority cannot be precisely represented as a String, the GrantedAuthority is considered "complex" and getAuthority() must return null. An example of a "complex" GrantedAuthority would be an implementation that stores a list of operations and authority thresholds that apply to different customer account numbers. Representing this complex GrantedAuthority as a String would be quite complex, and as a result the getAuthority() method should return null. This will indicate to any AccessDecisionManager that it will need to specifically support the GrantedAuthority implementation in order to understand its contents. Spring Security includes one concrete GrantedAuthority implementation, GrantedAuthorityImpl. This allows any user-specified String to be converted into a GrantedAuthority. All AuthenticationProviders included with the security architecture use GrantedAuthorityImpl to populate the Authentication object.
Pre-Invocation Handling As we'll see in the Technical Overview chapter, Spring Security provides interceptors which control access to secure objects such as method invocations or web requests. A pre-invocation decision on whether the invocation is allowed to proceed is made by the AccessDecisionManager.
The AccessDecisionManager The AccessDecisionManager is called by the AbstractSecurityInterceptor and is responsible for making final access control decisions. The AccessDecisionManager interface contains three methods: void decide(Authentication authentication, Object secureObject, ConfigAttributeDefinition config) throws AccessDeniedException; boolean supports(ConfigAttribute attribute); boolean supports(Class clazz); As can be seen from the first method, the AccessDecisionManager is passed via method parameters all information that is likely to be of value in assessing an authorization decision. In particular, passing the secure Object enables those arguments contained in the actual secure object invocation to be inspected. For example, let's assume the secure object was a MethodInvocation. It would be easy to query the MethodInvocation for any Customer argument, and then implement some sort of security logic in the AccessDecisionManager to ensure the principal is permitted to operate on that customer. Implementations are expected to throw an AccessDeniedException if access is denied. The supports(ConfigAttribute) method is called by the AbstractSecurityInterceptor at startup time to determine if the AccessDecisionManager can process the passed ConfigAttribute. The supports(Class) method is called by a security interceptor implementation to ensure the configured AccessDecisionManager supports the type of secure object that the security interceptor will present.
Voting-Based AccessDecisionManager Implementations Whilst users can implement their own AccessDecisionManager to control all aspects of authorization, Spring Security includes several AccessDecisionManager implementations that are based on voting. illustrates the relevant classes.
Voting Decision Manager
Using this approach, a series of AccessDecisionVoter implementations are polled on an authorization decision. The AccessDecisionManager then decides whether or not to throw an AccessDeniedException based on its assessment of the votes. The AccessDecisionVoter interface has three methods: int vote(Authentication authentication, Object object, ConfigAttributeDefinition config); boolean supports(ConfigAttribute attribute); boolean supports(Class clazz); Concrete implementations return an int, with possible values being reflected in the AccessDecisionVoter static fields ACCESS_ABSTAIN, ACCESS_DENIED and ACCESS_GRANTED. A voting implementation will return ACCESS_ABSTAIN if it has no opinion on an authorization decision. If it does have an opinion, it must return either ACCESS_DENIED or ACCESS_GRANTED. There are three concrete AccessDecisionManagers provided with Spring Security that tally the votes. The ConsensusBased implementation will grant or deny access based on the consensus of non-abstain votes. Properties are provided to control behavior in the event of an equality of votes or if all votes are abstain. The AffirmativeBased implementation will grant access if one or more ACCESS_GRANTED votes were received (i.e. a deny vote will be ignored, provided there was at least one grant vote). Like the ConsensusBased implementation, there is a parameter that controls the behavior if all voters abstain. The UnanimousBased provider expects unanimous ACCESS_GRANTED votes in order to grant access, ignoring abstains. It will deny access if there is any ACCESS_DENIED vote. Like the other implementations, there is a parameter that controls the behaviour if all voters abstain. It is possible to implement a custom AccessDecisionManager that tallies votes differently. For example, votes from a particular AccessDecisionVoter might receive additional weighting, whilst a deny vote from a particular voter may have a veto effect.
<classname>RoleVoter</classname> The most commonly used AccessDecisionVoter provided with Spring Security is the simple RoleVoter, which treats configuration attributes as simple role names and votes to grant access if the user has been assigned that role. It will vote if any ConfigAttribute begins with the prefix ROLE_. It will vote to grant access if there is a GrantedAuthority which returns a String representation (via the getAuthority() method) exactly equal to one or more ConfigAttributes starting with ROLE_. If there is no exact match of any ConfigAttribute starting with ROLE_, the RoleVoter will vote to deny access. If no ConfigAttribute begins with ROLE_, the voter will abstain. RoleVoter is case sensitive on comparisons as well as the ROLE_ prefix.
Custom Voters It is also possible to implement a custom AccessDecisionVoter. Several examples are provided in Spring Security unit tests, including ContactSecurityVoter and DenyVoter. The ContactSecurityVoter abstains from voting decisions where a CONTACT_OWNED_BY_CURRENT_USER ConfigAttribute is not found. If voting, it queries the MethodInvocation to extract the owner of the Contact object that is subject of the method call. It votes to grant access if the Contact owner matches the principal presented in the Authentication object. It could have just as easily compared the Contact owner with some GrantedAuthority the Authentication object presented. All of this is achieved with relatively few lines of code and demonstrates the flexibility of the authorization model.
After Invocation Handling Whilst the AccessDecisionManager is called by the AbstractSecurityInterceptor before proceeding with the secure object invocation, some applications need a way of modifying the object actually returned by the secure object invocation. Whilst you could easily implement your own AOP concern to achieve this, Spring Security provides a convenient hook that has several concrete implementations that integrate with its ACL capabilities. illustrates Spring Security's AfterInvocationManager and its concrete implementations.
After Invocation Implementation
Like many other parts of Spring Security, AfterInvocationManager has a single concrete implementation, AfterInvocationProviderManager, which polls a list of AfterInvocationProviders. Each AfterInvocationProvider is allowed to modify the return object or throw an AccessDeniedException. Indeed multiple providers can modify the object, as the result of the previous provider is passed to the next in the list. Let's now consider our ACL-aware implementations of AfterInvocationProvider. Please be aware that if you're using AfterInvocationManager, you will still need configuration attributes that allow the MethodSecurityInterceptor's AccessDecisionManager to allow an operation. If you're using the typical Spring Security included AccessDecisionManager implementations, having no configuration attributes defined for a particular secure method invocation will cause each AccessDecisionVoter to abstain from voting. In turn, if the AccessDecisionManager property "allowIfAllAbstainDecisions" is false, an AccessDeniedException will be thrown. You may avoid this potential issue by either (i) setting "allowIfAllAbstainDecisions" to true (although this is generally not recommended) or (ii) simply ensure that there is at least one configuration attribute that an AccessDecisionVoter will vote to grant access for. This latter (recommended) approach is usually achieved through a ROLE_USER or ROLE_AUTHENTICATED configuration attribute
ACL-Aware AfterInvocationProviders PLEASE NOTE: Acegi Security 1.0.3 contains a preview of a new ACL module. The new ACL module is a significant rewrite of the existing ACL module. The new module can be found under the org.springframework.security.acls package, with the old ACL module under org.springframework.security.acl. We encourage users to consider testing with the new ACL module and build applications with it. The old ACL module should be considered deprecated and may be removed from a future release. The following information relates to the new ACL package, and is thus recommended. A common services layer method we've all written at one stage or another looks like this: public Contact getById(Integer id); Quite often, only principals with permission to read the Contact should be allowed to obtain it. In this situation the AccessDecisionManager approach provided by the AbstractSecurityInterceptor will not suffice. This is because the identity of the Contact is all that is available before the secure object is invoked. The AclAfterInvocationProvider delivers a solution, and is configured as follows: ]]> In the above example, the Contact will be retrieved and passed to the AclEntryAfterInvocationProvider. The provider will thrown an AccessDeniedException if one of the listed requirePermissions is not held by the Authentication. The AclEntryAfterInvocationProvider queries the AclService to determine the ACL that applies for this domain object to this Authentication. Similar to the AclEntryAfterInvocationProvider is AclEntryAfterInvocationCollectionFilteringProvider. It is designed to remove Collection or array elements for which a principal does not have access. It never thrown an AccessDeniedException - simply silently removes the offending elements. The provider is configured as follows: ]]> As you can imagine, the returned Object must be a Collection or array for this provider to operate. It will remove any element if the AclManager indicates the Authentication does not hold one of the listed requirePermissions. The Contacts sample application demonstrates these two AfterInvocationProviders.
ACL-Aware AfterInvocationProviders (old ACL module) PLEASE NOTE: Acegi Security 1.0.3 contains a preview of a new ACL module. The new ACL module is a significant rewrite of the existing ACL module. The new module can be found under the org.springframework.security.acls package, with the old ACL module under org.springframework.security.acl. We encourage users to consider testing with the new ACL module and build applications with it. The old ACL module should be considered deprecated and may be removed from a future release. A common services layer method we've all written at one stage or another looks like this: public Contact getById(Integer id); Quite often, only principals with permission to read the Contact should be allowed to obtain it. In this situation the AccessDecisionManager approach provided by the AbstractSecurityInterceptor will not suffice. This is because the identity of the Contact is all that is available before the secure object is invoked. The BasicAclAfterInvocationProvider delivers a solution, and is configured as follows: ]]> In the above example, the Contact will be retrieved and passed to the BasicAclEntryAfterInvocationProvider. The provider will thrown an AccessDeniedException if one of the listed requirePermissions is not held by the Authentication. The BasicAclEntryAfterInvocationProvider queries the AclManager to determine the ACL that applies for this domain object to this Authentication. Similar to the BasicAclEntryAfterInvocationProvider is BasicAclEntryAfterInvocationCollectionFilteringProvider. It is designed to remove Collection or array elements for which a principal does not have access. It never thrown an AccessDeniedException - simply silently removes the offending elements. The provider is configured as follows: ]]> As you can imagine, the returned Object must be a Collection or array for this provider to operate. It will remove any element if the AclManager indicates the Authentication does not hold one of the listed requirePermissions. The Contacts sample application demonstrates these two AfterInvocationProviders.
Authorization Tag Libraries AuthorizeTag is used to include content if the current principal holds certain GrantedAuthoritys. The following JSP fragment illustrates how to use the AuthorizeTag: ">Del ]]> This tag would cause the tag's body to be output if the principal has been granted ROLE_SUPERVISOR. The security:authorize tag declares the following attributes: ifAllGranted: All the listed roles must be granted for the tag to output its body. ifAnyGranted: Any of the listed roles must be granted for the tag to output its body. ifNotGranted: None of the listed roles must be granted for the tag to output its body. You'll note that in each attribute you can list multiple roles. Simply separate the roles using a comma. The authorize tag ignores whitespace in attributes. The tag library logically ANDs all of it's parameters together. This means that if you combine two or more attributes, all attributes must be true for the tag to output it's body. Don't add an ifAllGranted="ROLE_SUPERVISOR", followed by an ifNotGranted="ROLE_SUPERVISOR", or you'll be surprised to never see the tag's body. By requiring all attributes to return true, the authorize tag allows you to create more complex authorization scenarios. For example, you could declare an ifAllGranted="ROLE_SUPERVISOR" and an ifNotGranted="ROLE_NEWBIE_SUPERVISOR" in the same tag, in order to prevent new supervisors from seeing the tag body. However it would no doubt be simpler to use ifAllGranted="ROLE_EXPERIENCED_SUPERVISOR" rather than inserting NOT conditions into your design. One last item: the tag verifies the authorizations in a specific order: first ifNotGranted, then ifAllGranted, and finally, if AnyGranted. AccessControlListTag is used to include content if the current principal has an ACL to the indicated domain object. The following JSP fragment illustrates how to use the AccessControlListTag: ">Del ]]> This tag would cause the tag's body to be output if the principal holds either permission 16 or permission 1 for the "contact" domain object. The numbers are actually integers that are used with BasePermission bit masking. Please refer to the ACL section of this reference guide to understand more about the ACL capabilities of Spring Security. AclTag is part of the old ACL module and should be considered deprecated. For the sake of historical reference, works exactly the samae as AccessControlListTag.
spring-security-2.0.7.RELEASE/docs/reference/springsecurity.xml0000644000000000000000000002475011766764657021377 0ustar Spring Security Reference Documentation Ben Alex, Luke Taylor 2.0.x Preface Spring Security provides a comprehensive security solution for J2EE-based enterprise software applications. As you will discover as you venture through this reference guide, we have tried to provide you a useful and highly configurable security system. Security is an ever-moving target, and it's important to pursue a comprehensive, system-wide approach. In security circles we encourage you to adopt "layers of security", so that each layer tries to be as secure as possible in its own right, with successive layers providing additional security. The "tighter" the security of each layer, the more robust and safe your application will be. At the bottom level you'll need to deal with issues such as transport security and system identification, in order to mitigate man-in-the-middle attacks. Next you'll generally utilise firewalls, perhaps with VPNs or IP security to ensure only authorised systems can attempt to connect. In corporate environments you may deploy a DMZ to separate public-facing servers from backend database and application servers. Your operating system will also play a critical part, addressing issues such as running processes as non-privileged users and maximising file system security. An operating system will usually also be configured with its own firewall. Hopefully somewhere along the way you'll be trying to prevent denial of service and brute force attacks against the system. An intrusion detection system will also be especially useful for monitoring and responding to attacks, with such systems able to take protective action such as blocking offending TCP/IP addresses in real-time. Moving to the higher layers, your Java Virtual Machine will hopefully be configured to minimize the permissions granted to different Java types, and then your application will add its own problem domain-specific security configuration. Spring Security makes this latter area - application security - much easier. Of course, you will need to properly address all security layers mentioned above, together with managerial factors that encompass every layer. A non-exhaustive list of such managerial factors would include security bulletin monitoring, patching, personnel vetting, audits, change control, engineering management systems, data backup, disaster recovery, performance benchmarking, load monitoring, centralised logging, incident response procedures etc. With Spring Security being focused on helping you with the enterprise application security layer, you will find that there are as many different requirements as there are business problem domains. A banking application has different needs from an ecommerce application. An ecommerce application has different needs from a corporate sales force automation tool. These custom requirements make application security interesting, challenging and rewarding. Please read , in its entirety to begin with. This will introduce you to the framework and the namespace-based configuration system with which you can get up and running quite quickly. To get more of an understanding of an in-depth understaning of how Spring Security works, and some of the classes you might need to use, you should then read . The remaining parts of this guide are structured in a more traditional reference style, designed to be read on an as-required basis. We'd also recommend that you read up as much as possible on application security issues in general. Spring Security is not a panacea which will solve all security issues. It is important that the application is designed with security in mind from the start. Attempting to retrofit it is not a good idea. In particular, if you are building a web application, you should be aware of the many potential vulnerabilities such as cross-site scripting, request-forgery and session-hijacking which you should be taking into account from the start. The OWASP web site (http://www.owasp.org/) maintains a top ten list of web application vulnerabilities as well as a lot of useful reference information. We hope that you find this reference guide useful, and we welcome your feedback and suggestions. Finally, welcome to the Spring Security community. Getting Started The later parts of this guide provide an in-depth discussion of the framework architecture and implementation classes, an understanding of which is important if you need to do any serious customization. In this part, we'll introduce Spring Security 2.0, give a brief overview of the project's history and take a slightly gentler look at how to get started using the framework. In particular, we'll look at namespace configuration which provides a much simpler way of securing your application compared to the traditional Spring bean approach where you had to wire up all the implementation classes individually. We'll also take a look at the sample applications that are available. It's worth trying to run these and experimenting with them a bit even before you read the later sections - you can dip back into them as your understanding of the framework increases. Overall Architecture Like most software, Spring Security has certain central interfaces, classes and conceptual abstractions that are commonly used throughout the framework. In this part of the reference guide we will introduce Spring Security, before examining these central elements that are necessary to successfully planning and executing a Spring Security integration. Authentication We've already introduced Spring Security's authentication architecture in the Technical Overview chapter. In this part of the reference guide we will examine individual authentication mechanisms and their corresponding AuthenticationProviders. We'll also look at how to configure authentication more generally, including if you have several authentication approaches that need to be chained together. With some exceptions, we will be discussing the full details of Spring Security bean configuration rather than the shorthand namespace syntax. You should review the introduction to using namespace configuration and the options it provides to see if they will meet your needs. As you come to use the framework more, and need to customize the internal behaviour, you will probably want to understand more about how the individual services are implemented, which classes to look at extending and so on. This part is more targeted at providing this kind of information. We'd recommend that you supplement the content by browsing the Javadoc and the source itself Links to both Javadoc APIs and browsable source cross-reference are available from the project web site.. Authorization The advanced authorization capabilities within Spring Security represent one of the most compelling reasons for its popularity. Irrespective of how you choose to authenticate - whether using a Spring Security-provided mechanism and provider, or integrating with a container or other non-Spring Security authentication authority - you will find the authorization services can be used within your application in a consistent and simple way. In this part we'll explore the different AbstractSecurityInterceptor implementations, which were introduced in Part I. We then move on to explore how to fine-tune authorization through use of domain access control lists. spring-security-2.0.7.RELEASE/docs/reference/domain-acls.xml0000644000000000000000000005427111766764657020475 0ustar Domain Object Security
Overview PLEASE NOTE: Before release 2.0.0, Spring Security was known as Acegi Security. An ACL module was provided with the old Acegi Security releases under the org.[acegisecurity/springsecurity].acl package. This old package is now deprecated and will be removed in a future release of Spring Security. This chapter covers the new ACL module, which is officially recommended from Spring Security 2.0.0 and above, and can be found under the org.springframework.security.acls package. Complex applications often will find the need to define access permissions not simply at a web request or method invocation level. Instead, security decisions need to comprise both who (Authentication), where (MethodInvocation) and what (SomeDomainObject). In other words, authorization decisions also need to consider the actual domain object instance subject of a method invocation. Imagine you're designing an application for a pet clinic. There will be two main groups of users of your Spring-based application: staff of the pet clinic, as well as the pet clinic's customers. The staff will have access to all of the data, whilst your customers will only be able to see their own customer records. To make it a little more interesting, your customers can allow other users to see their customer records, such as their "puppy preschool" mentor or president of their local "Pony Club". Using Spring Security as the foundation, you have several approaches that can be used: Write your business methods to enforce the security. You could consult a collection within the Customer domain object instance to determine which users have access. By using the SecurityContextHolder.getContext().getAuthentication(), you'll be able to access the Authentication object. Write an AccessDecisionVoter to enforce the security from the GrantedAuthority[]s stored in the Authentication object. This would mean your AuthenticationManager would need to populate the Authentication with custom GrantedAuthority[]s representing each of the Customer domain object instances the principal has access to. Write an AccessDecisionVoter to enforce the security and open the target Customer domain object directly. This would mean your voter needs access to a DAO that allows it to retrieve the Customer object. It would then access the Customer object's collection of approved users and make the appropriate decision. Each one of these approaches is perfectly legitimate. However, the first couples your authorization checking to your business code. The main problems with this include the enhanced difficulty of unit testing and the fact it would be more difficult to reuse the Customer authorization logic elsewhere. Obtaining the GrantedAuthority[]s from the Authentication object is also fine, but will not scale to large numbers of Customers. If a user might be able to access 5,000 Customers (unlikely in this case, but imagine if it were a popular vet for a large Pony Club!) the amount of memory consumed and time required to construct the Authentication object would be undesirable. The final method, opening the Customer directly from external code, is probably the best of the three. It achieves separation of concerns, and doesn't misuse memory or CPU cycles, but it is still inefficient in that both the AccessDecisionVoter and the eventual business method itself will perform a call to the DAO responsible for retrieving the Customer object. Two accesses per method invocation is clearly undesirable. In addition, with every approach listed you'll need to write your own access control list (ACL) persistence and business logic from scratch. Fortunately, there is another alternative, which we'll talk about below.
Key Concepts Spring Security's ACL services are shipped in the spring-security-acl-xxx.jar. You will need to add this JAR to your classpath to use Spring Security's domain object instance security capabilities. Spring Security's domain object instance security capabilities centre on the concept of an access control list (ACL). Every domain object instance in your system has its own ACL, and the ACL records details of who can and can't work with that domain object. With this in mind, Spring Security delivers three main ACL-related capabilities to your application: A way of efficiently retrieving ACL entries for all of your domain objects (and modifying those ACLs) A way of ensuring a given principal is permitted to work with your objects, before methods are called A way of ensuring a given principal is permitted to work with your objects (or something they return), after methods are called As indicated by the first bullet point, one of the main capabilities of the Spring Security ACL module is providing a high-performance way of retrieving ACLs. This ACL repository capability is extremely important, because every domain object instance in your system might have several access control entries, and each ACL might inherit from other ACLs in a tree-like structure (this is supported out-of-the-box by Spring Security, and is very commonly used). Spring Security's ACL capability has been carefully designed to provide high performance retrieval of ACLs, together with pluggable caching, deadlock-minimizing database updates, independence from ORM frameworks (we use JDBC directly), proper encapsulation, and transparent database updating. Given databases are central to the operation of the ACL module, let's explore the four main tables used by default in the implementation. The tables are presented below in order of size in a typical Spring Security ACL deployment, with the table with the most rows listed last: ACL_SID allows us to uniquely identify any principal or authority in the system ("SID" stands for "security identity"). The only columns are the ID, a textual representation of the SID, and a flag to indicate whether the textual representation refers to a prncipal name or a GrantedAuthority. Thus, there is a single row for each unique principal or GrantedAuthority. When used in the context of receiving a permission, a SID is generally called a "recipient". ACL_CLASS allows us to uniquely identify any domain object class in the system. The only columns are the ID and the Java class name. Thus, there is a single row for each unique Class we wish to store ACL permissions for. ACL_OBJECT_IDENTITY stores information for each unique domain object instance in the system. Columns include the ID, a foreign key to the ACL_CLASS table, a unique identifier so we know which ACL_CLASS instance we're providing information for, the parent, a foreign key to the ACL_SID table to represent the owner of the domain object instance, and whether we allow ACL entries to inherit from any parent ACL. We have a single row for every domain object instance we're storing ACL permissions for. Finally, ACL_ENTRY stores the individual permissions assigned to each recipient. Columns include a foreign key to the ACL_OBJECT_IDENTITY, the recipient (ie a foreign key to ACL_SID), whether we'll be auditing or not, and the integer bit mask that represents the actual permission being granted or denied. We have a single row for every recipient that receives a permission to work with a domain object. As mentioned in the last paragraph, the ACL system uses integer bit masking. Don't worry, you need not be aware of the finer points of bit shifting to use the ACL system, but suffice to say that we have 32 bits we can switch on or off. Each of these bits represents a permission, and by default the permissions are read (bit 0), write (bit 1), create (bit 2), delete (bit 3) and administer (bit 4). It's easy to implement your own Permission instance if you wish to use other permissions, and the remainder of the ACL framework will operate without knowledge of your extensions. It is important to understand that the number of domain objects in your system has absolutely no bearing on the fact we've chosen to use integer bit masking. Whilst you have 32 bits available for permissions, you could have billions of domain object instances (which will mean billions of rows in ACL_OBJECT_IDENTITY and quite probably ACL_ENTRY). We make this point because we've found sometimes people mistakenly believe they need a bit for each potential domain object, which is not the case. Now that we've provided a basic overview of what the ACL system does, and what it looks like at a table structure, let's explore the key interfaces. The key interfaces are: Acl: Every domain object has one and only one Acl object, which internally holds the AccessControlEntrys as well as knows the owner of the Acl. An Acl does not refer directly to the domain object, but instead to an ObjectIdentity. The Acl is stored in the ACL_OBJECT_IDENTITY table. AccessControlEntry: An Acl holds multiple AccessControlEntrys, which are often abbreviated as ACEs in the framework. Each ACE refers to a specific tuple of Permission, Sid and Acl. An ACE can also be granting or non-granting and contain audit settings. The ACE is stored in the ACL_ENTRY table. Permission: A permission represents a particular immutable bit mask, and offers convenience functions for bit masking and outputting information. The basic permissions presented above (bits 0 through 4) are contained in the BasePermission class. Sid: The ACL module needs to refer to principals and GrantedAuthority[]s. A level of indirection is provided by the Sid interface, which is an abbreviation of "security identity". Common classes include PrincipalSid (to represent the principal inside an Authentication object) and GrantedAuthoritySid. The security identity information is stored in the ACL_SID table. ObjectIdentity: Each domain object is represented internally within the ACL module by an ObjectIdentity. The default implementation is called ObjectIdentityImpl. AclService: Retrieves the Acl applicable for a given ObjectIdentity. In the included implementation (JdbcAclService), retrieval operations are delegated to a LookupStrategy. The LookupStrategy provides a highly optimized strategy for retrieving ACL information, using batched retrievals (BasicLookupStrategy) and supporting custom implementations that leverage materialized views, hierarchical queries and similar performance-centric, non-ANSI SQL capabilities. MutableAclService: Allows a modified Acl to be presented for persistence. It is not essential to use this interface if you do not wish. Please note that our out-of-the-box AclService and related database classes all use ANSI SQL. This should therefore work with all major databases. At the time of writing, the system had been successfully tested using Hypersonic SQL, PostgreSQL, Microsoft SQL Server and Oracle. Two samples ship with Spring Security that demonstrate the ACL module. The first is the Contacts Sample, and the other is the Document Management System (DMS) Sample. We suggest taking a look over these for examples.
Getting Started To get starting using Spring Security's ACL capability, you will need to store your ACL information somewhere. This necessitates the instantiation of a DataSource using Spring. The DataSource is then injected into a JdbcMutableAclService and BasicLookupStrategy instance. The latter provides high-performance ACL retrieval capabilities, and the former provides mutator capabilities. Refer to one of the samples that ship with Spring Security for an example configuration. You'll also need to populate the database with the four ACL-specific tables listed in the last section (refer to the ACL samples for the appropriate SQL statements). Once you've created the required schema and instantiated JdbcMutableAclService, you'll next need to ensure your domain model supports interoperability with the Spring Security ACL package. Hopefully ObjectIdentityImpl will prove sufficient, as it provides a large number of ways in which it can be used. Most people will have domain objects that contain a public Serializable getId() method. If the return type is long, or compatible with long (eg an int), you will find you need not give further consideration to ObjectIdentity issues. Many parts of the ACL module rely on long identifiers. If you're not using long (or an int, byte etc), there is a very good chance you'll need to reimplement a number of classes. We do not intend to support non-long identifiers in Spring Security's ACL module, as longs are already compatible with all database sequences, the most common identifier data type, and are of sufficient length to accommodate all common usage scenarios. The following fragment of code shows how to create an Acl, or modify an existing Acl:// Prepare the information we'd like in our access control entry (ACE) ObjectIdentity oi = new ObjectIdentityImpl(Foo.class, new Long(44)); Sid sid = new PrincipalSid("Samantha"); Permission p = BasePermission.ADMINISTRATION; // Create or update the relevant ACL MutableAcl acl = null; try { acl = (MutableAcl) aclService.readAclById(oi); } catch (NotFoundException nfe) { acl = aclService.createAcl(oi); } // Now grant some permissions via an access control entry (ACE) acl.insertAce(acl.getEntries().length, p, sid, true); aclService.updateAcl(acl); In the example above, we're retrieving the ACL associated with the "Foo" domain object with identifier number 44. We're then adding an ACE so that a principal named "Samantha" can "administer" the object. The code fragment is relatively self-explanatory, except the insertAce method. The first argument to the insertAce method is determining at what position in the Acl the new entry will be inserted. In the example above, we're just putting the new ACE at the end of the existing ACEs. The final argument is a boolean indicating whether the ACE is granting or denying. Most of the time it will be granting (true), but if it is denying (false), the permissions are effectively being blocked. Spring Security does not provide any special integration to automatically create, update or delete ACLs as part of your DAO or repository operations. Instead, you will need to write code like shown above for your individual domain objects. It's worth considering using AOP on your services layer to automatically integrate the ACL information with your services layer operations. We've found this quite an effective approach in the past. Once you've used the above techniques to store some ACL information in the database, the next step is to actually use the ACL information as part of authorization decision logic. You have a number of choices here. You could write your own AccessDecisionVoter or AfterInvocationProvider that respectively fires before or after a method invocation. Such classes would use AclService to retrieve the relevant ACL and then call Acl.isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode) to decide whether permission is granted or denied. Alternately, you could use our AclEntryVoter, AclEntryAfterInvocationProvider or AclEntryAfterInvocationCollectionFilteringProvider classes. All of these classes provide a declarative-based approach to evaluating ACL information at runtime, freeing you from needing to write any code. Please refer to the sample applications to learn how to use these classes.
spring-security-2.0.7.RELEASE/docs/reference/jaas-auth-provider.xml0000644000000000000000000001670311766764657022011 0ustar Java Authentication and Authorization Service (JAAS) Provider
Overview Spring Security provides a package able to delegate authentication requests to the Java Authentication and Authorization Service (JAAS). This package is discussed in detail below. Central to JAAS operation are login configuration files. To learn more about JAAS login configuration files, consult the JAAS reference documentation available from Sun Microsystems. We expect you to have a basic understanding of JAAS and its login configuration file syntax in order to understand this section.
Configuration The JaasAuthenticationProvider attempts to authenticate a user’s principal and credentials through JAAS. Let’s assume we have a JAAS login configuration file, /WEB-INF/login.conf, with the following contents: JAASTest { sample.SampleLoginModule required; }; Like all Spring Security beans, the JaasAuthenticationProvider is configured via the application context. The following definitions would correspond to the above JAAS login configuration file: ]]> The CallbackHandlers and AuthorityGranters are discussed below.
JAAS CallbackHandler Most JAAS LoginModules require a callback of some sort. These callbacks are usually used to obtain the username and password from the user. In a Spring Security deployment, Spring Security is responsible for this user interaction (via the authentication mechanism). Thus, by the time the authentication request is delegated through to JAAS, Spring Security's authentication mechanism will already have fully-populated an Authentication object containing all the information required by the JAAS LoginModule. Therefore, the JAAS package for Spring Security provides two default callback handlers, JaasNameCallbackHandler and JaasPasswordCallbackHandler. Each of these callback handlers implement JaasAuthenticationCallbackHandler. In most cases these callback handlers can simply be used without understanding the internal mechanics. For those needing full control over the callback behavior, internally JaasAutheticationProvider wraps these JaasAuthenticationCallbackHandlers with an InternalCallbackHandler. The InternalCallbackHandler is the class that actually implements JAAS’ normal CallbackHandler interface. Any time that the JAAS LoginModule is used, it is passed a list of application context configured InternalCallbackHandlers. If the LoginModule requests a callback against the InternalCallbackHandlers, the callback is in-turn passed to the JaasAuthenticationCallbackHandlers being wrapped.
JAAS AuthorityGranter JAAS works with principals. Even "roles" are represented as principals in JAAS. Spring Security, on the other hand, works with Authentication objects. Each Authentication object contains a single principal, and multiple GrantedAuthority[]s. To facilitate mapping between these different concepts, Spring Security's JAAS package includes an AuthorityGranter interface. An AuthorityGranter is responsible for inspecting a JAAS principal and returning a String. The JaasAuthenticationProvider then creates a JaasGrantedAuthority (which implements Spring Security’s GrantedAuthority interface) containing both the AuthorityGranter-returned String and the JAAS principal that the AuthorityGranter was passed. The JaasAuthenticationProvider obtains the JAAS principals by firstly successfully authenticating the user’s credentials using the JAAS LoginModule, and then accessing the LoginContext it returns. A call to LoginContext.getSubject().getPrincipals() is made, with each resulting principal passed to each AuthorityGranter defined against the JaasAuthenticationProvider.setAuthorityGranters(List) property. Spring Security does not include any production AuthorityGranters given that every JAAS principal has an implementation-specific meaning. However, there is a TestAuthorityGranter in the unit tests that demonstrates a simple AuthorityGranter implementation.
spring-security-2.0.7.RELEASE/docs/reference/dao-auth-provider.xml0000644000000000000000000001622111766764657021631 0ustar DAO Authentication Provider
Overview Spring Security includes a production-quality AuthenticationProvider implementation called DaoAuthenticationProvider. This authentication provider is compatible with all of the authentication mechanisms that generate a UsernamePasswordAuthenticationToken, and is probably the most commonly used provider in the framework. Like most of the other authentication providers, the DaoAuthenticationProvider leverages a UserDetailsService in order to lookup the username, password and GrantedAuthority[]s. Unlike most of the other authentication providers that leverage UserDetailsService, this authentication provider actually requires the password to be presented, and the provider will actually evaluate the validity or otherwise of the password presented in an authentication request object.
Configuration Aside from adding DaoAuthenticationProvider to your ProviderManager list (as discussed at the start of this part of the reference guide), and ensuring a suitable authentication mechanism is configured to present a UsernamePasswordAuthenticationToken, the configuration of the provider itself is rather simple: ]]> The PasswordEncoder and SaltSource are optional. A PasswordEncoder provides encoding and decoding of passwords presented in the UserDetails object that is returned from the configured UserDetailsService. A SaltSource enables the passwords to be populated with a "salt", which enhances the security of the passwords in the authentication repository. PasswordEncoder implementations are provided with Spring Security covering MD5, SHA and cleartext encodings. Two SaltSource implementations are also provided: SystemWideSaltSource which encodes all passwords with the same salt, and ReflectionSaltSource, which inspects a given property of the returned UserDetails object to obtain the salt. Please refer to the JavaDocs for further details on these optional features. In addition to the properties above, the DaoAuthenticationProvider supports optional caching of UserDetails objects. The UserCache interface enables the DaoAuthenticationProvider to place a UserDetails object into the cache, and retrieve it from the cache upon subsequent authentication attempts for the same username. By default the DaoAuthenticationProvider uses the NullUserCache, which performs no caching. A usable caching implementation is also provided, EhCacheBasedUserCache, which is configured as follows: ]]> All Spring Security EH-CACHE implementations (including EhCacheBasedUserCache) require an EH-CACHE Cache object. The Cache object can be obtained from wherever you like, although we recommend you use Spring's factory classes as shown in the above configuration. If using Spring's factory classes, please refer to the Spring documentation for further details on how to optimise the cache storage location, memory usage, eviction policies, timeouts etc. In the majority of cases, where your application is a stateful web application, you don't need to use a cache as the user's authentication information will be stored in the HttpSession. A design decision was made not to support account locking in the DaoAuthenticationProvider, as doing so would have increased the complexity of the UserDetailsService interface. For instance, a method would be required to increase the count of unsuccessful authentication attempts. Such functionality could be easily provided by leveraging the application event publishing features discussed below. DaoAuthenticationProvider returns an Authentication object which in turn has its principal property set. The principal will be either a String (which is essentially the username) or a UserDetails object (which was looked up from the UserDetailsService). By default the UserDetails is returned, as this enables applications to add extra properties potentially of use in applications, such as the user's full name, email address etc. If using container adapters, or if your applications were written to operate with Strings (as was the case for releases prior to Spring Security 0.6), you should set the DaoAuthenticationProvider.forcePrincipalAsString property to true in your application context
spring-security-2.0.7.RELEASE/docs/reference/index-classes.xsl0000644000000000000000000000120211766764657021040 0ustar spring-security-2.0.7.RELEASE/docs/reference/appendix-namespace.xml0000644000000000000000000011150111766764657022036 0ustar The Security Namespace This appendix provides a reference to the elements available in the security namespace and information on the underlying beans they create (a knowledge of the individual classes and how they work together is assumed - you can find more information in the project Javadoc and elsewhere in this document). If you haven't used the namespace before, please read the introductory chapter on namespace configuration, as this is intended as a supplement to the information there. Using a good quality XML editor while editing a configuration based on the schema is recommended as this will provide contextual information on which elements and attributes are available as well as comments explaining their purpose.
Web Application Security - the <literal><http></literal> Element The <http> element encapsulates the security configuration for the web layer of your application. It creates a FilterChainProxy bean named "springSecurityFilterChain" which maintains the stack of security filters which make up the web security configuration See the introductory chapter for how to set up the mapping from your web.xml. Some core filters are always created and others will be added to the stack depending on the attributes child elements which are present. The positions of the standard filters are fixed (see the filter order table in the namespace introduction), removing a common source of errors with previous versions of the framework when users had to configure the filter chain explicitly in theFilterChainProxy bean. You can, of course, still do this if you need full control of the configuration. All filters which require a reference to the AuthenticationManager will be automatically injected with the internal instance created by the namespace configuration (see the introductory chapter for more on the AuthenticationManager). The <http> namespace block always creates an HttpSessionContextIntegrationFilter, an ExceptionTranslationFilter and a FilterSecurityInterceptor. These are fixed and cannot be replaced with alternatives.
<literal><http></literal> Attributes The attributes on the <http> element control some of the properties on the core filters.
<literal>servlet-api-provision</literal> Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by adding a SecurityContextHolderAwareRequestFilter bean to the stack. Defaults to "true".
<literal>path-type</literal> Controls whether URL patterns are interpreted as ant paths (the default) or regular expressions. In practice this sets a particular UrlMatcher instance on the FilterChainProxy.
<literal>lowercase-comparisons</literal> Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true"
<literal>session-fixation-protection</literal> Indicates whether an existing session should be invalidated when a user authenticates and a new session started. If set to "none" no change will be made. "newSession" will create a new empty session. "migrateSession" will create a new session and copy the session attributes to the new session. Defaults to "migrateSession". If enabled this will add a SessionFixationProtectionFilter to the stack. The session fixation protection options on namespace-created instances of AbstractProcessingFilter will also be set appropriately.
<literal>realm</literal> Sets the realm name used for basic authentication (if enabled). Corresponds to the realmName proerty on BasicProcessingFilterEntryPoint.
<literal>entry-point-ref</literal> Normally the AuthenticationEntryPoint used will be set depending on which authentication mechanisms have been configured. This attribute allows this behaviour to be overridden by defining a customized AuthenticationEntryPoint bean which will start the authentication process.
<literal>access-decision-manager-ref</literal> Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests. By default an AffirmativeBased implementation is used for with a RoleVoter and an AuthenticatedVoter.
<literal>access-denied-page</literal> Allows the access denied page to be set (the user will be redirected here if an AccessDeniedException is raised). Corresponds to the errorPage property set on the AccessDeniedHandlerImpl which is used by the ExceptionTranslationFilter.
<literal>once-per-request</literal> Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true".
<literal>create-session</literal> Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". Other options are "always" and "never". The setting of this attribute affect the allowSessionCreation and forceEagerSessionCreation properties of HttpSessionContextIntegrationFilter. allowSessionCreation will always be true unless this attribute is set to "never". forceEagerSessionCreation is "false" unless it is set to "always". So the default configuration allows session creation but does not force it. The exception is if concurrent session control is enabled, when forceEagerSessionCreation will be set to true, regardless of what the setting is here. Using "never" would then cause an exception during the initialization of HttpSessionContextIntegrationFilter.
The <literal><intercept-url></literal> Element This element is used to define the set of URL patterns that the application is interested in and to configure how they should be handled. It is used to construct the FilterInvocationDefinitionSource used by the FilterSecurityInterceptor and to exclude particular patterns from the filter chain entirely (by setting the attribute filters="none"). It is also responsible for configuring a ChannelProcessingFilter if particular URLs need to be accessed by HTTPS, for example.
<literal>pattern</literal> The pattern which defines the URL path. The content will depend on the path-type attribute from the containing http element, so will default to ant path syntax.
<literal>method</literal> The HTTP Method which will be used in combination with the pattern to match an incoming request. If omitted, any method will match.
<literal>access</literal> Lists the access attributes which will be stored in the FilterInvocationDefinitionSource for the defined URL pattern/method combination. This should be a comma-separated list of the attributes (such as role names).
<literal>requires-channel</literal> Can be "http" or "https" depending on whether a particular URL pattern should be accessed over HTTP or HTTPS respectively. Alternatively the value "any" can be used when there is no preference. If this attribute is present on any <intercept-url> element, then a ChannelProcessingFilter will be added to the filter stack and its additional dependencies added to the application context. See the chapter on channel security for an example configuration using traditional beans. If a <port-mappings> configuration is added, this will be used to by the SecureChannelProcessor and InsecureChannelProcessor beans to determine the ports used for redirecting to HTTP/HTTPS.
The <literal><port-mappings></literal> Element By default, an instance of PortMapperImpl will be added to the configuration for use in redirecting to secure and insecure URLs. This element can optionally be used to override the default mappings which that class defines. Each child <port-mapping> element defines a pair of HTTP:HTTPS ports. The default mappings are 80:443 and 8080:8443. An example of overriding these can be found in the namespace introduction.
The <literal><form-login></literal> Element Used to add an AuthenticationProcessingFilter to the filter stack and an AuthenticationProcessingFilterEntryPoint to the application context to provide authentication on demand. This will always take precedence over other namespace-created entry points. If no attributes are supplied, a login page will be generated automatically at the URL "/spring-security-login" This feature is really just provided for convenience and is not intended for production (where a view technology will have been chosen and can be used to render a customized login page). The class DefaultLoginPageGeneratingFilter is responsible for rendering the login page and will provide login forms for both normal form login and/or OpenID if required. The behaviour can be customized using the following attributes.
<literal>login-page</literal> The URL that should be used to render the login page. Maps to the loginFormUrl property of the AuthenticationProcessingFilterEntryPoint. Defaults to "/spring-security-login".
<literal>login-processing-url</literal> Maps to the filterProcessesUrl property of AuthenticationProcessingFilter. The default value is "/j_spring_security_check".
<literal>default-target-url</literal> Maps to the defaultTargetUrl property of AuthenticationProcessingFilter. If not set, the default value is "/" (the application root). A user will be taken to this URL after logging in, provided they were not asked to login while attempting to access a secured resource, when they will be taken to the originally requested URL.
<literal>always-use-default-target</literal> If set to "true", the user will always start at the value given by default-target-url, regardless of how they arrived at the login page. Maps to the alwaysUseDefaultTargetUrl property of AuthenticationProcessingFilter. Default value is "false".
<literal>authentication-failure-url</literal> Maps to the authenticationFailureUrl property of AuthenticationProcessingFilter. Defines the URL the browser will be redirected to on login failure. Defaults to "/spring_security_login?login_error", which will be automatically handled by the automatic login page generator, re-rendering the login page with an error message.
The <literal><http-basic></literal> Element Adds a BasicProcessingFilter and BasicProcessingFilterEntryPoint to the configuration. The latter will only be used as the configuration entry point if form-based login is not enabled.
The <literal><remember-me></literal> Element Adds the RememberMeProcessingFilter to the stack. This in turn will be configured with either a TokenBasedRememberMeServices, a PersistentTokenBasedRememberMeServices or a user-specified bean implementing RememberMeServices depending on the attribute settings.
<literal>data-source-ref</literal> If this is set, PersistentTokenBasedRememberMeServices will be used and configured with a JdbcTokenRepositoryImpl instance.
<literal>token-repository-ref</literal> Configures a PersistentTokenBasedRememberMeServices but allows the use of a custom PersistentTokenRepository bean.
<literal>services-ref</literal> Allows complete control of the RememberMeServices implementation that will be used by the filter. The value should be the Id of a bean in the application context which implements this interface.
<literal>token-repository-ref</literal> Configures a PersistentTokenBasedRememberMeServices but allows the use of a custom PersistentTokenRepository bean.
The <literal>key</literal> Attribute Maps to the "key" property of AbstractRememberMeServices. Should be set to a unique value to ensure that remember-me cookies are only valid within the one application This doesn't affect the use of PersistentTokenBasedRememberMeServices, where the tokens are stored on the server side..
<literal>token-validity-seconds</literal> Maps to the tokenValiditySeconds property of AbstractRememberMeServices. Specifies the period in seconds for which the remember-me cookie should be valid. By default it will be valid for 14 days.
<literal>user-service-ref</literal> The remember-me services implementations require access to a UserDetailsService, so there has to be one defined in the application context. If there is only one, it will be selected and used automatically by the namespace configuration. If there are multiple instances, you can specify a bean Id explicitly using this attribute.
The <literal><concurrent-session-control></literal> Element Adds support for concurrent session control, allowing limits to be placed on the number of active sessions a user can have. A ConcurrentSessionFilter will be created, along with a ConcurrentSessionControllerImpl and an instance of SessionRegistry (a SessionRegistryImpl instance unless the user wishes to use a custom bean). The controller is registered with the namespace's AuthenticationManager (ProviderManager). Other namespace-created beans which require a reference to the SessionRegistry will automatically have it injected. Note that the forceEagerSessionCreation of HttpSessionContextIntegrationFilter will be set to true if concurrent session control is in use.
The <literal>max-sessions</literal> attribute Maps to the maximumSessions property of ConcurrentSessionControllerImpl.
The <literal>expired-url</literal> attribute The URL a user will be redirected to if they attempt to use a session which has been "expired" by the concurrent session controller because the user has exceeded the number of allowed sessions and has logged in again elsewhere. Should be set unless exception-if-maximum-exceeded is set. If no value is supplied, an expiry message will just be written directly back to the response.
The <literal>exception-if-maximum-exceeded</literal> attribute If set to "true" a ConcurrentLoginException should be raised when a user attempts to exceed the maximum allowed number of sessions. The default behaviour is to expire the original session.
The <literal>session-registry-alias</literal> and <literal>session-registry-ref</literal> attributes The user can supply their own SessionRegistry implementation using the session-registry-ref attribute. The other concurrent session control beans will be wired up to use it. It can also be useful to have a reference to the internal session registry for use in your own beans or an admin interface. You can expose the interal bean using the session-registry-alias attribute, giving it a name that you can use elsewhere in your configuration.
The <literal><anonymous></literal> Element Adds an AnonymousProcessingFilter to the stack and an AnonymousAuthenticationProvider. Required if you are using the IS_AUTHENTICATED_ANONYMOUSLY attribute.
The <literal><x509></literal> Element Adds support for X.509 authentication. An X509PreAuthenticatedProcessingFilter will be added to the stack and a PreAuthenticatedProcessingFilterEntryPoint bean will be created. The latter will only be used if no other authentication mechanisms are in use (it's only functionality is to return an HTTP 403 error code). A PreAuthenticatedAuthenticationProvider will also be created which delegates the loading of user authorities to a UserDetailsService.
The <literal>subject-principal-regex</literal> attribute Defines a regular expression which will be used to extract the username from the certificate (for use with the UserDetailsService).
The <literal>user-service-ref</literal> attribute Allows a specific UserDetailsService to be used with X.509 in the case where multiple instances are configured. If not set, an attempt will be made to locate a suitable instance automatically and use that.
The <literal><openid-login></literal> Element Similar to <form-login> and has the same attributes. The default value for login-processing-url is "/j_spring_openid_security_check". An OpenIDAuthenticationProcessingFilter and OpenIDAuthenticationProvider will be registered. The latter requires a reference to a UserDetailsService. Again, this can be specified by Id, using the user-service-ref attribute, or will be located automatically in the application context.
The <literal><logout></literal> Element Adds a LogoutFilter to the filter stack. This is configured with a SecurityContextLogoutHandler.
The <literal>logout-url</literal> attribute The URL which will cause a logout (i.e. which will be processed by the filter). Defaults to "/j_spring_security_logout".
The <literal>logout-success-url</literal> attribute The destination URL which the user will be taken to after logging out. Defaults to "/".
The <literal>invalidate-session</literal> attribute Maps to the invalidateHttpSession of the SecurityContextLogoutHandler. Defaults to "true", so the session will be invalidated on logout.
Authentication Services If you are using the namespace, an AuthenticationManager is automatically registered and will be used by all the namespace-created beans which need to reference it. The bean is an instance of Spring Security's ProviderManager class, which needs to be configured with a list of one or more AuthenticationProvider instances. These can either be created using syntax elements provided by the namespace, or they can be standard bean definitions, marked for addition to the list using the custom-authentication-provider element.
The <authentication-provider> Element This element is basically a shorthand syntax for configuring a DaoAuthenticationProvider. DaoAuthenticationProvider loads user information from a UserDetailsService and compares the username/password combination with the values supplied at login. The UserDetailsService instance can be defined either by using an available namespace element (jdbc-user-service or by using the user-service-ref attribute to point to a bean defined elsewhere in the application context). You can find examples of these variations in the namespace introduction.
Using <literal><custom-authentication-provider></literal> to register an AuthenticationProvider If you have written your own AuthenticationProvider implementation (or want to configure one of Spring Security's own implementations as a traditional bean for some reason, then you can use the following syntax to add it to the internal ProviderManager's list: ]]>
The <literal><authentication-manager></literal> Element Since the AuthenticationManager will be automatically registered in the application context, this element is entirely optional. It allows you to define an alias name for the internal instance for use in your own configuration and also to supply a link to a ConcurrentSessionController if you are configuring concurrent session control yourself rather than through the namespace (a rare requirement). Its use is described in the namespace introduction.
Method Security
The <literal><global-method-security></literal> Element This element is the primary means of adding support for securing methods on Spring Security beans. Methods can be secured by the use of annotations (defined at the interface or class level) or by defining a set of pointcuts as child elements, using AspectJ syntax. Method security uses the same AccessDecisionManager configuration as web security, but this can be overridden as explained above , using the same attribute.
The <literal><secured-annotations></literal> and <literal><jsr250-annotations></literal> Attributes Setting these to "true" will enable support for Spring Security's own @Secured annotations and JSR-250 annotations, respectively. They are both disabled by default. Use of JSR-250 annotations also adds a Jsr250Voter to the AccessDecisionManager, so you need to make sure you do this if you are using a custom implementation and want to use these annotations.
Securing Methods using <literal><protect-pointcut></literal> Rather than defining security attributes on an individual method or class basis using the @Secured annotation, you can define cross-cutting security constraints across whole sets of methods and interfaces in your service layer using the <protect-pointcut> element. This has two attributes: expression - the pointcut expression access - the security attributes which apply You can find an example in the namespace introduction.
LDAP Namespace Options LDAP is covered in some details in its own chapter. We will expand on that here with some explanation of how the namespace options map to Spring beans. The LDAP implementation uses Spring LDAP extensively, so some familiarity with that project's API may be useful.
Defining the LDAP Server using the <literal><ldap-server></literal> Element This element sets up a Spring LDAP ContextSource for use by the other LDAP beans, defining the location of the LDAP server and other information (such as a username and password, if it doesn't allow anonymous access) for connecting to it. It can also be used to create an embedded server for testing. Details of the syntax for both options are covered in the LDAP chapter. The actual ContextSource implementation is DefaultSpringSecurityContextSource which extends Spring LDAP's LdapContextSource class. The manager-dn and manager-password attributes map to the latter's userDn and password properties respectively. If you only have one server defined in your application context, the other LDAP namespace-defined beans will use it automatically. Otherwise, you can give the element an "id" attribute and refer to it from other namespace beans using the server-ref attribute. This is actually the bean Id of the ContextSource instance, if you want to use it in other traditional Spring beans.
The <literal><ldap-provider></literal> Element This element is shorthand for the creation of an LdapAuthenticationProvider instance. By default this will be configured with a BindAuthenticator instance and a DefaultAuthoritiesPopulator.
The <literal>user-dn-pattern</literal> Attribute If your users are at a fixed location in the directory (i.e. you can work out the DN directly from the username without doing a directory search), you can use this attribute to map directly to the DN. It maps directly to the userDnPatterns property of AbstractLdapAuthenticator.
The <literal>user-search-base</literal> and <literal>user-search-filter</literal> Attributes If you need to perform a search to locate the user in the directory, then you can set these attributes to control the search. The BindAuthenticator will be configured with a FilterBasedLdapUserSearch and the attribute values map directly to the first two arguments of that bean's constructor. If these attributes aren't set and no user-dn-pattern has been supplied as an alternative, then the default search values of user-search-filter="(uid={0})" and user-search-base="" will be used.
<literal>group-search-filter</literal>, <literal>group-search-base</literal>, <literal>group-role-attribute</literal> and <literal>role-prefix</literal> Attributes The value of group-search-base is mapped to the groupSearchBase constructor argument of DefaultAuthoritiesPopulator and defaults to "ou=groups". The default filter value is "(uniqueMember={0})", which assumes that the entry is of type "groupOfUniqueNames". group-role-attribute maps to the groupRoleAttribute attribute and defaults to "cn". Similarly role-prefix maps to rolePrefix and defaults to "ROLE_".
The <literal><password-compare></literal> Element This is used as child element to <ldap-provider> and switches the authentication strategy from BindAuthenticator to PasswordComparisonAuthenticator. This can optionally be supplied with a hash attribute or with a child <password-encoder> element to hash the password before submitting it to the directory for comparison.
The <literal><ldap-user-service></literal> Element This element configures an LDAP UserDetailsService. The class used is LdapUserDetailsService which is a combination of a FilterBasedLdapUserSearch and a DefaultAuthoritiesPopulator. The attributes it supports have the same usage as in <ldap-provider>.
spring-security-2.0.7.RELEASE/docs/reference/cas-auth-provider.xml0000644000000000000000000005545611766764657021651 0ustar CAS Authentication
Overview JA-SIG produces an enterprise-wide single sign on system known as CAS. Unlike other initiatives, JA-SIG's Central Authentication Service is open source, widely used, simple to understand, platform independent, and supports proxy capabilities. Spring Security fully supports CAS, and provides an easy migration path from single-application deployments of Spring Security through to multiple-application deployments secured by an enterprise-wide CAS server. You can learn more about CAS at http://www.ja-sig.org/products/cas/. You will also need to visit this site to download the CAS Server files.
How CAS Works Whilst the CAS web site contains documents that detail the architecture of CAS, we present the general overview again here within the context of Spring Security. Spring Security 2.0 supports CAS 3. At the time of writing, the CAS server was at version 3.2. Somewhere in your enterprise you will need to setup a CAS server. The CAS server is simply a standard WAR file, so there isn't anything difficult about setting up your server. Inside the WAR file you will customise the login and other single sign on pages displayed to users. When deploying a CAS 3.2 server, you will also need to specify an AuthenticationHandler in the deployerConfigContext.xml included with CAS. The AuthenticationHandler has a simple method that returns a boolean as to whether a given set of Credentials is valid. Your AuthenticationHandler implementation will need to link into some type of backend authentication repository, such as an LDAP server or database. CAS itself includes numerous AuthenticationHandlers out of the box to assist with this. When you download and deploy the server war file, it is set up to successfully authenticate users who enter a password matching their username, which is useful for testing. Apart from the CAS server itself, the other key players are of course the secure web applications deployed throughout your enterprise. These web applications are known as "services". There are two types of services: standard services and proxy services. A proxy service is able to request resources from other services on behalf of the user. This will be explained more fully later.
Configuration of CAS Client The web application side of CAS is made easy due to Spring Security. It is assumed you already know the basics of using Spring Security, so these are not covered again below. We'll assume a namespace based configuration is being used and add in the CAS beans as required. You will need to add a ServiceProperties bean to your application context. This represents your service: ]]> The service must equal a URL that will be monitored by the CasProcessingFilter. The sendRenew defaults to false, but should be set to true if your application is particularly sensitive. What this parameter does is tell the CAS login service that a single sign on login is unacceptable. Instead, the user will need to re-enter their username and password in order to gain access to the service. The following beans should be configured to commence the CAS authentication process: ]]> The CasProcessingFilterEntryPoint should be selected to drive authentication using entry-point-ref. The CasProcessingFilter has very similar properties to the AuthenticationProcessingFilter (used for form-based logins). Each property is self-explanatory. Note that we've also used the namespace syntax for setting up an alias to the authentication mnager, since the CasProcessingFilter needs a reference to it. For CAS to operate, the ExceptionTranslationFilter must have its authenticationEntryPoint property set to the CasProcessingFilterEntryPoint bean. The CasProcessingFilterEntryPoint must refer to the ServiceProperties bean (discussed above), which provides the URL to the enterprise's CAS login server. This is where the user's browser will be redirected. Next you need to add a CasAuthenticationProvider and its collaborators: ... ]]> The CasAuthenticationProvider uses a UserDetailsService instance to load the authorities for a user, once they have been authentiated by CAS. We've shown a simple in-memory setup here. The beans are all reasonable self-explanatory if you refer back to the "How CAS Works" section.
spring-security-2.0.7.RELEASE/docs/reference/technical-overview.xml0000644000000000000000000007344111766764657022104 0ustar Technical Overview
Runtime Environment Spring Security is written to execute within a standard Java 1.4 Runtime Environment. It also supports Java 5.0, although the Java types which are specific to this release are packaged in a separate package with the suffix "tiger" in their JAR filename. As Spring Security aims to operate in a self-contained manner, there is no need to place any special configuration files into your Java Runtime Environment. In particular, there is no need to configure a special Java Authentication and Authorization Service (JAAS) policy file or place Spring Security into common classpath locations. Similarly, if you are using an EJB Container or Servlet Container there is no need to put any special configuration files anywhere, nor include Spring Security in a server classloader. This design offers maximum deployment time flexibility, as you can simply copy your target artifact (be it a JAR, WAR or EAR) from one system to another and it will immediately work.
Shared Components Let's explore some of the most important shared components in Spring Security. Components are considered "shared" if they are central to the framework and the framework cannot operate without them. These Java types represent the building blocks of the remaining system, so it's important to understand that they're there, even if you don't need to directly interact with them.
SecurityContextHolder, SecurityContext and Authentication Objects The most fundamental object is SecurityContextHolder. This is where we store details of the present security context of the application, which includes details of the principal currently using the application. By default the SecurityContextHolder uses a ThreadLocal to store these details, which means that the security context is always available to methods in the same thread of execution, even if the security context is not explicitly passed around as an argument to those methods. Using a ThreadLocal in this way is quite safe if care is taken to clear the thread after the present principal's request is processed. Of course, Spring Security takes care of this for you automatically so there is no need to worry about it. Some applications aren't entirely suitable for using a ThreadLocal, because of the specific way they work with threads. For example, a Swing client might want all threads in a Java Virtual Machine to use the same security context. For this situation you would use the SecurityContextHolder.MODE_GLOBAL. Other applications might want to have threads spawned by the secure thread also assume the same security identity. This is achieved by using SecurityContextHolder.MODE_INHERITABLETHREADLOCAL. You can change the mode from the default SecurityContextHolder.MODE_THREADLOCAL in two ways. The first is to set a system property. Alternatively, call a static method on SecurityContextHolder. Most applications won't need to change from the default, but if you do, take a look at the JavaDocs for SecurityContextHolder to learn more. Inside the SecurityContextHolder we store details of the principal currently interacting with the application. Spring Security uses an Authentication object to represent this information. Whilst you won't normally need to create an Authentication object yourself, it is fairly common for users to query the Authentication object. You can use the following code block - from anywhere in your application - to obtain the name of the authenticated user, for example: Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (obj instanceof UserDetails) { String username = ((UserDetails)obj).getUsername(); } else { String username = obj.toString(); } The above code introduces a number of interesting relationships and key objects. First, you will notice that there is an intermediate object between SecurityContextHolder and Authentication. The SecurityContextHolder.getContext() method is actually returning a SecurityContext.
The UserDetailsService Another item to note from the above code fragment is that you can obtain a principal from the Authentication object. The principal is just an Object. Most of the time this can be cast into a UserDetails object. UserDetails is a central interface in Spring Security. It represents a principal, but in an extensible and application-specific way. Think of UserDetails as the adapter between your own user database and what Spring Security needs inside the SecurityContextHolder. Being a representation of something from your own user database, quite often you will cast the UserDetails to the original object that your application provided, so you can call business-specific methods (like getEmail(), getEmployeeNumber() and so on). By now you're probably wondering, so when do I provide a UserDetails object? How do I do that? I thought you said this thing was declarative and I didn't need to write any Java code - what gives? The short answer is that there is a special interface called UserDetailsService. The only method on this interface accepts a String-based username argument and returns a UserDetails. Most authentication providers that ship with Spring Security delegate to a UserDetailsService as part of the authentication process. The UserDetailsService is used to build the Authentication object that is stored in the SecurityContextHolder. The good news is that we provide a number of UserDetailsService implementations, including one that uses an in-memory map and another that uses JDBC. Most users tend to write their own, though, with such implementations often simply sitting on top of an existing Data Access Object (DAO) that represents their employees, customers, or other users of the enterprise application. Remember the advantage that whatever your UserDetailsService returns can always be obtained from the SecurityContextHolder, as per the above code fragment.
GrantedAuthority Besides the principal, another important method provided by Authentication is getAuthorities(). This method provides an array of GrantedAuthority objects. A GrantedAuthority is, not surprisingly, an authority that is granted to the principal. Such authorities are usually "roles", such as ROLE_ADMINISTRATOR or ROLE_HR_SUPERVISOR. These roles are later on configured for web authorization, method authorization and domain object authorization. Other parts of Spring Security are capable of interpreting these authorities, and expect them to be present. GrantedAuthority objects are usually loaded by the UserDetailsService. Usually the GrantedAuthority objects are application-wide permissions. They are not specific to a given domain object. Thus, you wouldn't likely have a GrantedAuthority to represent a permission to Employee object number 54, because if there are thousands of such authorities you would quickly run out of memory (or, at the very least, cause the application to take a long time to authenticate a user). Of course, Spring Security is expressly designed to handle this common requirement, but you'd instead use the project's domain object security capabilities for this purpose. Last but not least, sometimes you will need to store the SecurityContext between HTTP requests. Other times the principal will re-authenticate on every request, although most of the time it will be stored. The HttpSessionContextIntegrationFilter is responsible for storing a SecurityContext between HTTP requests. As suggested by the name of the class, the HttpSession is used to store this information. You should never interact directly with the HttpSession for security purposes. There is simply no justification for doing so - always use the SecurityContextHolder instead.
Summary Just to recap, the major building blocks of Spring Security are: SecurityContextHolder, to provide any type access to the SecurityContext. SecurityContext, to hold the Authentication and possibly request-specific security information. HttpSessionContextIntegrationFilter, to store the SecurityContext in the HttpSession between web requests. Authentication, to represent the principal in a Spring Security-specific manner. GrantedAuthority, to reflect the application-wide permissions granted to a principal. UserDetails, to provide the necessary information to build an Authentication object from your application's DAOs. UserDetailsService, to create a UserDetails when passed in a String-based username (or certificate ID or alike). Now that you've gained an understanding of these repeatedly-used components, let's take a closer look at the process of authentication.
Authentication As mentioned in the beginning of this reference guide, Spring Security can participate in many different authentication environments. Whilst we recommend people use Spring Security for authentication and not integrate with existing Container Managed Authentication, it is nevertheless supported - as is integrating with your own proprietary authentication system. Let's first explore authentication from the perspective of Spring Security managing web security entirely on its own, which is illustrative of the most complex and most common situation. Consider a typical web application's authentication process: You visit the home page, and click on a link. A request goes to the server, and the server decides that you've asked for a protected resource. As you're not presently authenticated, the server sends back a response indicating that you must authenticate. The response will either be an HTTP response code, or a redirect to a particular web page. Depending on the authentication mechanism, your browser will either redirect to the specific web page so that you can fill out the form, or the browser will somehow retrieve your identity (eg a BASIC authentication dialogue box, a cookie, a X509 certificate etc). The browser will send back a response to the server. This will either be an HTTP POST containing the contents of the form that you filled out, or an HTTP header containing your authentication details. Next the server will decide whether or not the presented credentials are valid. If they're valid, the next step will happen. If they're invalid, usually your browser will be asked to try again (so you return to step two above). The original request that you made to cause the authentication process will be retried. Hopefully you've authenticated with sufficient granted authorities to access the protected resource. If you have sufficient access, the request will be successful. Otherwise, you'll receive back an HTTP error code 403, which means "forbidden". Spring Security has distinct classes responsible for most of the steps described above. The main participants (in the order that they are used) are the ExceptionTranslationFilter, an AuthenticationEntryPoint, an authentication mechanism, and an AuthenticationProvider.
ExceptionTranslationFilter ExceptionTranslationFilter is a Spring Security filter that has responsibility for detecting any Spring Security exceptions that are thrown. Such exceptions will generally be thrown by an AbstractSecurityInterceptor, which is the main provider of authorization services. We will discuss AbstractSecurityInterceptor in the next section, but for now we just need to know that it produces Java exceptions and knows nothing about HTTP or how to go about authenticating a principal. Instead the ExceptionTranslationFilter offers this service, with specific responsibility for either returning error code 403 (if the principal has been authenticated and therefore simply lacks sufficient access - as per step seven above), or launching an AuthenticationEntryPoint (if the principal has not been authenticated and therefore we need to go commence step three).
AuthenticationEntryPoint The AuthenticationEntryPoint is responsible for step three in the above list. As you can imagine, each web application will have a default authentication strategy (well, this can be configured like nearly everything else in Spring Security, but let's keep it simple for now). Each major authentication system will have its own AuthenticationEntryPoint implementation, which takes actions such as described in step three. After your browser decides to submit your authentication credentials (either as an HTTP form post or HTTP header) there needs to be something on the server that "collects" these authentication details. By now we're at step six in the above list. In Spring Security we have a special name for the function of collecting authentication details from a user agent (usually a web browser), and that name is "authentication mechanism". After the authentication details are collected from the user agent, an "Authentication request" object is built and then presented to an AuthenticationProvider.
AuthenticationProvider The last player in the Spring Security authentication process is an AuthenticationProvider. Quite simply, it is responsible for taking an Authentication request object and deciding whether or not it is valid. The provider will either throw an exception or return a fully populated Authentication object. Remember our good friends, UserDetails and UserDetailsService? If not, head back to the previous section and refresh your memory. Most AuthenticationProviders will ask a UserDetailsService to provide a UserDetails object. As mentioned earlier, most application will provide their own UserDetailsService, although some will be able to use the JDBC or in-memory implementation that ships with Spring Security. The resultant UserDetails object - and particularly the GrantedAuthority[]s contained within the UserDetails object - will be used when building the fully populated Authentication object. After the authentication mechanism receives back the fully-populated Authentication object, it will deem the request valid, put the Authentication into the SecurityContextHolder, and cause the original request to be retried (step seven above). If, on the other hand, the AuthenticationProvider rejected the request, the authentication mechanism will ask the user agent to retry (step two above).
Setting the SecurityContextHolder Contents Directly Whilst this describes the typical authentication workflow, the good news is that Spring Security doesn't mind how you put an Authentication inside the SecurityContextHolder. The only critical requirement is that the SecurityContextHolder contains an Authentication that represents a principal before the AbstractSecurityInterceptor needs to authorize a request. You can (and many users do) write their own filters or MVC controllers to provide interoperability with authentication systems that are not based on Spring Security. For example, you might be using Container-Managed Authentication which makes the current user available from a ThreadLocal or JNDI location. Or you might work for a company that has a legacy proprietary authentication system, which is a corporate "standard" over which you have little control. In such situations it's quite easy to get Spring Security to work, and still provide authorization capabilities. All you need to do is write a filter (or equivalent) that reads the third-party user information from a location, build a Spring Security-specific Authentication object, and put it onto the SecurityContextHolder. It's quite easy to do this, and it is a fully-supported integration approach.
Secure Objects Spring Security uses the term "secure object" to refer to any object that can have security (such as an authorization decision) applied to it. The most common examples are method invocations and web requests.
Security and AOP Advice If you're familiar with AOP, you'd be aware there are different types of advice available: before, after, throws and around. An around advice is very useful, because an advisor can elect whether or not to proceed with a method invocation, whether or not to modify the response, and whether or not to throw an exception. Spring Security provides an around advice for method invocations as well as web requests. We achieve an around advice for method invocations using Spring's standard AOP support and we achieve an around advice for web requests using a standard Filter. For those not familiar with AOP, the key point to understand is that Spring Security can help you protect method invocations as well as web requests. Most people are interested in securing method invocations on their services layer. This is because the services layer is where most business logic resides in current-generation J2EE applications (for clarification, the author disapproves of this design and instead advocates properly encapsulated domain objects together with the DTO, assembly, facade and transparent persistence patterns, but as use of anemic domain objects is the present mainstream approach, we'll talk about it here). If you just need to secure method invocations to the services layer, Spring's standard AOP (otherwise known as AOP Alliance) will be adequate. If you need to secure domain objects directly, you will likely find that AspectJ is worth considering. You can elect to perform method authorization using AspectJ or Spring AOP, or you can elect to perform web request authorization using filters. You can use zero, one, two or three of these approaches together. The mainstream usage is to perform some web request authorization, coupled with some Spring AOP method invocation authorization on the services layer.
AbstractSecurityInterceptor Each secure object type supported by Spring Security has its own class, which is a subclass of AbstractSecurityInterceptor. Importantly, by the time the AbstractSecurityInterceptor is called, the SecurityContextHolder will contain a valid Authentication if the principal has been authenticated. AbstractSecurityInterceptor provides a consistent workflow for handling secure object requests, typically: Look up the "configuration attributes" associated with the present request Submitting the secure object, current Authentication and configuration attributes to the AccessDecisionManager for an authorization decision Optionally change the Authentication under which the invocation takes place Allow the secure object to proceed (assuming access was granted) Call the AfterInvocationManager if configured, once the invocation has returned.
What are Configuration Attributes? A "configuration attribute" can be thought of as a String that has special meaning to the classes used by AbstractSecurityInterceptor. They may be simple role names or have more complex meaning, depending on the how sophisticated the AccessDecisionManager implementation is. The AbstractSecurityInterceptor is configured with an ObjectDefinitionSource which it uses to look up the attributes for a secure object. Usually this configuration will be hidden from the user. Configuration attributes will be entered as annotations on secured methods, or as access attributes on secured URLs (using the namespace <intercept-url> syntax).
RunAsManager Assuming AccessDecisionManager decides to allow the request, the AbstractSecurityInterceptor will normally just proceed with the request. Having said that, on rare occasions users may want to replace the Authentication inside the SecurityContext with a different Authentication, which is handled by the AccessDecisionManager calling a RunAsManager. This might be useful in reasonably unusual situations, such as if a services layer method needs to call a remote system and present a different identity. Because Spring Security automatically propagates security identity from one server to another (assuming you're using a properly-configured RMI or HttpInvoker remoting protocol client), this may be useful.
AfterInvocationManager Following the secure object proceeding and then returning - which may mean a method invocation completing or a filter chain proceeding - the AbstractSecurityInterceptor gets one final chance to handle the invocation. At this stage the AbstractSecurityInterceptor is interested in possibly modifying the return object. We might want this to happen because an authorization decision couldn't be made "on the way in" to a secure object invocation. Being highly pluggable, AbstractSecurityInterceptor will pass control to an AfterInvocationManager to actually modify the object if needed. This class can even entirely replace the object, or throw an exception, or not change it in any way. AbstractSecurityInterceptor and its related objects are shown in .
The key "secure object" model
Extending the Secure Object Model Only developers contemplating an entirely new way of intercepting and authorizing requests would need to use secure objects directly. For example, it would be possible to build a new secure object to secure calls to a messaging system. Anything that requires security and also provides a way of intercepting a call (like the AOP around advice semantics) is capable of being made into a secure object. Having said that, most Spring applications will simply use the three currently supported secure object types (AOP Alliance MethodInvocation, AspectJ JoinPoint and web request FilterInvocation) with complete transparency.
spring-security-2.0.7.RELEASE/docs/reference/x509-auth-provider.xml0000644000000000000000000001431511766764657021575 0ustar X.509 Authentication
Overview The most common use of X.509 certificate authentication is in verifying the identity of a server when using SSL, most commonly when using HTTPS from a browser. The browser will automatically check that the certificate presented by a server has been issued (ie digitally signed) by one of a list of trusted certificate authorities which it maintains. You can also use SSL with mutual authentication; the server will then request a valid certificate from the client as part of the SSL handshake. The server will authenticate the client by checking that it's certificate is signed by an acceptable authority. If a valid certificate has been provided, it can be obtained through the servlet API in an application. Spring Security X.509 module extracts the certificate using a filter and passes it to the configured X.509 authentication provider to allow any additional application-specific checks to be applied. It also maps the certificate to an application user and loads that user's set of granted authorities for use with the standard Spring Security infrastructure. You should be familiar with using certificates and setting up client authentication for your servlet container before attempting to use it with Spring Security. Most of the work is in creating and installing suitable certificates and keys. For example, if you're using Tomcat then read the instructions here http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html. It's important that you get this working before trying it out with Spring Security
Adding X.509 Authentication to Your Web Application Enabling X.509 client authentication is very straightforward. Just add the <x509/> element to your http security namespace configuration. <http> ... <x509 subject-principal-regex="CN=(.*?)," user-service-ref="userService"/> ... </http> The element has two optional attributes: subject-principal-regex. The regular expression used to extract a username from the certificate's subject name. The default value is shown above. This is the username which will be passed to the UserDetailsService to load the authorities for the user. user-service-ref. This is the bean Id of the UserDetailsService to be used with X.509. It isn't needed if there is only one defined in your application context. The subject-principal-regex should contain a single group. For example the default expression "CN=(.*?)," matches the common name field. So if the subject name in the certificate is "CN=Jimi Hendrix, OU=...", this will give a user name of "Jimi Hendrix". The matches are case insensitive. So "emailAddress=(.?)," will match "EMAILADDRESS=jimi@hendrix.org,CN=..." giving a user name "jimi@hendrix.org". If the client presents a certificate and a valid username is successfully extracted, then there should be a valid Authentication object in the security context. If no certificate is found, or no corresponding user could be found then the security context will remain empty. This means that you can easily use X.509 authentication with other options such as a form-based login.
Setting up SSL in Tomcat There are some pre-generated certificates in the samples/certificate directory in the Spring Security project. You can use these to enable SSL for testing if you don't want to generate your own. The file server.jks contains the server certificate, private key and the issuing certificate authority certificate. There are also some client certificate files for the users from the sample applications. You can install these in your browser to enable SSL client authentication. To run tomcat with SSL support, drop the server.jks file into the tomcat conf directory and add the following connector to the server.xml file <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true" clientAuth="true" sslProtocol="TLS" keystoreFile="${catalina.home}/conf/server.jks" keystoreType="JKS" keystorePass="password" truststoreFile="${catalina.home}/conf/server.jks" truststoreType="JKS" truststorePass="password" /> clientAuth can also be set to want if you still want SSL connections to succeed even if the client doesn't provide a certificate. Clients which don't present a certificate won't be able to access any objects secured by Spring Security unless you use a non-X.509 authentication mechanism, such as form authentication.
spring-security-2.0.7.RELEASE/docs/reference/class-index-html.xsl0000644000000000000000000000207111766764657021457 0ustar http://static.springframework.org/spring-security/site/xref/ http://static.springframework.org/spring-security/site/reference/html/

Class and Interface Index

Source

spring-security-2.0.7.RELEASE/docs/reference/container-adapters.xml0000644000000000000000000004271711766764657022073 0ustar Container Adapter Authentication
Overview Very early versions of Spring Security exclusively used Container Adapters for interfacing authentication with end users. Whilst this worked well, it required considerable time to support multiple container versions and the configuration itself was relatively time-consuming for developers. For this reason the HTTP Form Authentication and HTTP Basic Authentication approaches were developed, and are today recommended for almost all applications. Container Adapters enable Spring Security to integrate directly with the containers used to host end user applications. This integration means that applications can continue to leverage the authentication and authorization capabilities built into containers (such as isUserInRole() and form-based or basic authentication), whilst benefiting from the enhanced security interception capabilities provided by Spring Security (it should be noted that Spring Security also offers ContextHolderAwareRequestWrapper to deliver isUserInRole() and similar Servlet Specification compatibility methods). The integration between a container and Spring Security is achieved through an adapter. The adapter provides a container-compatible user authentication provider, and needs to return a container-compatible user object. The adapter is instantiated by the container and is defined in a container-specific configuration file. The adapter then loads a Spring application context which defines the normal authentication manager settings, such as the authentication providers that can be used to authenticate the request. The application context is usually named acegisecurity.xml and is placed in a container-specific location. Spring Security currently supports Jetty, Catalina (Tomcat), JBoss and Resin. Additional container adapters can easily be written
Adapter Authentication Provider As is always the case, the container adapter generated Authentication object still needs to be authenticated by an AuthenticationManager when requested to do so by the AbstractSecurityInterceptor. The AuthenticationManager needs to be certain the adapter-provided Authentication object is valid and was actually authenticated by a trusted adapter. Adapters create Authentication objects which are immutable and implement the AuthByAdapter interface. These objects store the hash of a key that is defined by the adapter. This allows the Authentication object to be validated by the AuthByAdapterProvider. This authentication provider is defined as follows: <bean id="authByAdapterProvider" class="org.springframework.security.adapters.AuthByAdapterProvider"> <property name="key"><value>my_password</value></property> </bean> The key must match the key that is defined in the container-specific configuration file that starts the adapter. The AuthByAdapterProvider automatically accepts as valid any AuthByAdapter implementation that returns the expected hash of the key. To reiterate, this means the adapter will perform the initial authentication using providers such as DaoAuthenticationProvider, returning an AuthByAdapter instance that contains a hash code of the key. Later, when an application calls a security interceptor managed resource, the AuthByAdapter instance in the SecurityContext in the SecurityContextHolder will be tested by the application's AuthByAdapterProvider. There is no requirement for additional authentication providers such as DaoAuthenticationProvider within the application-specific application context, as the only type of Authentication instance that will be presented by the application is from the container adapter. Classloader issues are frequent with containers and the use of container adapters illustrates this further. Each container requires a very specific configuration. The installation instructions are provided below. Once installed, please take the time to try the sample application to ensure your container adapter is properly configured. When using container adapters with the DaoAuthenticationProvider, ensure you set its forcePrincipalAsString property to true.
Jetty The following was tested with Jetty 4.2.18. $JETTY_HOME refers to the root of your Jetty installation. Edit your $JETTY_HOME/etc/jetty.xml file so the <Configure class> section has a new addRealm call: <Call name="addRealm"> <Arg> <New class="org.springframework.security.adapters.jetty.JettySpringSecurityUserRealm"> <Arg>Spring Powered Realm</Arg> <Arg>my_password</Arg> <Arg>etc/acegisecurity.xml</Arg> </New> </Arg> </Call> Copy acegisecurity.xml into $JETTY_HOME/etc. Copy the following files into $JETTY_HOME/ext: aopalliance.jar commons-logging.jar spring.jar acegi-security-jetty-XX.jar commons-codec.jar burlap.jar hessian.jar None of the above JAR files (or acegi-security-XX.jar) should be in your application's WEB-INF/lib. The realm name indicated in your web.xml does matter with Jetty. The web.xml must express the same <realm-name> as your jetty.xml (in the example above, "Spring Powered Realm").
JBoss The following was tested with JBoss 3.2.6. $JBOSS_HOME refers to the root of your JBoss installation. There are two different ways of making spring context available to the Jboss integration classes. The first approach is by editing your $JBOSS_HOME/server/your_config/conf/login-config.xml file so that it contains a new entry under the <Policy> section: <application-policy name = "SpringPoweredRealm"> <authentication> <login-module code = "org.springframework.security.adapters.jboss.JbossSpringSecurityLoginModule" flag = "required"> <module-option name = "appContextLocation">acegisecurity.xml</module-option> <module-option name = "key">my_password</module-option> </login-module> </authentication> </application-policy> Copy acegisecurity.xml into $JBOSS_HOME/server/your_config/conf. In this configuration acegisecurity.xml contains the spring context definition including all the authentication manager beans. You have to bear in mind though, that SecurityContext is created and destroyed on each login request, so the login operation might become costly. Alternatively, the second approach is to use Spring singleton capabilities through org.springframework.beans.factory.access.SingletonBeanFactoryLocator. The required configuration for this approach is: <application-policy name = "SpringPoweredRealm"> <authentication> <login-module code = "org.springframework.security.adapters.jboss.JbossSpringSecurityLoginModule" flag = "required"> <module-option name = "singletonId">springRealm</module-option> <module-option name = "key">my_password</module-option> <module-option name = "authenticationManager">authenticationManager</module-option> </login-module> </authentication> </application-policy> In the above code fragment, authenticationManager is a helper property that defines the expected name of the AuthenticationManager in case you have several defined in the IoC container. The singletonId property references a bean defined in a beanRefFactory.xml file. This file needs to be available from anywhere on the JBoss classpath, including $JBOSS_HOME/server/your_config/conf. The beanRefFactory.xml contains the following declaration: <beans> <bean id="springRealm" singleton="true" lazy-init="true" class="org.springframework.context.support.ClassPathXmlApplicationContext"> <constructor-arg> <list> <value>acegisecurity.xml</value> </list> </constructor-arg> </bean> </beans> Finally, irrespective of the configuration approach you need to copy the following files into $JBOSS_HOME/server/your_config/lib: aopalliance.jar spring.jar acegi-security-jboss-XX.jar commons-codec.jar burlap.jar hessian.jar None of the above JAR files (or acegi-security-XX.jar) should be in your application's WEB-INF/lib. The realm name indicated in your web.xml does not matter with JBoss. However, your web application's WEB-INF/jboss-web.xml must express the same <security-domain> as your login-config.xml. For example, to match the above example, your jboss-web.xml would look like this: <jboss-web> <security-domain>java:/jaas/SpringPoweredRealm</security-domain> </jboss-web> JBoss is a widely-used container adapter (mostly due to the need to support legacy EJBs), so please let us know if you have any difficulties.
Resin The following was tested with Resin 3.0.6. $RESIN_HOME refers to the root of your Resin installation. Resin provides several ways to support the container adapter. In the instructions below we have elected to maximise consistency with other container adapter configurations. This will allow Resin users to simply deploy the sample application and confirm correct configuration. Developers comfortable with Resin are naturally able to use its capabilities to package the JARs with the web application itself, and/or support single sign-on. Copy the following files into $RESIN_HOME/lib: aopalliance.jar commons-logging.jar spring.jar acegi-security-resin-XX.jar commons-codec.jar burlap.jar hessian.jar Unlike the container-wide acegisecurity.xml files used by other container adapters, each Resin web application will contain its own WEB-INF/resin-acegisecurity.xml file. Each web application will also contain a resin-web.xml file which Resin uses to start the container adapter: <web-app> <authenticator> <type>org.springframework.security.adapters.resin.ResinAcegiAuthenticator</type> <init> <app-context-location>WEB-INF/resin-acegisecurity.xml</app-context-location> <key>my_password</key> </init> </authenticator> </web-app> With the basic configuration provided above, none of the JAR files listed (or acegi-security-XX.jar) should be in your application's WEB-INF/lib. The realm name indicated in your web.xml does not matter with Resin, as the relevant authentication class is indicated by the <authenticator> setting
Tomcat The following was tested with Jakarta Tomcat 4.1.30 and 5.0.19. $CATALINA_HOME refers to the root of your Catalina (Tomcat) installation. Edit your $CATALINA_HOME/conf/server.xml file so the <Engine> section contains only one active <Realm> entry. An example realm entry: <Realm className="org.springframework.security.adapters.catalina.CatalinaSpringSecurityUserRealm" appContextLocation="conf/acegisecurity.xml" key="my_password" /> Be sure to remove any other <Realm> entry from your <Engine> section. Copy acegisecurity.xml into $CATALINA_HOME/conf. Copy spring-security-catalina-XX.jar into $CATALINA_HOME/server/lib. Copy the following files into $CATALINA_HOME/common/lib: aopalliance.jar spring.jar commons-codec.jar burlap.jar hessian.jar None of the above JAR files (or spring-security-XX.jar) should be in your application's WEB-INF/lib. The realm name indicated in your web.xml does not matter with Catalina. We have received reports of problems using this Container Adapter with Mac OS X. A work-around is to use a script such as follows: #!/bin/sh export CATALINA_HOME="/Library/Tomcat" export JAVA_HOME="/Library/Java/Home" cd / $CATALINA_HOME/bin/startup.sh Finally, restart Tomcat.
spring-security-2.0.7.RELEASE/docs/reference/ldap-auth-provider.xml0000644000000000000000000006270411766764657022015 0ustar LDAP Authentication
Overview LDAP is often used by organizations as a central repository for user information and as an authentication service. It can also be used to store the role information for application users. There are many different scenarios for how an LDAP server may be configured so Spring Security's LDAP provider is fully configurable. It uses separate strategy interfaces for authentication and role retrieval and provides default implementations which can be configured to handle a wide range of situations. You should be familiar with LDAP before trying to use it with Spring Security. The following link provides a good introduction to the concepts involved and a guide to setting up a directory using the free LDAP server OpenLDAP: http://www.zytrax.com/books/ldap/. Some familiarity with the JNDI APIs used to access LDAP from Java may also be useful. We don't use any third-party LDAP libraries (Mozilla, JLDAP etc.) in the LDAP provider, but extensive use is made of Spring LDAP, so some familiarity with that project may be useful if you plan on adding your own customizations.
Using LDAP with Spring Security LDAP authentication in Spring Security can be roughly divided into the following stages. Obtaining the unique LDAP Distinguished Name, or DN, from the login name. This will often mean performing a search in the directory, unless the exact mapping of usernames to DNs is known in advance. Authenticating the user, either by binding as that user or by performing a remote compare operation of the user's password against the password attribute in the directory entry for the DN. Loading the list of authorities for the user. The exception is when the LDAP directory is just being used to retrieve user information and authenticate against it locally. This may not be possible as directories are often set up with limited read access for attributes such as user passwords. We will look at some configuration scenarios below. For full information on available configuration options, please consult the security namespace schema (information from which should be available in your XML editor).
Configuring an LDAP Server The first thing you need to do is configure the server against which authentication should take place. This is done using the <ldap-server> element from the security namespace. This can be configured to point at an external LDAP server, using the url attribute: ]]>
Using an Embedded Test Server The <ldap-server> element can also be used to create an embedded server, which can be very useful for testing and demonstrations. In this case you use it without the url attribute: ]]> Here we've specified that the root DIT of the directory should be dc=springframework,dc=org, which is the default. Used this way, the namespace parser will create an embedded Apache Directory server and scan the classpath for any LDIF files, which it will attempt to load into the server. You can customize this behaviour using the ldif attribute, which defines an LDIF resource to be loaded: ]]> This makes it a lot easier to get up and running with LDAP, since it can be inconvenient to work all the time with an external server. It also insulates the user from the complex bean configuration needed to wire up an Apache Directory server. Using plain Spring Beans the configuration would be much more cluttered. You must have the necessary Apache Directory dependency jars available for your application to use. These can be obtained from the LDAP sample application.
Using Bind Authentication This is the most common LDAP authentication scenario. ]]> This simple example would obtain the DN for the user by substituting the user login name in the supplied pattern and attempting to bind as that user with the login password. This is OK if all your users are stored under a single node in the directory. If instead you wished to configure an LDAP search filter to locate the user, you could use the following: ]]> If used with the server definition above, this would perform a search under the DN ou=people,dc=springframework,dc=org using the value of the user-search-filter attribute as a filter. Again the user login name is substituted for the parameter in the filter name. If user-search-base isn't supplied, the search will be performed from the root.
Loading Authorities How authorities are loaded from groups in the LDAP directory is controlled by the following attributes. group-search-base. Defines the part of the directory tree under which group searches should be performed. group-role-attribute. The attribute which contains the name of the authority defined by the group entry. Defaults to cn group-search-filter. The filter which is used to search for group membership. The default is uniqueMember={0}, corresponding to the groupOfUniqueMembers LDAP class. In this case, the substituted parameter is the full distinguished name of the user. The parameter {1} can be used if you want to filter on the login name. So if we used the following configuration ]]> and authenticated successfully as user ben, the subsequent loading of authorities would perform a search under the directory entry ou=groups,dc=springframework,dc=org, looking for entries which contain the attribute uniqueMember with value uid=ben,ou=people,dc=springframework,dc=org. By default the authority names will have the prefix ROLE_ prepended. You can change this using the role-prefix attribute. If you don't want any prefix, use role-prefix="none". For more information on loading authorities, see the Javadoc for the DefaultLdapAuthoritiesPopulator class.
Implementation Classes The namespace configuration options we've used above are simple to use and much more concise than using Spring beans explicitly. There are situations when you may need to know how to configure Spring Security LDAP directly in your application context. You may wish to customize the behaviour of some of the classes, for example. If you're happy using namespace configuration then you can skip this section and the next one. The main LDAP provider class is org.springframework.security.providers.ldap.LdapAuthenticationProvider. This bean doesn't actually do much itself but delegates the work to two other beans, an LdapAuthenticator and an LdapAuthoritiesPopulator which are responsible for authenticating the user and retrieving the user's set of GrantedAuthoritys respectively.
LdapAuthenticator Implementations The authenticator is also responsible for retrieving any required user attributes. This is because the permissions on the attributes may depend on the type of authentication being used. For example, if binding as the user, it may be necessary to read them with the user's own permissions. There are currently two authentication strategies supplied with Spring Security: Authentication directly to the LDAP server ("bind" authentication). Password comparison, where the password supplied by the user is compared with the one stored in the repository. This can either be done by retrieving the value of the password attribute and checking it locally or by performing an LDAP "compare" operation, where the supplied password is passed to the server for comparison and the real password value is never retrieved.
Common Functionality Before it is possible to authenticate a user (by either strategy), the distinguished name (DN) has to be obtained from the login name supplied to the application. This can be done either by simple pattern-matching (by setting the setUserDnPatterns array property) or by setting the userSearch property. For the DN pattern-matching approach, a standard Java pattern format is used, and the login name will be substituted for the parameter {0}. The pattern should be relative to the DN that the configured SpringSecurityContextSource will bind to (see the section on connecting to the LDAP server for more information on this). For example, if you are using an LDAP server with the URL ldap://monkeymachine.co.uk/dc=springframework,dc=org, and have a pattern uid={0},ou=greatapes, then a login name of "gorilla" will map to a DN uid=gorilla,ou=greatapes,dc=springframework,dc=org. Each configured DN pattern will be tried in turn until a match is found. For information on using a search, see the section on search objects below. A combination of the two approaches can also be used - the patterns will be checked first and if no matching DN is found, the search will be used.
BindAuthenticator The class org.springframework.security.providers.ldap.authenticator.BindAuthenticator implements the bind authentication strategy. It simply attempts to bind as the user.
PasswordComparisonAuthenticator The class org.springframework.security.providers.ldap.authenticator.PasswordComparisonAuthenticator implements the password comparison authentication strategy.
Active Directory Authentication In addition to standard LDAP authentication (binding with a DN), Active Directory has its own non-standard syntax for user authentication.
Connecting to the LDAP Server The beans discussed above have to be able to connect to the server. They both have to be supplied with a SpringSecurityContextSource which is an extension of Spring LDAP's ContextSource. Unless you have special requirements, you will usually configure a DefaultSpringSecurityContextSource bean, which can be configured with the URL of your LDAP server and optionally with the username and password of a "manager" user which will be used by default when binding to the server (instead of binding anonymously). For more information read the Javadoc for this class and for Spring LDAP's AbstractContextSource.
LDAP Search Objects Often more a more complicated strategy than simple DN-matching is required to locate a user entry in the directory. This can be encapsulated in an LdapUserSearch instance which can be supplied to the authenticator implementations, for example, to allow them to locate a user. The supplied implementation is FilterBasedLdapUserSearch.
<classname>FilterBasedLdapUserSearch</classname> This bean uses an LDAP filter to match the user object in the directory. The process is explained in the Javadoc for the corresponding search method on the JDK DirContext class. As explained there, the search filter can be supplied with parameters. For this class, the only valid parameter is {0} which will be replaced with the user's login name.
LdapAuthoritiesPopulator After authenticating the user successfully, the LdapAuthenticationProvider will attempt to load a set of authorities for the user by calling the configured LdapAuthoritiesPopulator bean. The DefaultLdapAuthoritiesPopulator is an implementation which will load the authorities by searching the directory for groups of which the user is a member (typically these will be groupOfNames or groupOfUniqueNames entries in the directory). Consult the Javadoc for this class for more details on how it works.
Spring Bean Configuration A typical configuration, using some of the beans we've discussed here, might look like this: uid={0},ou=people ]]> This would set up the provider to access an LDAP server with URL ldap://monkeymachine:389/dc=springframework,dc=org. Authentication will be performed by attempting to bind with the DN uid=<user-login-name>,ou=people,dc=springframework,dc=org. After successful authentication, roles will be assigned to the user by searching under the DN ou=groups,dc=springframework,dc=org with the default filter (member=<user's-DN>). The role name will be taken from the ou attribute of each match. To configure a user search object, which uses the filter (uid=<user-login-name>) for use instead of the DN-pattern (or in addition to it), you would configure the following bean ]]> and use it by setting the BindAuthenticator bean's userSearch property. The authenticator would then call the search object to obtain the correct user's DN before attempting to bind as this user.
LDAP Attributes and Customized UserDetails The net result of an authentication using LdapAuthenticationProvider is the same as a normal Spring Security authentication using the standard UserDetailsService interface. A UserDetails object is created and stored in the returned Authentication object. As with using a UserDetailsService, a common requirement is to be able to customize this implementation and add extra properties. When using LDAP, these will normally be attributes from the user entry. The creation of the UserDetails object is controlled by the provider's UserDetailsContextMapper strategy, which is responsible for mapping user objects to and from LDAP context data: Only the first method is relevant for authentication. If you provide an implementation of this interface, you can control exactly how the UserDetails object is created. The first parameter is an instance of Spring LDAP's DirContextOperations which gives you access to the LDAP attributes which were loaded. The username parameter is the name used to authenticate and the final parameter is the list of authorities loaded for the user. The way the context data is loaded varies slightly depending on the type of authentication you are using. With the BindAuthenticatior, the context returned from the bind operation will be used to read the attributes, otherwise the data will be read using the standard context obtained from the configured ContextSource (when a search is configured to locate the user, this will be the data returned by the search object).
spring-security-2.0.7.RELEASE/docs/reference/preauth.xml0000644000000000000000000003004211766764657017744 0ustar Pre-Authentication Scenarios There are situations where you want to use Spring Security for authorization, but the user has already been reliably authenticated by some external system prior to accessing the application. We refer to these situations as pre-authenticated scenarios. Examples include X.509, Siteminder and authentication by the J2EE container in which the application is running. When using pre-authentication, Spring Security has to Identify the user making the request. Obtain the authorities for the user. The details will depend on the external authentication mechanism. A user might be identified by their certificate information in the case of X.509, or by an HTTP request header in the case of Siteminder. If relying on container authentication, the user will be identified by calling the getUserPrincipal() method on the incoming HTTP request. In some cases, the external mechanism may supply role/authority information for the user but in others the authorities must be obtained from a separate source, such as a UserDetailsService.
Pre-Authentication Framework Classes Because most pre-authentication mechanisms follow the same pattern, Spring Security has a set of classes which provide an internal framework for implementing pre-authenticated authentication providers. This removes duplication and allows new implementations to be added in a structured fashion, without having to write everything from scratch. You don't need to know about these classes if you want to use something like X.509 authentication, as it already has a namespace configuration option which is simpler to use and get started with. If you need to use explicit bean confiuration or are planning on writing your own implementation then an understanding of how the provided implementations work will be useful. You will find the web related classes under the org.springframework.security.ui.preauth package and the backend classes under org.springframework.security.providers.preauth. We just provide an outline here so you should consult the Javadoc and source where appropriate.
AbstractPreAuthenticatedProcessingFilter This class will check the current contents of the security context and, if empty, it will attempt to extract user information from the HTTP request and submit it to the AuthenticationManager. Subclasses override the following methods to obtain this information: protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request); protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request); After calling these, the filter will create a PreAuthenticatedAuthenticationToken containing the returned data and submit it for authentication. By authentication here, we really just mean further processing to perhaps load the user's authorities, but the standard Spring Security authentication architecture is followed.
AbstractPreAuthenticatedAuthenticationDetailsSource Like other Spring Security authentication filters, the pre-authentication filter has an authenticationDetailsSource property which by default will create a WebAuthenticationDetails object to store additional information such as the session-identifier and originating IP address in the details property of the Authentication object. In cases where user role information can be obtained from the pre-authentication mechanism, the data is also stored in this property. Subclasses of AbstractPreAuthenticatedAuthenticationDetailsSource use an extended details object which implements the GrantedAuthoritiesContainer interface, thus enabling the authentication provider to read the authorities which were externally allocated to the user. We'll look at a concrete example next.
J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource If the filter is configured with an authenticationDetailsSource which is an instance of this class, the authority information is obtained by calling the isUserInRole(String role) method for each of a pre-determined set of mappable roles. The class gets these from a configured MappableAttributesRetriever. Possible implementations include hard-coding a list in the application context and reading the role information from the <security-role> information in a web.xml file. The pre-authentication sample application uses the latter approach. There is an additional stage where the roles (or attributes) are mapped to Spring Security GrantedAuthority objects using a configured Attributes2GrantedAuthoritiesMapper. The default will just add the usual ROLE_ prefix to the names, but it gives you full control over the behaviour.
PreAuthenticatedAuthenticationProvider The pre-authenticated provider has little more to do than load the UserDetails object for the user. It does this by delegating to a AuthenticationUserDetailsService. The latter is similar to the standard UserDetailsService but takes an Authentication object rather than just user name: public interface AuthenticationUserDetailsService { UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException; } This interface may have also other uses but with pre-authentication it allows access to the authorities which were packaged in the Authentication object, as we saw in the previous section. The PreAuthenticatedGrantedAuthoritiesUserDetailsService class does this. Alternatively, it may delegate to a standard UserDetailsService via the UserDetailsByNameServiceWrapper implementation.
PreAuthenticatedProcessingFilterEntryPoint The AuthenticationEntryPoint was discussed in the technical overview chapter. Normally it is responsible for kick-starting the authentication process for an unauthenticated user (when they try to access a protected resource), but in the pre-authenticated case this doesn't apply. You would only configure the ExceptionTranslationFilter with an instance of this class if you aren't using pre-authentication in combination with other authentication mechanisms. It will be called if the user is rejected by the AbstractPreAuthenticatedProcessingFilter resulting in a null authentication. It always returns a 403-forbidden response code if called.
Concrete Implementations X.509 authentication is covered in its own chapter. Here we'll look at some classes which provide support for other pre-authenticated scenarios.
Request-Header Authentication (Siteminder) An external authentication system may supply information to the application by setting specific headers on the HTTP request. A well known example of this is is Siteminder, which passes the username in a header called SM_USER. This mechanism is supported by the class RequestHeaderPreAuthenticatedProcessingFilter which simply extracts the username from the header. It defaults to using the name SM_USER as the header name. See the Javadoc for more details. Note that when using a system like this, the framework performs no authentication checks at all and it is extremely important that the external system is configured properly and protects all access to the application. If an attacker is able to forge the headers in their original request without this being detected then they could potentially choose any userame they wished.
Siteminder Example Configuration A typical configuration using this filter would look like this: ]]> We've assumed here that the security namespace is being used for configuration (hence the user of the custom-filter, authentication-manager and custom-authentication-provider elements (you can read more about them in the namespace chapter). You would leave these out of a traditional bean configuration. It's also assumed that you have added a UserDetailsService (called userDetailsService) to your configuration to load the user's roles.
J2EE Container Authentication The class J2eePreAuthenticatedProcessingFilter will extract the username from the userPrincipal property of the HttpServletRequest. use of this filter would usually be combined with the use of J2EE roles as described above in .
spring-security-2.0.7.RELEASE/docs/reference/channel-security.xml0000644000000000000000000002251711766764657021561 0ustar Channel Security
Overview In addition to coordinating the authentication and authorization requirements of your application, Spring Security is also able to ensure unauthenticated web requests have certain properties. These properties may include being of a particular transport type, having a particular HttpSession attribute set and so on. The most common requirement is for your web requests to be received using a particular transport protocol, such as HTTPS. An important issue in considering transport security is that of session hijacking. Your web container manages a HttpSession by reference to a jsessionid that is sent to user agents either via a cookie or URL rewriting. If the jsessionid is ever sent over HTTP, there is a possibility that session identifier can be intercepted and used to impersonate the user after they complete the authentication process. This is because most web containers maintain the same session identifier for a given user, even after they switch from HTTP to HTTPS pages. If session hijacking is considered too significant a risk for your particular application, the only option is to use HTTPS for every request. This means the jsessionid is never sent across an insecure channel. You will need to ensure your web.xml-defined <welcome-file> points to an HTTPS location, and the application never directs the user to an HTTP location. Spring Security provides a solution to assist with the latter.
Configuration Channel security is supported by the security namespace by means of the requires-channel attribute on the <intercept-url> element and this is the simplest (and recommended approach) To confiure channel security explicitly, you would define the following the filter in your application context: ]]> Like FilterSecurityInterceptor, Apache Ant style paths are also supported by the ChannelProcessingFilter. The ChannelProcessingFilter operates by filtering all web requests and determining the configuration attributes that apply. It then delegates to the ChannelDecisionManager. The default implementation, ChannelDecisionManagerImpl, should suffice in most cases. It simply delegates to the list of configured ChannelProcessor instances. The attribute ANY_CHANNEL can be used to override this behaviour and skip a particular URL. Otherwise, a ChannelProcessor will review the request, and if it is unhappy with the request (e.g. if it was received across the incorrect transport protocol), it will perform a redirect, throw an exception or take whatever other action is appropriate. Included with Spring Security are two concrete ChannelProcessor implementations: SecureChannelProcessor ensures requests with a configuration attribute of REQUIRES_SECURE_CHANNEL are received over HTTPS, whilst InsecureChannelProcessor ensures requests with a configuration attribute of REQUIRES_INSECURE_CHANNEL are received over HTTP. Both implementations delegate to a ChannelEntryPoint if the required transport protocol is not used. The two ChannelEntryPoint implementations included with Spring Security simply redirect the request to HTTP and HTTPS as appropriate. Appropriate defaults are assigned to the ChannelProcessor implementations for the configuration attribute keywords they respond to and the ChannelEntryPoint they delegate to, although you have the ability to override these using the application context. Note that the redirections are absolute (eg http://www.company.com:8080/app/page), not relative (eg /app/page). During testing it was discovered that Internet Explorer 6 Service Pack 1 has a bug whereby it does not respond correctly to a redirection instruction which also changes the port to use. Accordingly, absolute URLs are used in conjunction with bug detection logic in the PortResolverImpl that is wired up by default to many Spring Security beans. Please refer to the JavaDocs for PortResolverImpl for further details. You should note that using a secure channel is recommended if usernames and passwords are to be kept secure during the login process. If you do decide to use ChannelProcessingFilter with form-based login, please ensure that your login page is set to REQUIRES_SECURE_CHANNEL, and that the AuthenticationProcessingFilterEntryPoint.forceHttps property is true.
Conclusion Once configured, using the channel security filter is very easy. Simply request pages without regard to the protocol (ie HTTP or HTTPS) or port (eg 80, 8080, 443, 8443 etc). Obviously you'll still need a way of making the initial request (probably via the web.xml <welcome-file> or a well-known home page URL), but once this is done the filter will perform redirects as defined by your application context. You can also add your own ChannelProcessor implementations to the ChannelDecisionManagerImpl. For example, you might set a HttpSession attribute when a human user is detected via a "enter the contents of this graphic" procedure. Your ChannelProcessor would respond to say REQUIRES_HUMAN_USER configuration attributes and redirect to an appropriate entry point to start the human user validation process if the HttpSession attribute is not currently set. To decide whether a security check belongs in a ChannelProcessor or an AccessDecisionVoter, remember that the former is designed to handle unauthenticated requests, whilst the latter is designed to handle authenticated requests. The latter therefore has access to the granted authorities of the authenticated principal. In addition, problems detected by a ChannelProcessor will generally cause an HTTP/HTTPS redirection so its requirements can be met, whilst problems detected by an AccessDecisionVoter will ultimately result in an AccessDeniedException (depending on the governing AccessDecisionManager).
spring-security-2.0.7.RELEASE/docs/reference/namespace-config.xml0000644000000000000000000012477311766764657021512 0ustar Security Namespace Configuration
Introduction Namespace configuration has been available since version 2.0 of the Spring framework. It allows you to supplement the traditional Spring beans application context syntax with elements from additional XML schema. You can find more information in the Spring Reference Documentation. A namespace element can be used simply to allow a more concise way of configuring an individual bean or, more powerfully, to define an alternative configuration syntax which more closely matches the problem domain and hides the underlying complexity from the user. A simple element may conceal the fact that multiple beans and processing steps are being added to the application context. For example, adding the following element from the security namespace to an application context will start up an embedded LDAP server for testing use within the application: ]]> This is much simpler than wiring up the equivalent Apache Directory Server beans. The most common alternative configuration requirements are supported by attributes on the ldap-server element and the user is isolated from worrying about which beans they need to be set on and what the bean property names are. You can find out more about the use of the ldap-server element in the chapter on LDAP. . Use of a good XML editor while editing the application context file should provide information on the attributes and elements that are available. We would recommend that you try out the SpringSource Tool Suite as it has special features for working with the Spring portfolio namespaces. To start using the security namespace in your application context, all you need to do is add the schema declaration to your application context file: ... ]]> In many of the examples you will see (and in the sample) applications, we will often use "security" as the default namespace rather than "beans", which means we can omit the prefix on all the security namespace elements, making the context easier to read. You may also want to do this if you have your application context divided up into separate files and have most of your security configuration in one of them. Your security application context file would then start like this ... ]]> We'll assume this syntax is being used from now on in this chapter.
Design of the Namespace The namespace is designed to capture the most common uses of the framework and provide a simplified and concise syntax for enabling them within an application. The design is largely based around the large-scale dependencies within the framework, and can be divided up into the following areas: Web/HTTP Security - the most complex part. Sets up the filters and related service beans used to apply the framework authentication mechanisms, to secure URLs, render login and error pages and much more. Business Object (Method) Security - options for securing the service layer. AuthenticationManager - handles authentication requests from other parts of the framework. A default instance will be registered internally by the namespace. AccessDecisionManager - provides access decisions for web and method security. A default one will be registered, but you can also choose to use a custom one, declared using normal Spring bean syntax. AuthenticationProviders - mechanisms against which the authentication manager authenticates users. The namespace provides supports for several standard options and also a means of adding custom beans declared using a traditional syntax. UserDetailsService - closely related to authentication providers, but often also required by other beans. We'll see how these work together in the following sections.
Getting Started with Security Namespace Configuration In this section, we'll look at how you can build up a namespace configuration to use some of the main features of the framework. Let's assume you initially want to get up and running as quickly as possible and add authentication support and access control to an existing web application, with a few test logins. Then we'll look at how to change over to authenticating against a database or other security information repository. In later sections we'll introduce more advanced namespace configuration options.
<literal>web.xml</literal> Configuration The first thing you need to do is add the following filter declaration to your web.xml file: springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy springSecurityFilterChain /* ]]> This provides a hook into the Spring Security web infrastructure. DelegatingFilterProxy is a Spring Framework class which delegates to a filter implementation which is defined as a Spring bean in your application context. In this case, the bean is named "springSecurityFilterChain", which is an internal infrastructure bean created by the namespace to handle web security. Note that you should not use this bean name yourself. Once you've added this to your web.xml, you're ready to start editing your application context file. Web security services are configured using the <http> element.
A Minimal <literal><http></literal> Configuration All you need to enable web security to begin with is ]]> Which says that we want all URLs within our application to be secured, requiring the role ROLE_USER to access them. You can use multiple <intercept-url> elements to define different access requirements for different sets of URLs, but they will be evaluated in the order listed and the first match will be used. So you must put the most specific matches at the top. To add some users, you can define a set of test data directly in the namespace: ]]> If you are familiar with previous versions of the framework, you can probably already guess roughly what's going on here. The <http> element is responsible for creating a FilterChainProxy and the filter beans which it uses. Common issues like incorrect filter ordering are no longer an issue as the filter positions are predefined. The <authentication-provider> element creates a DaoAuthenticationProvider bean and the <user-service> element creates an InMemoryDaoImpl. A ProviderManager bean is always created by the namespace processing system and the DaoAuthenticationProvider is automatically registered with it. You can find more detailed information on the beans that are created in the namespace appendix. The configuration above defines two users, their passwords and their roles within the application (which will be used for access control). It is also possible to load user information from a standard properties file using the properties attribute on user-service. See the section on in-memory authentication for more details. Using the <authentication-provider> element means that the user information will be used by the authentication manager to process authentication requests. At this point you should be able to start up your application and you will be required to log in to proceed. Try it out, or try experimenting with the "tutorial" sample application that comes with the project. The above configuration actually adds quite a few services to the application because we have used the auto-config attribute. For example, form login processing and "remember-me" services are automatically enabled.
What does <literal>auto-config</literal> Include? The auto-config attribute, as we have used it above, is just a shorthand syntax for: ]]> These other elements are responsible for setting up form-login, anonymous authentication, basic authentication, logout handling and remember-me services respectively. They each have attributes which can be used to alter their behaviour. <literal>auto-config</literal> Requires a UserDetailsService An error can occur when using auto-config without a UserDetailsService in your application context (for example, if you are using LDAP authentication). This is because remember-me is automatically enabled when auto-config="true" and it requires an authentication mechanism which uses a UserDetailsService to function (see the Remember-me chapter for more details). If you have an error caused by a missing UserDetailsService then try removing the auto-config setting (and any remember-me setting you might have).
Form and Basic Login Options You might be wondering where the login form came from when you were prompted to log in, since we made no mention of any HTML files or JSPs. In fact, since we didn't explicitly set a URL for the login page, Spring Security generates one automatically, based on the features that are enabled and using standard values for the URL which processes the submitted login, the default target URL the user will be sent to and so on. However, the namespace offers plenty of suppport to allow you to customize these options. For example, if you want to supply your own login page, you could use: ]]> Note that you can still use auto-config. The form-login element just overrides the default settings. Also note that we've added an extra intercept-url element to say that any requests for the login page should be excluded from processing by the security filters. Otherwise the request would be matched by the pattern /** and it wouldn't be possible to access the login page itself! If you want to use basic authentication instead of form login, then change the configuration to ]]> Basic authentication will then take precedence and will be used to prompt for a login when a user attempts to access a protected resource. Form login is still available in this configuration if you wish to use it, for example through a login form embedded in another web page.
Setting a Default Post-Login Destination If a form login isn't prompted by an attempt to access a protected resource, the default-target-url option comes into play. This is the URL the user will be taken to after logging in, and defaults to "/". You can also configure things so that they user always ends up at this page (regardless of whether the login was "on-demand" or they explicitly chose to log in) by setting the always-use-default-target attribute to "true". This is useful if your application always requires that the user starts at a "home" page, for example: ]]>
Using other Authentication Providers In practice you will need a more scalable source of user information than a few names added to the application context file. Most likely you will want to store your user information in something like a database or an LDAP server. LDAP namespace configuration is dealt with in the LDAP chapter, so we won't cover it here. If you have a custom implementation of Spring Security's UserDetailsService, called "myUserDetailsService" in your application context, then you can authenticate against this using ]]> If you want to use a database, then you can use ]]> Where "securityDataSource" is the name of a DataSource bean in the application context, pointing at a database containing the standard Spring Security user data tables. Alternatively, you could configure a Spring Security JdbcDaoImpl bean and point at that using the user-service-ref attribute: ]]> You can also use standard AuthenticationProvider beans by adding the <custom-authentication-provider> element within the bean definition. See for more on this.
Adding a Password Encoder Often your password data will be encoded using a hashing algorithm. This is supported by the <password-encoder> element. With SHA encoded passwords, the original authentication provider configuration would look like this: ]]> When using hashed passwords, it's also a good idea to use a salt value to protect against dictionary attacks and Spring Security supports this too. Ideally you would want to use a randomly generated salt value for each user, but you can use any property of the UserDetails object which is loaded by your UserDetailsService. For example, to use the username property, you would use ]]> You can use a custom password encoder bean by using the ref attribute of password-encoder. This should contain the name of a bean in the application context which is an instance of Spring Security's PasswordEncoder interface.
Advanced Web Features
Remember-Me Authentication See the separate Remember-Me chapter for information on remember-me namespace configuration.
Adding HTTP/HTTPS Channel Security If your application supports both HTTP and HTTPS, and you require that particular URLs can only be accessed over HTTPS, then this is directly supported using the requires-channel attribute on <intercept-url>: ... ]]> With this configuration in place, if a user attempts to access anything matching the "/secure/**" pattern using HTTP, they will first be redirected to an HTTPS URL. The available options are "http", "https" or "any". Using the value "any" means that either HTTP or HTTPS can be used. If your application uses non-standard ports for HTTP and/or HTTPS, you can specify a list of port mappings as follows: ... ]]> You can find a more in-depth discussion of channel security in .
Concurrent Session Control If you wish to place constraints on a single user's ability to log in to your application, Spring Security supports this out of the box with the following simple additions. First you need to add the following listener to your web.xml file to keep Spring Security updated about session lifecycle events: org.springframework.security.ui.session.HttpSessionEventPublisher ]]> Then add the following line to your application context: ... ]]> This will prevent a user from logging in multiple times - a second login will cause the first to be invalidated. Often you would prefer to prevent a second login, in which case you can use ... ]]> The second login will then be rejected.
OpenID Login The namespace supports OpenID login either instead of, or in addition to normal form-based login, with a simple change: ]]> You should then register yourself with an OpenID provider (such as myopenid.com), and add the user information to your in-memory <user-service>: ]]> You should be able to login using the myopenid.com site to authenticate.
Adding in Your Own Filters If you've used Spring Security before, you'll know that the framework maintains a chain of filters in order to apply its services. You may want to add your own filters to the stack at particular locations or use a Spring Security filter for which there isn't currently a namespace configuration option (CAS, for example). Or you might want to use a customized version of a standard namespace filter, such as the AuthenticationProcessingFilter which is created by the <form-login> element, taking advantage of some of the extra configuration options which are available by using defining the bean directly. How can you do this with namespace configuration, since the filter chain is not directly exposed? The order of the filters is always strictly enforced when using the namespace. Each Spring Security filter implements the Spring Ordered interface and the filters created by the namespace are sorted during initialization. The standard Spring Security filters each have an alias in the namespace. The filters, aliases and namespace elements/attributes which create the filters are shown in . Standard Filter Aliases and Ordering AliasFilter ClassNamespace Element or Attribute CHANNEL_FILTER ChannelProcessingFilter http/intercept-url CONCURRENT_SESSION_FILTER ConcurrentSessionFilter http/concurrent-session-control SESSION_CONTEXT_INTEGRATION_FILTER HttpSessionContextIntegrationFilter http LOGOUT_FILTER LogoutFilter http/logout X509_FILTER X509PreAuthenticatedProcessigFilter http/x509 PRE_AUTH_FILTER AstractPreAuthenticatedProcessingFilter Subclasses N/A CAS_PROCESSING_FILTER CasProcessingFilter N/A AUTHENTICATION_PROCESSING_FILTER AuthenticationProcessingFilter http/form-login BASIC_PROCESSING_FILTER BasicProcessingFilter http/http-basic SERVLET_API_SUPPORT_FILTER SecurityContextHolderAwareRequestFilter http/@servlet-api-provision REMEMBER_ME_FILTER RememberMeProcessingFilter http/remember-me ANONYMOUS_FILTER AnonymousProcessingFilter http/anonymous EXCEPTION_TRANSLATION_FILTER ExceptionTranslationFilter http NTLM_FILTER NtlmProcessingFilter N/A FILTER_SECURITY_INTERCEPTOR FilterSecurityInterceptor http SWITCH_USER_FILTER SwitchUserProcessingFilter N/A
You can add your own filter to the stack, using the custom-filter element and one of these names to specify the position your filter should appear at: ]]> You can also use the after or before attribtues if you want your filter to be inserted before or after another filter in the stack. The names "FIRST" and "LAST" can be used with the position attribute to indicate that you want your filter to appear before or after the entire stack, respectively.
Avoiding filter position conflicts If you are inserting a custom filter which may occupy the same position as one of the standard filters created by the namespace then it's important that you don't include the namespace versions by mistake. Avoid using the auto-config attribute and remove any elements which create filters whose functionality you want to replace. Note that you can't replace filters which are created by the use of the <http> element itself - HttpSessionContextIntegrationFilter, ExceptionTranslationFilter or FilterSecurityInterceptor. If you're replacing a namespace filter which requires an authentication entry point (i.e. where the authentication process is triggered by an attempt by an unauthenticated user to access to a secured resource), you will need to add a custom entry point bean too.
Setting a Custom <interfacename>AuthenticationEntryPoint</interfacename> If you aren't using form login, OpenID or basic authentication through the namespace, you may want to define an authentication filter and entry point using a traditional bean syntax and link them into the namespace, as we've just seen. The corresponding AuthenticationEntryPoint can be set using the entry-point-ref attribute on the <http> element. The CAS sample application is a good example of the use of custom beans with the namespace, including this syntax. If you aren't familiar with authentication entry points, they are discussed in the technical overview chapter.
Session Fixation Attack Protection Session fixation attacks are a potential risk where it is possible for a malicious attacker to create a session by accessing a site, then persuade another user to log in with the same session (by sending them a link containing the session identifier as a parameter, for example). Spring Security protects against this automatically by creating a new session when a user logs in. If you don't require this protection, or it conflicts with some other requirement, you can control the behaviour using the session-fixation-protection attribute on <http>, which has three options migrateSession - creates a new session and copies the existing session attributes to the new session. This is the default. none - Don't do anything. The original session will be retained. newSession - Create a new "clean" session, without copying the existing session data.
Method Security Spring Security 2.0 has improved support substantially for adding security to your service layer methods. If you are using Java 5 or greater, then support for JSR-250 security annotations is provided, as well as the framework's native @Secured annotation. You can apply security to a single bean, using the intercept-methods element to decorate the bean declaration, or you can secure multiple beans across the entire service layer using the AspectJ style pointcuts.
The <literal><global-method-security></literal> Element This element is used to enable annotation-based security in your application (by setting the appropriate attributes on the element), and also to group together security pointcut declarations which will be applied across your entire application context. You should only declare one <global-method-security> element. The following declaration would enable support for both Spring Security's @Secured, and JSR-250 annotations: ]]> Adding an annotation to a method (on an class or interface) would then limit the access to that method accordingly. Spring Security's native annotation support defines a set of attributes for the method. These will be passed to the AccessDecisionManager for it to make the actual decision. This example is taken from the tutorial sample, which is a good starting point if you want to use method security in your application: public interface BankService { @Secured("IS_AUTHENTICATED_ANONYMOUSLY") public Account readAccount(Long id); @Secured("IS_AUTHENTICATED_ANONYMOUSLY") public Account[] findAccounts(); @Secured("ROLE_TELLER") public Account post(Account account, double amount); }
Adding Security Pointcuts using <literal>protect-pointcut</literal> The use of protect-pointcut is particularly powerful, as it allows you to apply security to many beans with only a simple declaration. Consider the following example: ]]> This will protect all methods on beans declared in the application context whose classes are in the com.mycompany package and whose class names end in "Service". Only users with the ROLE_USER role will be able to invoke these methods. As with URL matching, the most specific matches must come first in the list of pointcuts, as the first matching expression will be used.
The <literal>intercept-methods</literal> Bean Decorator This alternative syntax allows you to specify security for a specific bean by adding this element within the bean itself. ]]> This allows you to configure security attributes for individual methods on the bean or simple wildcarded patterns.
The Default AccessDecisionManager This section assumes you have some knowledge of the underlying architecture for access-control within Spring Security. If you don't you can skip it and come back to it later, as this section is only really relevant for people who need to do some customization in order to use more than simple role based security. When you use a namespace configuration, a default instance of AccessDecisionManager is automatically registered for you and will be used for making access decisions for method invocations and web URL access, based on the access attributes you specify in your intercept-url and protect-pointcut declarations (and in annotations if you are using annotation secured methods). The default strategy is to use an AffirmativeBased AccessDecisionManager with a RoleVoter and an AuthenticatedVoter.
Customizing the AccessDecisionManager If you need to use a more complicated access control strategy then it is easy to set an alternative for both method and web security. For method security, you do this by setting the access-decision-manager-ref attribute on global-method-securityto the Id of the appropriate AccessDecisionManager bean in the application context: ... ]]> The syntax for web security is the same, but on the http element: ... ]]>
The Default Authentication Manager We've touched on the idea that the namespace configuration automatically registers an authentication manager bean for you. This is an instance of Spring Security's ProviderManager class, which you may already be familiar with if you've used the framework before. You can't use a custom AuthenticationProvider if you are using either HTTP or method security through the namespace, but this should not be a problem as you have full control over the AuthenticationProviders that are used. You may want to register additional AuthenticationProvider beans with the ProviderManager and you can do this using the <custom-authentication-provider> element within the bean. For example: ... ]]> Another common requirement is that another bean in the context may require a reference to the AuthenticationManager. There is a special element which lets you register an alias for the AuthenticationManager and you can then use this name elsewhere in your application context. ... ]]>
spring-security-2.0.7.RELEASE/docs/reference/secured-objects.xml0000644000000000000000000004067711766764657021374 0ustar Secure Object Implementations
AOP Alliance (MethodInvocation) Security Interceptor Prior to Spring Security 2.0, securing MethodInvocations needed quite a lot of boiler plate configuration. Now the recommended approach for method security is to use namespace configuration. This way the method security infrastructure beans are configured automatically for you so you don't really need to know about the implementation classes. We'll just provide a quick overview of the classes that are involved here. Method security in enforced using a MethodSecurityInterceptor, which secures MethodInvocations. Depending on the configuration approach, an interceptor may be specific to a single bean or shared between multiple beans. The interceptor uses a MethodDefinitionSource instance to obtain the configuration attributes that apply to a particular method invocation. MapBasedMethodDefinitionSource is used to store configuration attributes keyed by method names (which can be wildcarded) and will be used internally when the attributes are defined in the application context using the <intercept-methods> or <protect-point> elements. Other implementations will be used to handle annotation-based configuration.
Explicit MethodSecurityIterceptor Configuration You can of course configure a MethodSecurityIterceptor directly in your application context for use with one of Spring AOP's proxying mechanisms: org.springframework.security.context.BankManager.delete*=ROLE_SUPERVISOR org.springframework.security.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR ]]>
AspectJ (JoinPoint) Security Interceptor The AspectJ security interceptor is very similar to the AOP Alliance security interceptor discussed in the previous section. Indeed we will only discuss the differences in this section. The AspectJ interceptor is named AspectJSecurityInterceptor. Unlike the AOP Alliance security interceptor, which relies on the Spring application context to weave in the security interceptor via proxying, the AspectJSecurityInterceptor is weaved in via the AspectJ compiler. It would not be uncommon to use both types of security interceptors in the same application, with AspectJSecurityInterceptor being used for domain object instance security and the AOP Alliance MethodSecurityInterceptor being used for services layer security. Let's first consider how the AspectJSecurityInterceptor is configured in the Spring application context: org.springframework.security.context.BankManager.delete*=ROLE_SUPERVISOR org.springframework.security.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR ]]> As you can see, aside from the class name, the AspectJSecurityInterceptor is exactly the same as the AOP Alliance security interceptor. Indeed the two interceptors can share the same objectDefinitionSource, as the ObjectDefinitionSource works with java.lang.reflect.Methods rather than an AOP library-specific class. Of course, your access decisions have access to the relevant AOP library-specific invocation (ie MethodInvocation or JoinPoint) and as such can consider a range of addition criteria when making access decisions (such as method arguments). Next you'll need to define an AspectJ aspect. For example: package org.springframework.security.samples.aspectj; import org.springframework.security.intercept.method.aspectj.AspectJSecurityInterceptor; import org.springframework.security.intercept.method.aspectj.AspectJCallback; import org.springframework.beans.factory.InitializingBean; public aspect DomainObjectInstanceSecurityAspect implements InitializingBean { private AspectJSecurityInterceptor securityInterceptor; pointcut domainObjectInstanceExecution(): target(PersistableEntity) && execution(public * *(..)) && !within(DomainObjectInstanceSecurityAspect); Object around(): domainObjectInstanceExecution() { if (this.securityInterceptor == null) { return proceed(); } AspectJCallback callback = new AspectJCallback() { public Object proceedWithObject() { return proceed(); } }; return this.securityInterceptor.invoke(thisJoinPoint, callback); } public AspectJSecurityInterceptor getSecurityInterceptor() { return securityInterceptor; } public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) { this.securityInterceptor = securityInterceptor; } public void afterPropertiesSet() throws Exception { if (this.securityInterceptor == null) throw new IllegalArgumentException("securityInterceptor required"); } } In the above example, the security interceptor will be applied to every instance of PersistableEntity, which is an abstract class not shown (you can use any other class or pointcut expression you like). For those curious, AspectJCallback is needed because the proceed(); statement has special meaning only within an around() body. The AspectJSecurityInterceptor calls this anonymous AspectJCallback class when it wants the target object to continue. You will need to configure Spring to load the aspect and wire it with the AspectJSecurityInterceptor. A bean declaration which achieves this is shown below: ]]> That's it! Now you can create your beans from anywhere within your application, using whatever means you think fit (eg new Person();) and they will have the security interceptor applied.
FilterInvocation Security Interceptor To secure FilterInvocations, developers need to add a FilterSecurityInterceptor to their filter chain. A typical configuration example is provided below: In the application context you will need to configure three beans: ]]> The ExceptionTranslationFilter provides the bridge between Java exceptions and HTTP responses. It is solely concerned with maintaining the user interface. This filter does not do any actual security enforcement. If an AuthenticationException is detected, the filter will call the AuthenticationEntryPoint to commence the authentication process (e.g. a user login). The AuthenticationEntryPoint will be called if the user requests a secure HTTP resource but they are not authenticated. The class handles presenting the appropriate response to the user so that authentication can begin. Three concrete implementations are provided with Spring Security: AuthenticationProcessingFilterEntryPoint for commencing a form-based authentication, BasicProcessingFilterEntryPoint for commencing a HTTP Basic authentication process, and CasProcessingFilterEntryPoint for commencing a JA-SIG Central Authentication Service (CAS) login. The AuthenticationProcessingFilterEntryPoint and CasProcessingFilterEntryPoint have optional properties related to forcing the use of HTTPS, so please refer to the JavaDocs if you require this. FilterSecurityInterceptor is responsible for handling the security of HTTP resources. Like any other security interceptor, it requires a reference to an AuthenticationManager and an AccessDecisionManager, which are both discussed in separate sections below. The FilterSecurityInterceptor is also configured with configuration attributes that apply to different HTTP URL requests. A full discussion of configuration attributes is provided in the High Level Design section of this document. The FilterSecurityInterceptor can be configured with configuration attributes in two ways. The first, which is shown above, is using the <filter-invocation-definition-source> namespace element. This is similar to the <filter-chain-map> used to configure a FilterChainProxy but the <intercept-url> child elements only use the pattern and access attributes. The second is by writing your own ObjectDefinitionSource, although this is beyond the scope of this document. Irrespective of the approach used, the ObjectDefinitionSource is responsible for returning a ConfigAttributeDefinition object that contains all of the configuration attributes associated with a single secure HTTP URL. It should be noted that the FilterSecurityInterceptor.setObjectDefinitionSource() method actually expects an instance of FilterInvocationDefinitionSource. This is a marker interface which subclasses ObjectDefinitionSource. It simply denotes the ObjectDefinitionSource understands FilterInvocations. In the interests of simplicity we'll continue to refer to the FilterInvocationDefinitionSource as an ObjectDefinitionSource, as the distinction is of little relevance to most users of the FilterSecurityInterceptor. When using the namespace option to configure the interceptor, commas are used to delimit the different configuration attributes that apply to each HTTP URL. Each configuration attribute is assigned into its own SecurityConfig object. The SecurityConfig object is discussed in the High Level Design section. The ObjectDefinitionSource created by the property editor, FilterInvocationDefinitionSource, matches configuration attributes against FilterInvocations based on expression evaluation of the request URL. Two standard expression syntaxes are supported. The default is to treat all expressions as Apache Ant paths and regular expressions are also supported for ore complex cases. The path-type attribute is used to specify the type of pattern being used. It is not possible to mix expression syntaxes within the same definition. For example, the previous configuration using regular expressions instead of Ant paths would be written as follows: ]]> Irrespective of the type of expression syntax used, expressions are always evaluated in the order they are defined. Thus it is important that more specific expressions are defined higher in the list than less specific expressions. This is reflected in our example above, where the more specific /secure/super/ pattern appears higher than the less specific /secure/ pattern. If they were reversed, the /secure/ pattern would always match and the /secure/super/ pattern would never be evaluated. As with other security interceptors, the validateConfigAttributes property is observed. When set to true (the default), at startup time the FilterSecurityInterceptor will evaluate if the provided configuration attributes are valid. It does this by checking each configuration attribute can be processed by either the AccessDecisionManager or the RunAsManager. If neither of these can process a given configuration attribute, an exception is thrown.
spring-security-2.0.7.RELEASE/docs/reference/form-authentication.xml0000644000000000000000000000635011766764657022261 0ustar Form Authentication Mechanism
Overview HTTP Form Authentication involves using the AuthenticationProcessingFilter to process a login form. This is the most common way for an application to authenticate end users. Form-based authentication is entirely compatible with the DAO and JAAS authentication providers.
Configuration The login form simply contains j_username and j_password input fields, and posts to a URL that is monitored by the filter (by default /j_spring_security_check). You should add an AuthenticationProcessingFilter to your application context: ]]> The configured AuthenticationManager processes each authentication request. If authentication fails, the browser will be redirected to the authenticationFailureUrl. The AuthenticationException will be placed into the HttpSession attribute indicated by AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY, enabling a reason to be provided to the user on the error page. If authentication is successful, the resulting Authentication object will be placed into the SecurityContextHolder. Once the SecurityContextHolder has been updated, the browser will need to be redirected to the target URL which is usually indicated by the HttpSession attribute stored under AbstractProcessingFilter.SPRING_SECURITY_TARGET_URL_KEY. This attribute is automatically set by the ExceptionTranslationFilter when an AuthenticationException occurs, so that after login is completed the user can return to what they were originally trying to access. If for some reason the HttpSession does not indicate the target URL, the browser will be redirected to the defaultTargetUrl property.
spring-security-2.0.7.RELEASE/docs/reference/digest-authentication.xml0000644000000000000000000002073111766764657022574 0ustar Digest Authentication
Overview Spring Security provides a DigestProcessingFilter which is capable of processing digest authentication credentials presented in HTTP headers. Digest Authentication attempts to solve many of the weaknesses of Basic authentication, specifically by ensuring credentials are never sent in clear text across the wire. Many user agents support Digest Authentication, including FireFox and Internet Explorer. The standard governing HTTP Digest Authentication is defined by RFC 2617, which updates an earlier version of the Digest Authentication standard prescribed by RFC 2069. Most user agents implement RFC 2617. Spring Security DigestProcessingFilter is compatible with the "auth" quality of protection (qop) prescribed by RFC 2617, which also provides backward compatibility with RFC 2069. Digest Authentication is a highly attractive option if you need to use unencrypted HTTP (ie no TLS/HTTPS) and wish to maximise security of the authentication process. Indeed Digest Authentication is a mandatory requirement for the WebDAV protocol, as noted by RFC 2518 Section 17.1, so we should expect to see it increasingly deployed and replacing Basic Authentication. Digest Authentication is definitely the most secure choice between Form Authentication, Basic Authentication and Digest Authentication, although extra security also means more complex user agent implementations. Central to Digest Authentication is a "nonce". This is a value the server generates. Spring Security's nonce adopts the following format: base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) expirationTime: The date and time when the nonce expires, expressed in milliseconds key: A private key to prevent modification of the nonce token The DigestProcessingFilterEntryPoint has a property specifying the key used for generating the nonce tokens, along with a nonceValiditySeconds property for determining the expiration time (default 300, which equals five minutes). Whist ever the nonce is valid, the digest is computed by concatenating various strings including the username, password, nonce, URI being requested, a client-generated nonce (merely a random value which the user agent generates each request), the realm name etc, then performing an MD5 hash. Both the server and user agent perform this digest computation, resulting in different hash codes if they disagree on an included value (eg password). In Spring Security implementation, if the server-generated nonce has merely expired (but the digest was otherwise valid), the DigestProcessingFilterEntryPoint will send a "stale=true" header. This tells the user agent there is no need to disturb the user (as the password and username etc is correct), but simply to try again using a new nonce. An appropriate value for DigestProcessingFilterEntryPoint's nonceValiditySeconds parameter will depend on your application. Extremely secure applications should note that an intercepted authentication header can be used to impersonate the principal until the expirationTime contained in the nonce is reached. This is the key principle when selecting an appropriate setting, but it would be unusual for immensely secure applications to not be running over TLS/HTTPS in the first instance. Because of the more complex implementation of Digest Authentication, there are often user agent issues. For example, Internet Explorer fails to present an "opaque" token on subsequent requests in the same session. Spring Security filters therefore encapsulate all state information into the "nonce" token instead. In our testing, Spring Security implementation works reliably with FireFox and Internet Explorer, correctly handling nonce timeouts etc.
Configuration Now that we've reviewed the theory, let's see how to use it. To implement HTTP Digest Authentication, it is necessary to define DigestProcessingFilter in the fitler chain. The application context will need to define the DigestProcessingFilter and its required collaborators: ]]> The configured UserDetailsService is needed because DigestProcessingFilter must have direct access to the clear text password of a user. Digest Authentication will NOT work if you are using encoded passwords in your DAO. The DAO collaborator, along with the UserCache, are typically shared directly with a DaoAuthenticationProvider. The authenticationEntryPoint property must be DigestProcessingFilterEntryPoint, so that DigestProcessingFilter can obtain the correct realmName and key for digest calculations. Like BasicAuthenticationFilter, if authentication is successful an Authentication request token will be placed into the SecurityContextHolder. If the authentication event was successful, or authentication was not attempted because the HTTP header did not contain a Digest Authentication request, the filter chain will continue as normal. The only time the filter chain will be interrupted is if authentication fails and the AuthenticationEntryPoint is called, as discussed in the previous paragraph. Digest Authentication's RFC offers a range of additional features to further increase security. For example, the nonce can be changed on every request. Despite this, Spring Security implementation was designed to minimise the complexity of the implementation (and the doubtless user agent incompatibilities that would emerge), and avoid needing to store server-side state. You are invited to review RFC 2617 if you wish to explore these features in more detail. As far as we are aware, Spring Security's implementation does comply with the minimum standards of this RFC.
spring-security-2.0.7.RELEASE/docs/reference/common-auth-services.xml0000644000000000000000000005673411766764657022364 0ustar Common Authentication Services
Mechanisms, Providers and Entry Points To use Spring Security's authentication services, you'll usually need to configure a web filter, together with an AuthenticationProvider and AuthenticationEntryPoint. In this section we are going to explore an example application that needs to support both form-based authentication (so a nice HTML page is presented to a user for them to login) and BASIC authentication (so a web service or similar can access protected resources). In the web.xml, this application will need a single Spring Security filter in order to use the FilterChainProxy. Nearly every Spring Security application will have such an entry, and it looks like this: filterChainProxy org.springframework.web.filter.DelegatingFilterProxy filterChainProxy /* ]]> The above declarations will cause every web request to be passed through to the bean called filterChainProxy which will usually be an instance of Spring Security's FilterChainProxy. As explained in the filters section of this reference guide, the FilterChainProxy is a generally-useful class that enables web requests to be passed to different filters based on URL patterns. Those delegated filters are managed inside the application context, so they can benefit from dependency injection. Let's have a look at what the FilterChainProxy bean definition would look like inside your application context: ]]> The filter-chain-map syntax from the security namespace allows you to define the mapping from URLs to filter chains, using a sequence of filter-chain child elements. Each of these defines a set of URLs using the pattern attribute and a chain of filters using the filters attribute.What's important to note at this stage is that a series of filters will be run - in the order specified by the declaration - and each of those filters are actually the id of another bean in the application context. So, in our case some extra beans will also appear in the application context, and they'll be named httpSessionContextIntegrationFilter, logoutFilter and so on. The order that the filters should appear is discussed in the filters section of the reference guide - although they are correct in the above example. In our example we have the AuthenticationProcessingFilter and BasicProcessingFilter being used. These are the "authentication mechanisms" that respond to form-based authentication and BASIC HTTP header-based authentication respectively (we discussed the role of authentication mechanisms earlier in this reference guide). If you weren't using form or BASIC authentication, neither of these beans would be defined. You'd instead define filters applicable to your desired authentication environment, such as DigestProcessingFilter or CasProcessingFilter. Refer to the individual chapters of this part of the reference guide to learn how to configure each of these authentication mechanisms. Recall that HttpSessionContextIntegrationFilter keeps the contents of the SecurityContext between invocations inside an HTTP session. This means the authentication mechanisms are only used once, being when the principal initially tries to authenticate. The rest of the time the authentication mechanisms sit there and silently pass the request through to the next filter in the chain. That is a practical requirement due to the fact that few authentication approaches present credentials on each and every call (BASIC authentication being a notable exception), but what happens if a principal's account gets cancelled or disabled or otherwise changed (eg an increase or decrease in GrantedAuthority[]s) after the initial authentication step? Let's look at how that is handled now. The major authorization provider for secure objects has previously been introduced as AbstractSecurityInterceptor. This class needs to have access to an AuthenticationManager. It also has configurable settings to indicate whether an Authentication object should be re-authenticated on each secure object invocation. By default it just accepts any Authentication inside the SecurityContextHolder is authenticated if Authentication.isAuthenticated() returns true. This is great for performance, but not ideal if you want to ensure up-to-the-moment authentication validity. For such cases you'll probably want to set the AbstractSecurityInterceptor.alwaysReauthenticate property to true. You might be asking yourself, "what's this AuthenticationManager?". We haven't explored it before, but we have discussed the concept of an AuthenticationProvider. Quite simply, an AuthenticationManager is responsible for passing requests through a chain of AuthenticationProviders. It's a little like the filter chain we discussed earlier, although there are some differences. There is only one AuthenticationManager implementation shipped with Spring Security, so let's look at how it's configured for the example we're using in this chapter: <bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager"> <property name="providers"> <list> <ref local="daoAuthenticationProvider"/> <ref local="anonymousAuthenticationProvider"/> <ref local="rememberMeAuthenticationProvider"/> </list> </property> </bean> It's probably worth mentioning at this point that your authentication mechanisms (which are usually filters) are also injected with a reference to the AuthenticationManager. So both AbstractSecurityInterceptor as well as the authentication mechanisms will use the above ProviderManager to poll a list of AuthenticationProviders. In our example we have three providers. They are tried in the order shown (which is implied by the use of a List instead of a Set), with each provider able to attempt authentication, or skip authentication by simply returning null. If all implementations return null, the ProviderManager will throw a suitable exception. If you're interested in learning more about chaining providers, please refer to the ProviderManager JavaDocs. The providers to use will sometimes be interchangeable with the authentication mechanisms, whilst at other times they will depend on a specific authentication mechanism. For example, the DaoAuthenticationProvider just needs a string-based username and password. Various authentication mechanisms result in the collection of a string-based username and password, including (but not limited to) BASIC and form authentication. Equally, some authentication mechanisms create an authentication request object which can only be interpreted by a single type of AuthenticationProvider. An example of this one-to-one mapping would be JA-SIG CAS, which uses the notion of a service ticket which can therefore only be authenticated by CasAuthenticationProvider. A further example of a one-to-one mapping would be the LDAP authentication mechanism, which can only be processed an the LdapAuthenticationProvider. The specifics of such relationships are detailed in the JavaDocs for each class, plus the authentication approach-specific chapters of this reference guide. You need not be terribly concerned about this implementation detail, because if you forget to register a suitable provider, you'll simply receive a ProviderNotFoundException when an attempt to authenticate is made. After configuring the correct authentication mechanisms in the FilterChainProxy, and ensuring that a corresponding AuthenticationProvider is registered in the ProviderManager, your last step is to configure an AuthenticationEntryPoint. Recall that earlier we discussed the role of ExceptionTranslationFilter, which is used when HTTP-based requests should receive back an HTTP header or HTTP redirect in order to start authentication. Continuing on with our earlier example: < value="false"/> ]]> Notice that the ExceptionTranslationFilter requires two collaborators. The first, AccessDeniedHandlerImpl, uses a RequestDispatcher forward to display the specified access denied error page. We use a forward so that the SecurityContextHolder still contains details of the principal, which may be useful for display to the user (in old releases of Spring Security we relied upon the servlet container to handle a 403 error message, which lacked this useful contextual information). AccessDeniedHandlerImpl will also set the HTTP header to 403, which is the official error code to indicate access denied. In the case of the AuthentionEntryPoint, here we're setting what action we would like taken when an unauthenticated principal attempts to perform a protected operation. Because in our example we're going to be using form-based authentication, we specify AuthenticationProcessinFilterEntryPoint and the URL of the login page. Your application will usually only have one entry point, and most authentication approaches define their own specific AuthenticationEntryPoint. Details of which entry point to use for each authentication approach is discussed in the authentication approach-specific chapters of this reference guide.
UserDetails and Associated Types As mentioned in the first part of the reference guide, most authentication providers take advantage of the UserDetails and UserDetailsService interfaces. The contract for this latter interface consists of a single method: UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException; The returned UserDetails is an interface that provides getters that guarantee non-null provision of basic authentication information such as the username, password, granted authorities and whether the user is enabled or disabled. Most authentication providers will use a UserDetailsService, even if the username and password are not actually used as part of the authentication decision. Generally such providers will be using the returned UserDetails object just for its GrantedAuthority[] information, because some other system (like LDAP or X509 or CAS etc) has undertaken the responsibility of actually validating the credentials. A single concrete implementation of UserDetails is provided with Spring Security, being the User class. Spring Security users will need to decide when writing their UserDetailsService what concrete UserDetails class to return. In most cases User will be used directly or subclassed, although special circumstances (such as object relational mappers) may require users to write their own UserDetails implementation from scratch. This is not such an unusual situation, and users should not hesitate to simply return their normal domain object that represents a user of the system. This is especially common given that UserDetails is often used to store additional principal-related properties (such as their telephone number and email address), so that they can be easily used by web views. Given UserDetailsService is so simple to implement, it should be easy for users to retrieve authentication information using a persistence strategy of their choice. Having said that, Spring Security does include a couple of useful base implementations, which we'll look at below.
In-Memory Authentication Whilst it is easy to use create a custom UserDetailsService implementation that extracts information from a persistence engine of choice, many applications do not require such complexity. This is particularly true if you're undertaking a rapid prototype or just starting integrating Spring Security, when you don't really want to spend time configuring databases or writing UserDetailsService implementations. For this sort of situation, a simple option is to use the user-service element from the security namespace: ]]> This also suppots the use of an external properties file: ]]> The properties file should contain entries in the form username=password,grantedAuthority[,grantedAuthority][,enabled|disabled] For example jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled bob=bobspassword,ROLE_USER,enabled
JDBC Authentication Spring Security also includes a UserDetailsService that can obtain authentication information from a JDBC data source. Internally Spring JDBC is used, so it avoids the complexity of a fully-featured object relational mapper (ORM) just to store user details. If your application does use an ORM tool, you might prefer to write a custom UserDetailsService to reuse the mapping files you've probably already created. Returning to JdbcDaoImpl, an example configuration is shown below: ]]> You can use different relational database management systems by modifying the DriverManagerDataSource shown above. You can also use a global data source obtained from JNDI, as per normal Spring options.
Default User Database Schema Irrespective of the database you are using and how a DataSource is obtained, a standard schema must be in place. The DDL for an HSQL database instance would be: CREATE TABLE users ( username VARCHAR(50) NOT NULL PRIMARY KEY, password VARCHAR(50) NOT NULL, enabled BIT NOT NULL ); CREATE TABLE authorities ( username VARCHAR(50) NOT NULL, authority VARCHAR(50) NOT NULL ); ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users foreign key (username) REFERENCES users(username); If the default schema is unsuitable for your needs, JdbcDaoImpl provides properties that allow customisation of the SQL statements. Please refer to the JavaDocs for details, but note that the class is not intended for complex custom subclasses. If you have a complex schema or would like a custom UserDetails implementation returned, you'd be better off writing your own UserDetailsService. The base implementation provided with Spring Security is intended for typical situations, rather than catering for all possible requirements.
Concurrent Session Handling Spring Security is able to prevent a principal from concurrently authenticating to the same application more than a specified number of times. Many ISVs take advantage of this to enforce licensing, whilst network administrators like this feature because it helps prevent people from sharing login names. You can, for example, stop user "Batman" from logging onto the web application from two different sessions. To use concurrent session support, you'll need to add the following to web.xml: <listener> <listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class> </listener> In addition, you will need to add the org.springframework.security.concurrent.ConcurrentSessionFilter to your FilterChainProxy. The ConcurrentSessionFilter requires two properties, sessionRegistry, which generally points to an instance of SessionRegistryImpl, and expiredUrl, which points to the page to display when a session has expired. The web.xml HttpSessionEventPublisher causes an ApplicationEvent to be published to the Spring ApplicationContext every time a HttpSession commences or terminates. This is critical, as it allows the SessionRegistryImpl to be notified when a session ends. You will also need to wire up the ConcurrentSessionControllerImpl and refer to it from your ProviderManager bean: ]]>
Authentication Tag Libraries AuthenticationTag is used to simply output a property of the current Authentication object to the web page. The following JSP fragment illustrates how to use the AuthenticationTag: <security:authentication property="principal.username"/> This tag would cause the principal's name to be output. Here we are assuming the Authentication.getPrincipal() is a UserDetails object, which is generally the case when using one of Spring Security's stadard AuthenticationProvider implementations.
spring-security-2.0.7.RELEASE/docs/reference/runas-auth-provider.xml0000644000000000000000000001406711766764657022224 0ustar Run-As Authentication Replacement
Overview The AbstractSecurityInterceptor is able to temporarily replace the Authentication object in the SecurityContext and SecurityContextHolder during the secure object callback phase. This only occurs if the original Authentication object was successfully processed by the AuthenticationManager and AccessDecisionManager. The RunAsManager will indicate the replacement Authentication object, if any, that should be used during the SecurityInterceptorCallback. By temporarily replacing the Authentication object during the secure object callback phase, the secured invocation will be able to call other objects which require different authentication and authorization credentials. It will also be able to perform any internal security checks for specific GrantedAuthority objects. Because Spring Security provides a number of helper classes that automatically configure remoting protocols based on the contents of the SecurityContextHolder, these run-as replacements are particularly useful when calling remote web services
Configuration A RunAsManager interface is provided by Spring Security: Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config); boolean supports(ConfigAttribute attribute); boolean supports(Class clazz); The first method returns the Authentication object that should replace the existing Authentication object for the duration of the method invocation. If the method returns null, it indicates no replacement should be made. The second method is used by the AbstractSecurityInterceptor as part of its startup validation of configuration attributes. The supports(Class) method is called by a security interceptor implementation to ensure the configured RunAsManager supports the type of secure object that the security interceptor will present. One concrete implementation of a RunAsManager is provided with Spring Security. The RunAsManagerImpl class returns a replacement RunAsUserToken if any ConfigAttribute starts with RUN_AS_. If any such ConfigAttribute is found, the replacement RunAsUserToken will contain the same principal, credentials and granted authorities as the original Authentication object, along with a new GrantedAuthorityImpl for each RUN_AS_ ConfigAttribute. Each new GrantedAuthorityImpl will be prefixed with ROLE_, followed by the RUN_AS ConfigAttribute. For example, a RUN_AS_SERVER will result in the replacement RunAsUserToken containing a ROLE_RUN_AS_SERVER granted authority. The replacement RunAsUserToken is just like any other Authentication object. It needs to be authenticated by the AuthenticationManager, probably via delegation to a suitable AuthenticationProvider. The RunAsImplAuthenticationProvider performs such authentication. It simply accepts as valid any RunAsUserToken presented. To ensure malicious code does not create a RunAsUserToken and present it for guaranteed acceptance by the RunAsImplAuthenticationProvider, the hash of a key is stored in all generated tokens. The RunAsManagerImpl and RunAsImplAuthenticationProvider is created in the bean context with the same key: ]]> By using the same key, each RunAsUserToken can be validated it was created by an approved RunAsManagerImpl. The RunAsUserToken is immutable after creation for security reasons
spring-security-2.0.7.RELEASE/docs/reference/classindex.pl0000755000000000000000000000465011766764657020255 0ustar #! /usr/bin/perl use strict; # Get list of links to class src packages system("curl http://static.springframework.org/spring-security/site/xref/allclasses-frame.html > allclasses-frame.html"); my @all_classes = `cat allclasses-frame.html`; $#all_classes > 0 || die "No lines in xref"; #AbstractAccessDecisionManager my %classnames_to_src; while ($_ = pop @all_classes) { next unless $_ =~ /(([a-zA-Z0-9_]+?))<\/a>/; $classnames_to_src{$2} = $1; } #my @docbook = glob("*.xml"); my @docbook; # Read the includes rather than using globbing to get the ordering right for the index. open MAINDOC, ") { if (/href="(.*\.xml)"/) { push @docbook, $1; } } # Hash of xml:id (i.e. anchor) to filename.html#anchor my %id_to_html; my %class_index; # Build map of html pages links while (my $file = pop @docbook) { open FILE, $file or die "$!"; print "\nProcessing: $file\n\n"; my $file_id; while() { if (/.* xml:id="([a-z0-9-]+?)"/) { $file_id = $1; last; } } $id_to_html{$file_id} = "$file_id.html#$file_id"; while () { next unless /.* xml:id="([a-z0-9-]+?)"/; print "$1\n"; $id_to_html{$1} = "$file_id.html#$1"; } close FILE; } # Get the list of class/interface names and their section ids/titles my @class_references = split /;/,`xsltproc --xinclude index-classes.xsl springsecurity.xml`; # Get unique values my %seen = (); @class_references = grep { !$seen{$_}++} @class_references; print "\nThere are $#class_references references to classes and interfaces.\n"; my %id_to_title; my %classnames_to_ids = (); foreach my $class_id_title (@class_references) { (my $class, my $id, my $title) = split /:/, $class_id_title; $title =~ s//>/; $id_to_title{$id} = $title; push( @{$classnames_to_ids{$class}}, $id ); } open INDEX, ">classindex.xml" || die "Couldn't open output file\n"; print INDEX "\n"; foreach my $class (sort keys %classnames_to_ids) { print INDEX "\n"; foreach my $id (@{$classnames_to_ids{$class}}) { print INDEX " \n"; } print INDEX "\n" } print INDEX "\n"; close INDEX; spring-security-2.0.7.RELEASE/docs/reference/introduction.xml0000644000000000000000000003361511766764657021026 0ustar Introduction What is Spring Security? Spring Security provides comprehensive security services for J2EE-based enterprise software applications. There is a particular emphasis on supporting projects built using The Spring Framework, which is the leading J2EE solution for enterprise software development. If you're not using Spring for developing enterprise applications, we warmly encourage you to take a closer look at it. Some familiarity with Spring - and in particular dependency injection principles - will help you get up to speed with Spring Security more easily. People use Spring Security for many reasons, but most are drawn to the project after finding the security features of J2EE's Servlet Specification or EJB Specification lack the depth required for typical enterprise application scenarios. Whilst mentioning these standards, it's important to recognise that they are not portable at a WAR or EAR level. Therefore, if you switch server environments, it is typically a lot of work to reconfigure your application's security in the new target environment. Using Spring Security overcomes these problems, and also brings you dozens of other useful, entirely customisable security features. As you probably know, security comprises two major operations. The first is known as "authentication", which is the process of establishing a principal is who they claim to be. A "principal" generally means a user, device or some other system which can perform an action in your application. "Authorization" refers to the process of deciding whether a principal is allowed to perform an action in your application. To arrive at the point where an authorization decision is needed, the identity of the principal has already been established by the authentication process. These concepts are common, and not at all specific to Spring Security. At an authentication level, Spring Security supports a wide range of authentication models. Most of these authentication models are either provided by third parties, or are developed by relevant standards bodies such as the Internet Engineering Task Force. In addition, Spring Security provides its own set of authentication features. Specifically, Spring Security currently supports authentication integration with all of these technologies: HTTP BASIC authentication headers (an IEFT RFC-based standard) HTTP Digest authentication headers (an IEFT RFC-based standard) HTTP X.509 client certificate exchange (an IEFT RFC-based standard) LDAP (a very common approach to cross-platform authentication needs, especially in large environments) Form-based authentication (for simple user interface needs) OpenID authentication Computer Associates Siteminder JA-SIG Central Authentication Service (otherwise known as CAS, which is a popular open source single sign on system) Transparent authentication context propagation for Remote Method Invocation (RMI) and HttpInvoker (a Spring remoting protocol) Automatic "remember-me" authentication (so you can tick a box to avoid re-authentication for a predetermined period of time) Anonymous authentication (allowing every call to automatically assume a particular security identity) Run-as authentication (which is useful if one call should proceed with a different security identity) Java Authentication and Authorization Service (JAAS) Container integration with JBoss, Jetty, Resin and Tomcat (so you can still use Container Manager Authentication if desired) Java Open Source Single Sign On (JOSSO) * OpenNMS Network Management Platform * AppFuse * AndroMDA * Mule ESB * Direct Web Request (DWR) * Grails * Tapestry * JTrac * Jasypt * Roller * Elastic Plath * Atlassian Crowd * Your own authentication systems (see below) (* Denotes provided by a third party; check our integration page for links to the latest details) Many independent software vendors (ISVs) adopt Spring Security because of this significant choice of flexible authentication models. Doing so allows them to quickly integrate their solutions with whatever their end clients need, without undertaking a lot of engineering or requiring the client to change their environment. If none of the above authentication mechanisms suit your needs, Spring Security is an open platform and it is quite simple to write your own authentication mechanism. Many corporate users of Spring Security need to integrate with "legacy" systems that don't follow any particular security standards, and Spring Security is happy to "play nicely" with such systems. Sometimes the mere process of authentication isn't enough. Sometimes you need to also differentiate security based on the way a principal is interacting with your application. For example, you might want to ensure requests only arrive over HTTPS, in order to protect passwords from eavesdropping or end users from man-in-the-middle attacks. Or, you might want to ensure that an actual human being is making the requests and not some robot or other automated process. This is especially helpful to protect password recovery processes from brute force attacks, or simply to make it harder for people to duplicate your application's key content. To help you achieve these goals, Spring Security fully supports automatic "channel security", together with JCaptcha integration for human user detection. Irrespective of how authentication was undertaken, Spring Security provides a deep set of authorization capabilities. There are three main areas of interest in respect of authorization, these being authorizing web requests, authorizing methods can be invoked, and authorizing access to individual domain object instances. To help you understand the differences, consider the authorization capabilities found in the Servlet Specification web pattern security, EJB Container Managed Security and file system security respectively. Spring Security provides deep capabilities in all of these important areas, which we'll explore later in this reference guide. History Spring Security began in late 2003 as "The Acegi Security System for Spring". A question was posed on the Spring Developers' mailing list asking whether there had been any consideration given to a Spring-based security implementation. At the time the Spring community was relatively small (especially by today's size!), and indeed Spring itself had only existed as a SourceForge project from early 2003. The response to the question was that it was a worthwhile area, although a lack of time currently prevented its exploration. With that in mind, a simple security implementation was built and not released. A few weeks later another member of the Spring community inquired about security, and at the time this code was offered to them. Several other requests followed, and by January 2004 around twenty people were using the code. These pioneering users were joined by others who suggested a SourceForge project was in order, which was duly established in March 2004. In those early days, the project didn't have any of its own authentication modules. Container Managed Security was relied upon for the authentication process, with Acegi Security instead focusing on authorization. This was suitable at first, but as more and more users requested additional container support, the fundamental limitation of container-specific authentication realm interfaces was experienced. There was also a related issue of adding new JARs to the container's classpath, which was a common source of end user confusion and misconfiguration. Acegi Security-specific authentication services were subsequently introduced. Around a year later, Acegi Security became an official Spring Framework subproject. The 1.0.0 final release was published in May 2006 - after more than two and a half years of active use in numerous production software projects and many hundreds of improvements and community contributions. Acegi Security became an official Spring Portfolio project towards the end of 2007 and was rebranded as "Spring Security". Today Spring Security enjoys a strong and active open source community. There are thousands of messages about Spring Security on the support forums. There is an active core of developers work who work on the code itself and an active community which also regularly share patches and support their peers. Release Numbering It is useful to understand how Spring Security release numbers work, as it will help you identify the effort (or lack thereof) involved in migrating to future releases of the project. Officially, we use the Apache Portable Runtime Project versioning guidelines, which can be viewed at http://apr.apache.org/versioning.html. We quote the introduction contained on that page for your convenience: Versions are denoted using a standard triplet of integers: MAJOR.MINOR.PATCH. The basic intent is that MAJOR versions are incompatible, large-scale upgrades of the API. MINOR versions retain source and binary compatibility with older minor versions, and changes in the PATCH level are perfectly compatible, forwards and backwards. Getting the Source Since Spring Security is an Open Source project, we'd strongly encourage you to check out the source code using subversion. This will give you full access to all the sample applications and you can build the most up to date version of the project easily. Having the source for a project is also a huge help in debugging. Exception stack traces are no longer obscure black-box issues but you can get straight to the line that's causing the problem and work out what's happening. The source is the ultimate documentation for a project and often the simplest place to find out how something actually works. To obtain the source for the project trunk, use the following subversion command: svn checkout http://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/trunk/ You can checkout specific versions from http://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/. spring-security-2.0.7.RELEASE/docs/reference/remember-me-authentication.xml0000644000000000000000000002617011766764657023515 0ustar Remember-Me Authentication
Overview Remember-me or persistent-login authentication refers to web sites being able to remember the identity of a principal between sessions. This is typically accomplished by sending a cookie to the browser, with the cookie being detected during future sessions and causing automated login to take place. Spring Security provides the necessary hooks for these operations to take place, and has two concrete remember-me implementations. One uses hashing to preserve the security of cookie-based tokens and the other uses a database or other persistent storage mechanism to store the generated tokens. Note that both implemementations require a UserDetailsService. If you are using an authentication provider which doesn't use a UserDetailsService (for example, the LDAP provider) then it won't work unless you also have a UserDetailsService bean in your application context.
Simple Hash-Based Token Approach This approach uses hashing to achieve a useful remember-me strategy. In essence a cookie is sent to the browser upon successful interactive authentication, with the cookie being composed as follows: base64(username + ":" + expirationTime + ":" + md5Hex(username + ":" + expirationTime + ":" password + ":" + key)) username: As identifiable to the UserDetailsService password: That matches the one in the retrieved UserDetails expirationTime: The date and time when the remember-me token expires, expressed in milliseconds key: A private key to prevent modification of the remember-me token As such the remember-me token is valid only for the period specified, and provided that the username, password and key does not change. Notably, this has a potential security issue in that a captured remember-me token will be usable from any user agent until such time as the token expires. This is the same issue as with digest authentication. If a principal is aware a token has been captured, they can easily change their password and immediately invalidate all remember-me tokens on issue. If more significant security is needed you should use the approach described in the next section. Alternatively remember-me services should simply not be used at all. If you are familiar with the topics discussed in the chapter on namespace configuration, you can enable remember-me authentication just by adding the <remember-me> element: ... ]]> It is automatically enabled for you if you are using the auto-config setting. The UserDetailsService will normally be selected automatically. If you have more than one in your application context, you need to specify which one should be used with the user-service-ref attribute, where the value is the name of your UserDetailsService bean.
Persistent Token Approach This approach is based on the article http://jaspan.com/improved_persistent_login_cookie_best_practice with some minor modifications Essentially, the username is not included in the cookie, to prevent exposing a valid login name unecessarily. There is a discussion on this in the comments section of this article.. To use the this approach with namespace configuration, you would supply a datasource reference: ... ]]> The database should contain a persistent_logins table, created using the following SQL (or equivalent): create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, token varchar(64) not null, last_used timestamp not null)
Remember-Me Interfaces and Implementations Remember-me authentication is not used with basic authentication, given it is often not used with HttpSessions. Remember-me is used with AuthenticationProcessingFilter, and is implemented via hooks in the AbstractProcessingFilter superclass. The hooks will invoke a concrete RememberMeServices at the appropriate times. The interface looks like this: Authentication autoLogin(HttpServletRequest request, HttpServletResponse response); void loginFail(HttpServletRequest request, HttpServletResponse response); void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication); Please refer to the JavaDocs for a fuller discussion on what the methods do, although note at this stage that AbstractProcessingFilter only calls the loginFail() and loginSuccess() methods. The autoLogin() method is called by RememberMeProcessingFilter whenever the SecurityContextHolder does not contain an Authentication. This interface therefore provides the underlying remember-me implementation with sufficient notification of authentication-related events, and delegates to the implementation whenever a candidate web request might contain a cookie and wish to be remembered. This design allows any number of remember-me implementation strategies. We've seen above that Spring Security provides two implementations. We'll look at thes in turn.
TokenBasedRememberMeServices This implementation supports the simpler approach described in . TokenBasedRememberMeServices generates a RememberMeAuthenticationToken, which is processed by RememberMeAuthenticationProvider. A key is shared between this authentication provider and the TokenBasedRememberMeServices. In addition, TokenBasedRememberMeServices requires A UserDetailsService from which it can retrieve the username and password for signature comparison purposes, and generate the RememberMeAuthenticationToken to contain the correct GrantedAuthority[]s. Some sort of logout command should be provided by the application that invalidates the cookie if the user requests this. TokenBasedRememberMeServices also implements Spring Security's LogoutHandler interface so can be used with LogoutFilter to have the cookie cleared automatically. The beans required in an application context to enable remember-me services are as follows: ]]> Don't forget to add your RememberMeServices implementation to your AuthenticationProcessingFilter.setRememberMeServices() property, include the RememberMeAuthenticationProvider in your AuthenticationManager.setProviders() list, and add RememberMeProcessingFilter into your FilterChainProxy (typically immediately after your AuthenticationProcessingFilter).
PersistentTokenBasedRememberMeServices This class can be used in the same way as TokenBasedRememberMeServices, but it additionally needs to be configured with a PersistentTokenRepository to store the tokens. There are two standard implementations. InMemoryTokenRepositoryImpl which is intended for testing only. JdbcTokenRepositoryImpl which stores the tokens in a database. The database schema is described above in .
spring-security-2.0.7.RELEASE/docs/reference/basic-authentication.xml0000644000000000000000000000636311766764657022403 0ustar BASIC Authentication Mechanism
Overview Spring Security provides a BasicProcessingFilter which is capable of processing basic authentication credentials presented in HTTP headers. This can be used for authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as well as normal user agents (such as Internet Explorer and Navigator). The standard governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and the BasicProcessingFilter conforms with this RFC. Basic Authentication is an attractive approach to authentication, because it is very widely deployed in user agents and implementation is extremely simple (it's just a Base64 encoding of the username:password, specified in an HTTP header).
Configuration To implement HTTP Basic Authentication, it is necessary to define BasicProcessingFilter in the filter chain. The application context will need to define the BasicProcessingFilter and its required collaborator: <bean id="basicProcessingFilter" class="org.springframework.security.ui.basicauth.BasicProcessingFilter"> <property name="authenticationManager"><ref bean="authenticationManager"/></property> <property name="authenticationEntryPoint"><ref bean="authenticationEntryPoint"/></property> </bean> <bean id="authenticationEntryPoint" class="org.springframework.security.ui.basicauth.BasicProcessingFilterEntryPoint"> <property name="realmName"><value>Name Of Your Realm</value></property> </bean> The configured AuthenticationManager processes each authentication request. If authentication fails, the configured AuthenticationEntryPoint will be used to retry the authentication process. Usually you will use the BasicProcessingFilterEntryPoint, which returns a 401 response with a suitable header to retry HTTP Basic authentication. If authentication is successful, the resulting Authentication object will be placed into the SecurityContextHolder. If the authentication event was successful, or authentication was not attempted because the HTTP header did not contain a supported authentication request, the filter chain will continue as normal. The only time the filter chain will be interrupted is if authentication fails and the AuthenticationEntryPoint is called, as discussed in the previous paragraph
spring-security-2.0.7.RELEASE/docs/reference/supporting-infrastructure.xml0000644000000000000000000004274611766764657023602 0ustar Supporting Infrastructure This chapter introduces some of the supplementary and supporting infrastructure used by Spring Security. If a capability is not directly related to security, yet included in the Spring Security project, we will discuss it in this chapter.
Localization Spring Security supports localization of exception messages that end users are likely to see. If your application is designed for English users, you don't need to do anything as by default all Security Security messages are in English. If you need to support other locales, everything you need to know is contained in this section. All exception messages can be localized, including messages related to authentication failures and access being denied (authorization failures). Exceptions and logging that is focused on developers or system deployers (including incorrect attributes, interface contract violations, using incorrect constructors, startup time validation, debug-level logging) etc are not localized and instead are hard-coded in English within Spring Security's code. Shipping in the spring-security-core-xx.jar you will find an org.springframework.security package that in turn contains a messages.properties file. This should be referred to by your ApplicationContext, as Spring Security classes implement Spring's MessageSourceAware interface and expect the message resolver to be dependency injected at application context startup time. Usually all you need to do is register a bean inside your application context to refer to the messages. An example is shown below: ]]> The messages.properties is named in accordance with standard resource bundles and represents the default language supported by Spring Security messages. This default file is in English. If you do not register a message source, Spring Security will still work correctly and fallback to hard-coded English versions of the messages. If you wish to customize the messages.properties file, or support other languages, you should copy the file, rename it accordingly, and register it inside the above bean definition. There are not a large number of message keys inside this file, so localization should not be considered a major initiative. If you do perform localization of this file, please consider sharing your work with the community by logging a JIRA task and attaching your appropriately-named localized version of messages.properties. Rounding out the discussion on localization is the Spring ThreadLocal known as org.springframework.context.i18n.LocaleContextHolder. You should set the LocaleContextHolder to represent the preferred Locale of each user. Spring Security will attempt to locate a message from the message source using the Locale obtained from this ThreadLocal. Please refer to Spring documentation for further details on using LocaleContextHolder and the helper classes that can automatically set it for you (eg AcceptHeaderLocaleResolver, CookieLocaleResolver, FixedLocaleResolver, SessionLocaleResolver etc)
Filters Spring Security uses many filters, as referred to throughout the remainder of this reference guide. If you are using namespace configuration, then the you don't usually have to declare the filter beans explicitly. There may be times when you want full control over the security filter chain, either because you are using features which aren't supported in the namespace, or you are using your own customized versions of classes. In this case, you have a choice in how these filters are added to your web application, in that you can use either Spring's DelegatingFilterProxy or FilterChainProxy. We'll look at both below. When using DelegatingFilterProxy, you will see something like this in the web.xml file: <filter> <filter-name>myFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> Notice that the filter is actually a DelegatingFilterProxy, and not the filter that will actually implement the logic of the filter. What DelegatingFilterProxy does is delegate the Filter's methods through to a bean which is obtained from the Spring application context. This enables the bean to benefit from the Spring web application context lifecycle support and configuration flexibility. The bean must implement javax.servlet.Filter and it must have the same name as that in the filter-name element. There is a lifecycle issue to consider when hosting Filters in an IoC container instead of a servlet container. Specifically, which container should be responsible for calling the Filter's "startup" and "shutdown" methods? It is noted that the order of initialization and destruction of a Filter can vary by servlet container, and this can cause problems if one Filter depends on configuration settings established by an earlier initialized Filter. The Spring IoC container on the other hand has more comprehensive lifecycle/IoC interfaces (such as InitializingBean, DisposableBean, BeanNameAware, ApplicationContextAware and many others) as well as a well-understood interface contract, predictable method invocation ordering, autowiring support, and even options to avoid implementing Spring interfaces (eg the destroy-method attribute in Spring XML). For this reason we recommend the use of Spring lifecycle services instead of servlet container lifecycle services wherever possible. Read the Javadoc for DelegatingFilterProxy for more information Rather than using DelegatingFilterProxy, we strongly recommend that you use FilterChainProxy instead. Whilst DelegatingFilterProxy is a very useful class, the problem is that the number of lines of code required for <filter> and <filter-mapping> entries in web.xml explodes when using more than a few filters. To overcome this issue, Spring Security provides a FilterChainProxy class. It is wired using a DelegatingFilterProxy (just like in the example above), but the target class is org.springframework.security.util.FilterChainProxy. The filter chain is then declared in the application context, using code such as this: ]]> You may notice similarities with the way FilterSecurityInterceptor is declared. Both regular expressions and Ant Paths are supported, and the most specific URIs appear first. At runtime the FilterChainProxy will locate the first URI pattern that matches the current web request and the list of filter beans specified by the filters attribute will be applied to that request. The filters will be invoked in the order they are defined, so you have complete control over the filter chain which is applied to a particular URL. You may have noticed we have declared two HttpSessionContextIntegrationFilters in the filter chain (ASC is short for allowSessionCreation, a property of HttpSessionContextIntegrationFilter). As web services will never present a jsessionid on future requests, creating HttpSessions for such user agents would be wasteful. If you had a high-volume application which required maximum scalability, we recommend you use the approach shown above. For smaller applications, using a single HttpSessionContextIntegrationFilter (with its default allowSessionCreation as true) would likely be sufficient. In relation to lifecycle issues, the FilterChainProxy will always delegate init(FilterConfig) and destroy() methods through to the underlaying Filters if such methods are called against FilterChainProxy itself. In this case, FilterChainProxy guarantees to only initialize and destroy each Filter once, irrespective of how many times it is declared by the FilterInvocationDefinitionSource. You control the overall choice as to whether these methods are called or not via the targetFilterLifecycle initialization parameter of the DelegatingFilterProxy that proxies DelegatingFilterProxy. As discussed above, by default any servlet container lifecycle invocations are not delegated through to DelegatingFilterProxy. You can use the attribute filters = "none" in the same way that you do when using namespace configuration to build the FilterChainProxy. This will omit the request pattern from the security filter chain entirely. Note that anything matching this path will then have no authentication or authorization services applied and will be freely accessible. The order that filters are defined in web.xml is very important. Irrespective of which filters you are actually using, the order of the <filter-mapping>s should be as follows: ChannelProcessingFilter, because it might need to redirect to a different protocol ConcurrentSessionFilter, because it doesn't use any SecurityContextHolder functionality but needs to update the SessionRegistry to reflect ongoing requests from the principal HttpSessionContextIntegrationFilter, so a SecurityContext can be setup in the SecurityContextHolder at the beginning of a web request, and any changes to the SecurityContext can be copied to the HttpSession when the web request ends (ready for use with the next web request) Authentication processing mechanisms - AuthenticationProcessingFilter, CasProcessingFilter, BasicProcessingFilter, HttpRequestIntegrationFilter, JbossIntegrationFilter etc - so that the SecurityContextHolder can be modified to contain a valid Authentication request token The SecurityContextHolderAwareRequestFilter, if you are using it to install a Spring Security aware HttpServletRequestWrapper into your servlet container RememberMeProcessingFilter, so that if no earlier authentication processing mechanism updated the SecurityContextHolder, and the request presents a cookie that enables remember-me services to take place, a suitable remembered Authentication object will be put there AnonymousProcessingFilter, so that if no earlier authentication processing mechanism updated the SecurityContextHolder, an anonymous Authentication object will be put there ExceptionTranslationFilter, to catch any Spring Security exceptions so that either an HTTP error response can be returned or an appropriate AuthenticationEntryPoint can be launched FilterSecurityInterceptor, to protect web URIs All of the above filters use DelegatingFilterProxy or FilterChainProxy. It is recommended that a single DelegatingFilterProxy proxy through to a single FilterChainProxy for each application, with that FilterChainProxy defining all of Spring Security filters. If you're using SiteMesh, ensure Spring Security filters execute before the SiteMesh filters are called. This enables the SecurityContextHolder to be populated in time for use by SiteMesh decorators
Tag Libraries Spring Security comes bundled with several JSP tag libraries which provide a range of different services.
Configuration All taglib classes are included in the core spring-security-xx.jar file, with the security.tld located in the JAR's META-INF directory. This means for JSP 1.2+ web containers you can simply include the JAR in the WAR's WEB-INF/lib directory and it will be available. If you're using a JSP 1.1 container, you'll need to declare the JSP taglib in your web.xml file, and include security.tld in the WEB-INF/lib directory. The following fragment is added to web.xml: http://www.springframework.org/security/tags /WEB-INF/security.tld ]]>
Usage Now that you've configured the tag libraries, refer to the individual reference guide sections for details on how to use them. Note that when using the tags, you should include the taglib reference in your JSP: <%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %>
spring-security-2.0.7.RELEASE/docs/reference/resources/0000755000000000000000000000000011766764657017565 5ustar spring-security-2.0.7.RELEASE/docs/reference/resources/css/0000755000000000000000000000000011766764657020355 5ustar spring-security-2.0.7.RELEASE/docs/reference/resources/css/html.css0000644000000000000000000001152011766764657022032 0ustar body { text-align: justify; margin-right: 2em; margin-left: 2em; } a, a[accesskey^="h"], a[accesskey^="n"], a[accesskey^="u"], a[accesskey^="p"] { font-family: Verdana, Arial, helvetica, sans-serif; font-size: 12px; color: #003399; } a:active { color: #003399; } a:visited { color: #888888; } p { font-family: Verdana, Arial, sans-serif; } dt { font-family: Verdana, Arial, sans-serif; font-size: 12px; } p, dl, dt, dd, blockquote { color: #000000; margin-bottom: 3px; margin-top: 3px; padding-top: 0; } ol, ul, p { margin-top: 6px; margin-bottom: 6px; } p, blockquote { font-size: 90%; } p.releaseinfo { font-size: 100%; font-weight: bold; font-family: Verdana, Arial, helvetica, sans-serif; padding-top: 10px; } p.pubdate { font-size: 120%; font-weight: bold; font-family: Verdana, Arial, helvetica, sans-serif; } td { font-size: 80%; } td, th, span { color: #000000; } td[width^="40%"] { font-family: Verdana, Arial, helvetica, sans-serif; font-size: 12px; color: #003399; } table[summary^="Navigation header"] tbody tr th[colspan^="3"] { font-family: Verdana, Arial, helvetica, sans-serif; } blockquote { margin-right: 0; } h1, h2, h3, h4, h6 { color: #000000; font-weight: 500; margin-top: 0; padding-top: 14px; font-family: Verdana, Arial, helvetica, sans-serif; margin-bottom: 0; } h2.title { font-weight: 800; margin-bottom: 8px; } h2.subtitle { font-weight: 800; margin-bottom: 20px; } .firstname, .surname { font-size: 12px; font-family: Verdana, Arial, helvetica, sans-serif; } table { border-collapse: collapse; border-spacing: 0; border: 1px black; empty-cells: hide; margin: 10px 0 30px 50px; width: 90%; } div.table { margin: 30px 0 10px 0; border: 1px dashed gray; padding: 10px; } div .table-contents table { border: 1px solid black; } div.table > p.title { padding-left: 10px; } table[summary^="Navigation footer"] { border-collapse: collapse; border-spacing: 0; border: 1px black; empty-cells: hide; margin: 0px; width: 100%; } table[summary^="Note"], table[summary^="Warning"], table[summary^="Tip"] { border-collapse: collapse; border-spacing: 0; border: 1px black; empty-cells: hide; margin: 10px 0px 10px -20px; width: 100%; } td { padding: 4pt; font-family: Verdana, Arial, helvetica, sans-serif; } div.warning TD { text-align: justify; } h1 { font-size: 150%; } h2 { font-size: 110%; } h3 { font-size: 100%; font-weight: bold; } h4 { font-size: 90%; font-weight: bold; } h5 { font-size: 90%; font-style: italic; } h6 { font-size: 100%; font-style: italic; } tt { font-size: 110%; font-family: "Courier New", Courier, monospace; color: #000000; } .navheader, .navfooter { border: none; } div.navfooter table { border-style: dashed; border-color: gray; border-width: 1px 1px 1px 1px; background-color: #cde48d; } pre { font-size: 110%; padding: 5px; border-style: solid; border-width: 1px; border-color: #CCCCCC; background-color: #f3f5e9; } ul, ol, li { list-style: disc; } hr { width: 100%; height: 1px; background-color: #CCCCCC; border-width: 0; padding: 0; } .variablelist { padding-top: 10px; padding-bottom: 10px; margin: 0; } .term { font-weight:bold; } .mediaobject { padding-top: 30px; padding-bottom: 30px; } .legalnotice { font-family: Verdana, Arial, helvetica, sans-serif; font-size: 12px; font-style: italic; } .sidebar { float: right; margin: 10px 0 10px 30px; padding: 10px 20px 20px 20px; width: 33%; border: 1px solid black; background-color: #F4F4F4; font-size: 14px; } .property { font-family: "Courier New", Courier, monospace; } a code { font-family: Verdana, Arial, monospace; font-size: 12px; } td code { font-size: 110%; } div.note * td, div.tip * td, div.warning * td, div.calloutlist * td { text-align: justify; font-size: 100%; } .programlisting { clear: both; } .programlisting .interfacename, .programlisting .literal, .programlisting .classname { font-size: 95%; } .title .interfacename, .title .literal, .title .classname { font-size: 130%; } /* everything in a is displayed in a coloured, comment-like font */ .programlisting * .lineannotation, .programlisting * .lineannotation * { color: green; } .question * p { font-size: 100%; } .answer * p { font-size: 100%; } spring-security-2.0.7.RELEASE/docs/reference/resources/xsl/0000755000000000000000000000000011766764657020373 5ustar spring-security-2.0.7.RELEASE/docs/reference/resources/xsl/html.xsl0000644000000000000000000000643111766764657022073 0ustar html.css 1 0 1 0 book toc 3 1 0 90 0 figure after example before equation before table before procedure before ,

Authors

spring-security-2.0.7.RELEASE/docs/reference/resources/xsl/fopdf.xsl0000644000000000000000000004431711766764657022232 0ustar Copyright © 2005-2007 , -5em -5em Spring Security ( ) 1 0 1 1 book toc 2 0 0 0 5mm 10mm 10mm 15mm 10mm 0mm 18mm 18mm 0pc justify false 11 8 1.4 0.8em 17.4cm 4pt 4pt 4pt 4pt 0.1pt 0.1pt 1 left bold pt 0.8em 0.8em 0.8em pt 0.1em 0.1em 0.1em 0.6em 0.6em 0.6em pt 0.1em 0.1em 0.1em 0.4em 0.4em 0.4em pt 0.1em 0.1em 0.1em bold pt false 0.4em 0.6em 0.8em pt 1em 1em 1em #444444 solid 0.1pt 0.5em 0.5em 0.5em 0.5em 0.5em 0.5em 1 #F0F0F0 0 1 90 '1' figure after example before equation before table before procedure before 1 0.8em 0.8em 0.8em 0.1em 0.1em 0.1em spring-security-2.0.7.RELEASE/docs/reference/resources/xsl/html_chunk.xsl0000644000000000000000000002674311766764657023273 0ustar '5' '1' 1 0 1 0 book toc 3 1 1 90 figure after example before equation before table before procedure before ,

Authors

1 spring-security-2.0.7.RELEASE/docs/reference/resources/images/0000755000000000000000000000000011766764657021032 5ustar spring-security-2.0.7.RELEASE/docs/reference/resources/images/logo.psd0000644000000000000000000044444111766764657022515 0ustar 8BPSØ_p8BIM8BIM%F ò‰&¸VÚ°œ¡°§w8BIM$9* adobe:docid:photoshop:0b6d4620-6bf5-11d8-aaca-e11f1c24aa3c uuid:D3B1161F093FDA11959FA8C7E0814291 1 720000/10000 720000/10000 2 256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;E4133D96ADD83760E18B816286BD8936 2005-10-17T22:27:16+10:00 Adobe Photoshop CS2 Windows 2005-08-31T17:07:02+10:00 2005-10-17T22:27:16+10:00 -1 216 144 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;FE2BB70CD0FD129C7AEDFBAD4E7CFDA3 application/vnd.adobe.photoshop 3 8BIMíHH8BIM&?€8BIM 8BIM8BIMó 8BIM 8BIM' 8BIMõH/fflff/ff¡™š2Z5-8BIMøpÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿè8BIM8BIM 8BIM08BIM- 8BIM@@8BIM8BIMönullbaseNameTEXTUserboundsObjcRct1Top longLeftlongBtomlongRghtlongØslicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlongRghtlongØurlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?ð8BIM8BIM 8BIM Ë kàÈ ¯ÿØÿàJFIFHHÿí Adobe_CMÿîAdobed€ÿÛ„            ÿÀk "ÿÝ ÿÄ?   3!1AQa"q2‘¡±B#$RÁb34r‚ÑC%’Sðáñcs5¢²ƒ&D“TdE£t6ÒUâeò³„ÃÓuãóF'”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷5!1AQaq"2‘¡±B#ÁRÑð3$bár‚’CScs4ñ%¢²ƒ&5ÂÒD“T£dEU6teâò³„ÃÓuãóF”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö'7GWgw‡—§·ÇÿÚ ?õT’I%)$’IJI$’R’I$”¤’I%)$’IJI$’R’I$”¤’I%)$’IOÿÐõT’I%)$’IJI$+ò+ǯ{ü@kF¤“£ZÖþó’&µ*J’ä³>¹°õ+ún9±¶c{m²Š”=^]ˆS›[n«ü7»ÓªÏÑ*¹_ZzÇK}Ydeôû õÜqŽ=øãÛ²ÀÍöQWÓßSY]õ¤Qœ ŠxKÛ¤ªcæ=µÙØ7WcxpVÓã E„)$’EJI$’R’I$”¤’I%)$’IOÿÑõT’I%)$’IKW™Ö3zïÖtΓk™^1Úü†pÑ/«*ö:?ž±í·ýUu ïÒz¸+[ë—\wMé®exȼ9Œu@¹ìnºêƒÃþ’¼l?û½•ê~‹ÔAúƒÐLé?h½™Y‘cØÙ!Œ€ÊifíÎôë©•×_üu¦ïü¾Ò—o¥tŒ•ŒÜ|:›[Z –ˆ%[±•ØÇ2Ƈ±Â×AIRê¹tcbXûìô©cfEŸ»Kë§ï7ØÄtdnó¹o«­ý[èØî;Úë³nÔîn5UÝ^3-ýæ[¿gõè]¢á>¡ãßÖ³ó¾¸f´Öî ïK£þ“µÿ…º¦~gý¦ºÏðë±ê=O§ô¼´õ Šñ©Ðû Kæ3óžÿä1 p }4I=[I,Ú~±ô°,ê5gÒì:Hm·o¬.!Œm³üÞç9¿MKëCÍeÏÅÏ¢æc7}ïmÚÆëï±ÓµŒö©8'¯¤é¡Ñè$³zoÖN…Õnu?:œ‹š$Ö×{ ~{ZèsÙü¶!ÿο«^ƒ²?icú5¼Vû=A´=Áïedþó›UŸæ%íÎë†V<;ªÝG¸1Žy˜h$À$Àðk}Î\/L¿ëf.Fn{°²E½cüŒz®>£+ɯ}Ý>ƒ[êMvDz»ý?W&•Óßõ«êÞ=¾ýK«k¶¾ÆƒµíÖí~·µè¹¢cUuùÔ2¬¹û5†Æí²"}'ƒµÿMªHqDíñq÷§«Ò«Ìæu.¾Ìc…—›m6>Ñ•›~®ê­muz5X7?쎽׹ïf ¿¤ýSí©²:ßÖ*z–r/²¡~V ©¸ín=•][œ÷:ö;2Œ¯_×oÙ¬uãÒÏæþ« ·ëoÕŠl}VõLfY[‹ÇXÐCšv½®þ«”YÔ~©ÛŸnc-Ãv~5µÙ3ÖeZ}W]¯£éZÏÎú'‰VøzÑïþ ¾«}QfM}­É¤ãÛëä“Yg¥¡¾ã[½8oóŒ÷îüõ´…‡Ô1Û•…s21ÞHmµ™iÚv;k¿’àŽ ™&R$Q$è—ÿÒõT’Q{ÚÆ»€’–²ÆV%ܞ䬣õ§άÞÓc®™{›.mCygó¤~ÏÒ:•ÌýnúË‘”çâaZYîm·V`ÚZv¾ª.­Û™K÷Óçßèÿ™¯ôÜ—©ì 4}ðÿ%I² '†?óš™ùÈã—Rö}ÿ¦MûEéÓÓqªþ†¡ è[Võ8•aâUSUÖÆ±• CÐ]Mÿ‹cv.Oücô^¥^PÁ§íC§¹î·7×zoßé†gè};ªgé};h¹®ÿVsúÓprºkØ2úu†ÆWc‹ZðKôÙô^×ÒÅ7-!±6#¾§mvxöÙв~ªuüîëQ™‘f+³0¬sMUƒ”Û)8^•u~­úKj¯wé*ôý?뎳Ž~¢fŠú{ñnœFßœö̰o{‡¢ãí{hs=ûÅQþ°ß…Öò2¾Ï_Pêî©ÌÇcϦݹ ͼ¾Í‡oüóŠÆ/Õ/­W}^Éè9÷b³•Özqas¶Ù]ž»…Î cöXßÑï÷ìýÅxåÆ6˜Ó,%¬¿Dmûü+hþ ^‰ÐgPúµÕñ¯ÄÅmx”›¨s¶dZò2u­­­ý/¬Ë6ï{½û!ÿ¬Îwþœ)ÿÏë·èSzóºßMÏë Ç¢žC1鸽ö Å¢Þݬ÷_¾Çÿ#ù¥›øºúÈý.‡c;§äd Æ[œàö†¶êkÝNßôY/ÜÏôŸáQ†h rDü§éÊ\<_¤ª=œ®ªà߬ŒrÇìúǤ0N @dû§ú'ôßÈPϯÑú­õx¶æÝ»#)ãa'a/©Þ“·„c¿œþZë2¾¤õsõ‹#7Òp݆üZKÞE…Çì5ï`¯oóÃ÷Õ¾ }bCé¸-û?¯‡}öÝ6;nÛMF½Žô½ß͹çÅú¿XÐFõþ¤Â¨êÇëIé¬ÿ? ¸ì¹ž™5k¶ÇÚüUï×óö¡}~ÅwDêÆÌöQÕ:w؃£uUloýe˜µ®—¬ýYꙿ\úwZ£Òû+jîyö:ç?c6ÿ…oç©}vú·Ôúåý-ø–Ü;û½Wè]C›³k»ù§¨až"xnW'gô¾mRFþnçCéÍé}§ŽqêkGwÄÜÿíÛ½êòI*$’I;“kŸÿÓõUÎ}zê¶tþŽÚè³ÒÈι˜”Û;vOéoÝîÛèã¶ç±û}–l]ã¿Æ){*é·‡šÙ”רð_!–N ÜÖÐêî~϶Wì­ÿ¤þmÓÌ"WÂkz|û"ðûinÚØu°ËXÏm;ýUê;ÓþrßK}ˆ7n­’D—h ¶¬ö³üÆ+½VêþËWJ®—2ÜK^ÑasI's«ÛéÐ_ê¿ØÛm®Ïð{?IüêÏËÂuuy¯5Z5Ú}ãBêÞæ[W¨Ë¹¯Øÿ§ê+‘ª»y92&ø¶â?ÖìäeŸZÀ)’­<ãô÷_éÅ­Ìl,ÖäãcÙUÂÇ*ak‹ˆk¿Iè3un~×5þÊlgé?áT2:=Ý>¶ä[·ôåÌ€A-0ÇØ×³ó=MÊþ}[=ÍÀc¾Õ•›4cSsXXväÛ’Û]ö¾žÜJìûEwÖßÒ¿e_¥Nâ¨ñXf®3tE~ßÞE×lé=Dõ*)7zy ´ooóù—ú.xÈu×VÆ[²×2ëlµvRÝoM·§a8év3j¼Â»&²÷Y_öÑ2þªôŽ”Êé­›­²ºhv㸾¼f†2ëô+÷þ‘íoó¹‡ú+ôæ¾°áösìq c¿ïÇjªHéæ~­ð Û¤’I‹Ô¸|ßñšÊ22Ž7M³'§áX*¿/Õk5qum-©Íwó®ßGuŸ¤ÿƒ]Âò<çW™Ôz¿Õœ[›ÚÞ¥•QØÓeô˜öYú<¬ge2ßMìÙ•†¬ò¸á3.(ñmÃ¸Ž§¬£ÿ1/cg×ÚŸ“öGjéç©ãdoÖ¯ÓnCÚöþÏÜúþ—ø5YÿãÓÓ¾ÏÒŸvTÞê1 C÷RǺÓ_Ò¹ÕØæ3oó~ÿQa},ÉÁèo¿fû~' j5mwÕV¿£«ÔµŽW¾¶ô~œÌžÓ0²Ÿ‰×1±ÙV5ÞaÛS]}Ñ®õks«»þÞSG17.+ùµé—õ‘gVýã _Ñ›Õ1z]¹—:œ¶1àŠCXÛ™{îcú ÿ§ci÷¨Óþ1í³¦äõt{Yé†XlöXçÙè:ºîô½=õ}7¬þ—ÖìêŸQºõy×VV-Om¶ÔÆÕêngµö×Pk=fí}vlö*_þjÇþ?ûpQöq]t}Øãù¤}2õ*Ï~@?Æã¤ÝÕ.è×SS,¢ºw¿knzŸ¤¦×Uµí«ÒüßôŠã.ªz^xéÎyÎvCM^«G¦qÜÊÌ¿g¿ÔõW?Õªêõ‹ÚmÎÊfF3ßˆì ˜ÐMa¶~Ž×mn÷}óFnëwRÅ'ô=2¡u-ýÓ”ü]´Û˜_ ¿Di242ùG§þœÑeöN™™öþ›‰³Òû]5ßé“;}F¶Í›¿;nåefýZÿÄçJÿÂXÿùé‹IgÌ)ЕïÿÔõU™õ‡¤~×靯i`¸K©6k$µÕ¾›ÚÂ×ýŸ"§ÙEÛ?I²ÏR¯ÓzkM$”ùý3&‘Ôq²KpÍ{ŸX6ÞÊj⬖ջí eT׉ƒÓë¯þÔçU‘êR±ó2(νÙQɰ4Yê5û÷z¿§³o©²¬½9®Ù¾ËX^ÓÔñl±‚üyõ«Ö`¸'ùk õ\²KÖö¹³ÌÒ5É ÓŽ‡ZÙŠ\¼%},Ù§Ï­m˜Ø5[•O°ChÉê }m}Vѳ+œkÛ²¾É‘é¿ÌFWMVz–zÔz¨ßWßõªÜÖf`¹ø8À·íK-¡÷äŠÀ®¶mwÓ§Ó)Å£õZÿÃßuÿ¥]}ÌÄ9jº¶Ý“´7í€ûAݰ[n÷±šý(ÙkO¹Î÷&gîM9e#®‹£Ž1ÛûVsì}޶ÛeÏúv¾7ñ ¶·÷+­»µþ«tò ú•Q¾ž<ó²wYgýqíöSþ¦ô+òœÛ3jÆì:>Ïä–ý*«ýÿð];ZZhÐ ©t’I©rÙÿâë çf]”lÉÇ/õ/Ç¢ÀÚžùÜ^æ9s}îßìzÖ§×[õŽŽ—Ó-±•¿ ä=´SMÖnŠw»í¶ã1´íwæÙ¿þ ÿ¬]`deudTÌ|>¦Î˜ÞX íkŸ]·¬KoûUÞ¯Ú±Ù_è~ÏWøUc2Æ¥ ˆñ‡ü[A§_¬}Pé_ ïVŒ~Ÿ”;lÑ[Xíí³sZÆ)uÿª½3¯>‹²]u8Óèäã?Ó°®ÝůoÒnï¡ìX½ëZ¿ë3pnÈßeùÕúvÒÚ™éâØêivK]»+!®ôþÑNße^¥ŸðˆßY:ßVÀêOÚ'IÅ‹2(ª¬ ×Úèxêt>Úó(«o¥è}’¿©êzŸàÑÌ'‰ê”u?¦xeþ2´t0¾¦ôl—ÑèõE9àŒ›‹µÒ6}=»±ŸCm{æ_IýûÔ¿ìbß[vñênßë}=›vïþBÍé}oëW^ɨ=×`Q——F@4ÕM4ƒök-õ²}]•»ô¿ðžóНÕÿ¬?X:…,¿3cÿf75¶]Eu>»\NÇâW»fnƿԽÿá6}L3jNA¡ŽC©ù¦=§gAŸâÛ 3+¶åzYŽ©ö“cwG©éìw§íþ}ûÕ¬¨ý#íÞ£ï¨×Uä<‹éú>Ÿ³ÚçúzË"¿­oŽ™u­ÌdzýG«5Œk_é9Ô´Ù@¬;þNûK}F†¦«¡Ÿ¬Ýbì,rìáŠié•u,›i¡—]w¨ç×c©ÇµÌ«ì¸m¯ÕËôÿMûˆðó~ç_šÎ÷ÿ®à­;=®%X8XøT—±je5—qmm³{´÷mj:­ÓrNWNÅÊ/é®ßQ­,ÞÖ¿{jsžê÷nþo±YUevo{ÕsÿÕõT’I%)UË阚äR×»÷ĵßöã6½ZI]Täªý,¿qü=GçJæ/Kéø‡u5®ýó.wùïÜõm$JR’I$å)$’IHþÍö•é3톱vÑ¿a;Í^§Óô÷Û]Ó:kóF{±)vkD7(ÖÓh·K¶úŸô•¤“‡KÛþjšß³zpÙ´JÃ}q[}¶¸’ûÙíöÜýÎßgÓQ·¤ô«òÙvfWžKêc­nß¡¶ç7ÔnÏÍVÒK×ýn¿Ú¤UccR,mU2±se¡ {¿œ²Í¿Mïü÷ ;¤t—ÖÊ…Žêë¬ÒƘZÚôèkvûivßæ¾‚¸’CŠôµ5©é½;5´bÓPc^ÆVÖ€Ûê\Æíoµ–ÙúK[þèwt^}4Ñ~5´ãG©õ1ͯþ%ŽnÚÿ°®¤®ÿJÔÅŒcÖ1¡¬h­†´)$’bŸÿÙ8BIM!UAdobe PhotoshopAdobe Photoshop CS28BIM".MM*bj(1r2އi¤Ð ü€' ü€'Adobe Photoshop CS2 Windows2005:10:17 22:27:16 ÿÿ Ø &(.HH8BIM îmoptÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿlTargetSettingsClrTObjc ColorTableClrsVlLsisExactboolMttCObjc NativeQuadBl longÿGrn longÿRd longÿTrnsbool addMetadatabool autoReduceboolcolorTableControlObjcColorTableControl lockedColorsVlLs shiftEntriesVlLsditherAlgorithmenumDitherAlgorithmNone ditherPercentlong fileFormatenum FileFormatGIF interlacedboollossylong noMatteColorbool numColorslongreductionAlgorithmenumReductionAlgorithmAdptrolloverMasterPalettebooltransparencyDitherAlgorithmenumDitherAlgorithmDfsntransparencyDitherAmountlongdwebShiftPercentlong zonedDitherObjc ZonedInfo channelIDlongÿÿÿÿ emphasizeTextboolemphasizeVectorsboolfloorlongzonedHistogramWeightObjc ZonedInfo channelIDlongÿÿÿÿ emphasizeTextboolemphasizeVectorsboolfloorlong zonedLossyObjc ZonedInfo channelIDlongÿÿÿÿ emphasizeTextboolemphasizeVectorsboolfloorlong8BIM¡-msetnullVersionlong8BIM¢ms4w8BIM£ maniIRFR8BIMAnDsànullAFStlongFrInVlLsObjcnullFrIDlongCšŒ<FrGAdoub@>FStsVlLsObjcnullFsIDlongAFrmlongFsFrVlLslongCšŒ<LCntlong8BIMRoll8BIM¤mfrir,rØbbb8BIMnormÿ)ð(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ Background8BIMluni Background8BIMlnsrbgnd8BIMlyid8BIMclbl8BIMinfx8BIMknko8BIMlspf8BIMlclr8BIMfxrpÿÿÿý|ÿÿ¶ˆÎÝ8BIMnormÿ(Ð(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿlogo8BIMluni logo8BIMlyid8BIMclbl8BIMinfx8BIMknko8BIMlspf8BIMlclr8BIMfxrpÀ@:ypƒÄÿÿ3***8BIMnormÿ(Bü(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ FOR SPRING8BIMTyShB?à?à@[à@`P2TxLrTxt TEXT FOR SPRINGTxtCObjcnullHrzndoubVrtcdoub textGriddingenum textGriddingRnd OrntenumOrntHrznAntAenumAnntAnSm EngineDatatdta@ << /EngineDict << /Editor << /Text (þÿFOR SPRING ) >> /ParagraphRun << /DefaultRunData << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> /RunArray [ << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> ] /RunLengthArray [ 11 ] /IsJoinable 1 >> /StyleRun << /DefaultRunData << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 24.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> /RunArray [ << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 24.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> ] /RunLengthArray [ 11 ] /IsJoinable 2 >> /GridInfo << /GridIsOn false /ShowGrid false /GridSize 0.0 /GridLeading 0.0 /GridColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /GridLeadingFillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /AlignLineHeightToGridFlags false >> /AntiAlias 3 /UseFractionalGlyphWidths false /Rendered << /Version 1 /Shapes << /WritingDirection 0 /Children [ << /ShapeType 0 /Procession 0 /Lines << /WritingDirection 0 /Children [ << /Procession 0 /LineTop -18.35156 /Leading 0.09999 /WordStarts [ 0 4 11 ] /CharacterCount 11 /Segments << /WritingDirection 0 /Children [ << /Range [ 0.0 30000.0 ] /Words << /WritingDirection 0 /Children [ << /Type 0 /Base << /CharacterCount 4 /Advance 63.0 /TrailingAdvance 8.0 /Leading 0.09999 /TrailingCharacterCount 1 /StyleRunAlignment 2 /Language 0 /WordCode 1 /IsBrokenWord 0 /BreakType 0 /Strikes << /WritingDirection 0 /Children [ << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 24.0 24.0 ] /FontSize 24.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 0.0 0.0 ] /GlyphMaps [ 41 50 53 3 ] /LigatureMaps [ ] /Flags 36 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 63.0 0.0 ] /OutlineWidth 1.0 >> ] >> >> >> << /Type 0 /Base << /CharacterCount 7 /Advance 114.0 /TrailingAdvance 8.0 /Leading 0.09999 /TrailingCharacterCount 1 /StyleRunAlignment 2 /Language 0 /WordCode 1 /IsBrokenWord 0 /BreakType 0 /Strikes << /WritingDirection 0 /Children [ << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 24.0 24.0 ] /FontSize 24.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 63.0 0.0 ] /GlyphMaps [ 54 51 53 44 49 42 3 ] /LigatureMaps [ ] /Flags 100 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 177.0 0.0 ] /OutlineWidth 1.0 >> ] >> >> >> ] >> >> ] >> >> ] >> /Cookie << /Photoshop << /ShapeType 0 /PointBase [ 0.0 0.0 ] /Base << /ShapeType 0 /TransformPoint0 [ 1.0 0.0 ] /TransformPoint1 [ 0.0 1.0 ] /TransformPoint2 [ 0.0 0.0 ] >> >> >> >> ] >> >> >> /ResourceDict << /KinsokuSet [ << /Name (þÿPhotoshopKinsokuHard) /NoStart (þÿ!\),.:;?]}¢    0!! 0000 0 0 0000A0C0E0G0I0c0ƒ0…0‡0Ž0›0œ00ž0¡0£0¥0§0©0Ã0ã0å0ç0î0õ0ö0û0ü0ý0þÿÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ\([{£§  00 0 0000ÿÿÿÿ ÿ;ÿ[ÿå) /Keep (þÿ  %) /Hanging (þÿ,.00) >> << /Name (þÿPhotoshopKinsokuSoft) /NoStart (þÿ  0000 0 0 00000ž0û0ý0þÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ  00 0 000ÿÿ;ÿ[) /Keep (þÿ  %) /Hanging (þÿ,.00) >> ] /MojiKumiSet [ << /InternalName (þÿPhotoshop6MojiKumiSet1) >> << /InternalName (þÿPhotoshop6MojiKumiSet2) >> << /InternalName (þÿPhotoshop6MojiKumiSet3) >> << /InternalName (þÿPhotoshop6MojiKumiSet4) >> ] /TheNormalStyleSheet 0 /TheNormalParagraphSheet 0 /ParagraphSheetSet [ << /Name (þÿDefault) /DefaultStyleSheet 0 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> ] /StyleSheetSet [ << /Name (þÿNormal) /StyleSheetData << /Font 1 /FontSize 18.0 /FauxBold false /FauxItalic false /AutoLeading true /Leading 27.0 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /AutoKerning true /Kerning 0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 1 /Strikethrough false /Ligatures true /DLigatures true /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst true /OutlineWidth 1.0 >> >> << /StyleSheetData << >> >> ] /FontSet [ << /Name (þÿVerdana-Bold) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.34180 /Ascent 1.00049 /Descent 0.20752 /CapHeight 0.74199 /DistanceToBaseline 0.76465 /UnderlinePosition 0.06787 /UnderlineThickness 0.10303 /HCJKProporitional false /VProporitional false >> >> << /Name (þÿTimesNewRomanPSMT) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.25000 /Ascent 1.00684 /Descent 0.30664 /CapHeight 0.67799 /DistanceToBaseline 0.69336 /UnderlinePosition 0.10889 /UnderlineThickness 0.04883 /HCJKProporitional false /VProporitional false >> >> ] /SuperscriptSize 0.58300 /SuperscriptPosition 0.33300 /SubscriptSize 0.58300 /SubscriptPosition 0.33300 /SmallCapSize 0.70000 >> >> €€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿZ­]ñEÿÿ>à?+/ÿÿ¨GÜIL=ÿÿD„Ei;ÿÿBÁCô9ÿÿ9C¸D°:ÿÿ´8_94.ÿÿæ;—=Ž1ÿÿƒ?æ@÷5ÿÿË<Ë>j3ÿÿ¨>@³4ÿÿFfG¨;ÿÿ­BJ3ÿÿ”>}@…2ÿÿÜ@ÀBž8žAb9Í:'1š0@8á9ñ/š0^79:.š0X8…92š0<79K/š0y0|2:)š0,.œ/Í)š0ä.§0u)š03^4.Ó¦1f2Á,ÿÿ]Íãÿÿ;ç;o9š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿjþh@rÿÿé2ÿÿïØ,!ÿÿEÐVš0àX¹;š0€€€š0äc€1š0ÖÀš0b°cš0‰ò2š0€€€š0Å;ß8tSš0íJyÿÿO !O#ÿÿ/O¯ÿÿIHçEÁ[š0€€€š0€€€š0€€€š0 bKa~mš0 ´&çÏ÷ «æ$ÿÿMÚXš0_’]*kš0#MÀJ¢`š0È. š0%5!š0ôþ(ÿÿTV•Tœdÿÿ€€€š0Úÿ/š0O !O#š0ôþ(š0äc€1š0€€€ÿÿe#í½?ÿÿíJyÿÿ 37ÿÿ±zzM|š0ü"y¬?š0öžš0FedÍn‚j€€€‚j­›‚p€€€‚p€€€‚pÆ ‰%‚pý¨‚pÉÝ­‚p{ ,}%‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€†x´CCG3.ÓË2$5ÿ#×Ö×AŸCŽ:×Ö>Ø?‹3×Ö;;C=‡1ÓËÉ:¢<‹2Á‰3g5 *kvN?c@w6‡•OC_DÊ8´BD©7q†ï> AÞ4ÄÖ;;C=‡1¸ÈC<Œ>F2ÙÜŒ=û?{2ÿÿ(7a9?-ÿÿÍ3ƒ5*,ÿÿI8†9Þ/ÿÿR9:2ÿÿm7}9Ö.ÿÿÀ4P6^.ÿÿ©4G6Ö-ÿÿË2B4ž.ÿÿ.1Æ2Z-ÿÿ *§+\%ÿÿ{,éÿÿF]m^uZÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€š0Fgfépš0ö6Eš0ÛuFu—zš0€€€š0€€€š0·2v9š0Ù*ÿÿ€€€ÿÿ€€€Ü·Eí= š0BOMø`š0ÏF_D¸Zš0noš0€€€š0’ñ7š0½÷š0€€€š0€€€š0€€€«Tÿ­!ÿÿaa´ÿÿ€€€ÿÿ€€€ÿÿ€€€š0ö/Ã,Jš0qhš0€€€š0Ã2ã7š0‘uΚ0€€€š0<›š0€€€š0€€€Ï𤬕 ÿÿFgfépÿÿ€€€š0öžš01.ý*`Hš0€€€š0øqÇ0š0BTþçÏhêÁÿÿ€€€š0Éñš0€€€š0¦—§ š0åš0€€€š0€€€ÿÿØL¡Jî^š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€whù;é>þ*whz)(,eKb:ÜL6sZŒ<>>ž5lZ)8×9f/q[5y6H,£”Õ1#3G*þüp3û4+C3K6Õ7þ,& 68•-ÅËW5ø6v.¸¶¸1q3×)£¤u2Å3l,•Žq2€4+ÍÔü,i.º%×ÖÕ m"ïÍÔÚ(Â*Q$Ó˸m,njÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÿÿ´nômÐtÿÿ“.ÿÿ½Ž¼"ÿÿ<ÇUÿÿåC[A§XÏš>¼æ2š0¡ 4  )š0€€€š0€€€š0 ´&š0Ìd¡9š0YLWœgš0­éš0äc€1š057¨š0ƒ\ßZäiÿÿ€€€ÿÿ€€€ÿÿ€€€š0WmU»dš0J–_š0qhš0= œ%š0€€€š06A}>pWš0¯„š0Ò-}* IÿÿhêÁÿÿ¨â:žA€€€š0pôš0¢­.š0( ñn$š0éOZ6š0€€€š0€€€š0eXš0æ1¢.šLš0€€€š04µ Ë*ÿÿ¡%O"Ã@ÿÿÊ y è'ÿÿÓ>:«T§†="š0€€€š0‘uΚ0AIÅFŠ]š0{V¥T|eš0Z ;Ô"š0ä$i!SAš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0Ó:ö=ä)‚pÛ$d'&‚pê/Ü1#)‚p6¶7‚-‚p¬9ì:Ö2‚p{8:i/‚pŒ8h:0‚us;õ<‘2l9 ;Å1‚p'4µ5¥*‚pD2n4*|j°3Ô5·+‚jÜ,û-(rcx/ð0{)pT¿13Å)2û0½2Á(C'2—3Ú)O+³-q/j%Ž‹f!C#ÔçÛB!ÄƵrJ‡KdGXH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€¸¶jþh@raa´Êç r.q yÄÖ€€€ÄÖ€€€ÿÿÅ$l3ÿÿÉñÿÿ€€€ÿÿ€€€ÿÿBòÿÿ•@Ì=WWÿÿ“Q‹O+bÿÿŸçÙÿÿÝF0=ÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿBòÿÿça±8ÿÿYLWœg«TÔTš0ž*Õ.š0ï5æ2¹Nš0€€€š0ðll‰tš0ÔTš06A}>pWš0²‚Žš0ï#p ~@š0€€€š0€€€ûótëÿÿé:8ÈQš0€€€š0‰ Lþ$š04%×!²@š0€€€š0½÷š0J–_š0€€€š0u¸Òš0_åË.ÿÿ€€€ÿÿÎD·5š0ö6Eš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿkþlÀ_š0®+5.Uš0?S!š09'°)  š0…-µ/Ž$š0_5Ÿ6d.ÿÿ¥759Ø/ÿÿS4Ç5«+š05.0ë&š0ç&“(K!š0O+›,%š0T*#, $š0Ü'º(("ÿÿÔ&Œ(Ü ÿÿŠ$Œ&@ÿÿ· ¤"¿ÿÿÄ!o#š0áHÔJ•Bš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€œ±-`˜^m¦²_øÒ ¦²pd/c«nœ±€€€œ±€€€œ±€€€œ«­›œ«ÖÀœ«¹œ«Ò9 ¦²€€€œ®å*'ºE¥¬<›¥¬€€€œ¥øqÇ0œ¥lýœ¥Áyvy'|¦²€€€¦²€€€ÿÿ> úò$ÿÿÔTÿÿeÑ ¤.ÿÿ‘uÎÿÿ€€€ÿÿ@5=2àMÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ`ˆ^3lÿÿlýÿÿ€€€ÿÿkjRsÿÿ¤¬• ÿÿÙP¾NbÿÿÖ/¶,[Iÿÿç0ðÿÿöžÿÿ€€€ÿÿ+ ß&ÿÿÔC ü-ÿÿ€€€ÿÿäc€1ÿÿ†¸ÿÿ€€€ÿÿÌab`]mÿÿË$Jÿÿà ¢c$ÿÿZ ;Ô"ÿÿ=»ºÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿd”e<\ÿÿB;ápW£µpd/c«nœ±€€€œ±€€€œ±€€€”ª3EËBÜXœ® 7"4çNœ®Áyvy'|œ®€€€œ®Âooçu¦²OM`¦²€€€¦²€€€¦²€€€¦²€€€¦²ØL¡Jî^œ®€€€œ®€€€¥¬tRiP&cœ«îS Rbcœ¥ÄcUbvo“¢ÓTìR_dš›%LÜIÑ^óö€€€ÿÿÈb\ahnÿÿFedÍnÿÿ€€€ÿÿ€€€ÿÿ÷NùLC_ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ 7"4çNÿÿÏF_D¸Zÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ‹pÊqÏhÿÿÜ[[]ÐQÿÿŒGÑI­<ÿÿB3D<8ÿÿgBbDç5ÿÿ:JñKBÿÿ[j\ñSÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€warp warpStyleenum warpStylewarpNone warpValuedoubwarpPerspectivedoubwarpPerspectiveOtherdoub warpRotateenumOrntHrzn8BIMluni FOR SPRING8BIMlnsrrend8BIMlyid 8BIMclbl8BIMinfx8BIMknko8BIMlspf8BIMlclr8BIMfxrp@Q€À[wpÄÿÿ‹VVV8BIMnormÿ(Bè(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿSYSTEM8BIMTyShAø?à?à@]À@[à2TxLrTxt TEXTSYSTEMTxtCObjcnullHrzndoubVrtcdoub textGriddingenum textGriddingRnd OrntenumOrntHrznAntAenumAnntAnSm EngineDatatdta@ << /EngineDict << /Editor << /Text (þÿSYSTEM ) >> /ParagraphRun << /DefaultRunData << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> /RunArray [ << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> ] /RunLengthArray [ 7 ] /IsJoinable 1 >> /StyleRun << /DefaultRunData << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 50.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> /RunArray [ << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 50.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> ] /RunLengthArray [ 7 ] /IsJoinable 2 >> /GridInfo << /GridIsOn false /ShowGrid false /GridSize 0.0 /GridLeading 0.0 /GridColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /GridLeadingFillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /AlignLineHeightToGridFlags false >> /AntiAlias 3 /UseFractionalGlyphWidths false /Rendered << /Version 1 /Shapes << /WritingDirection 0 /Children [ << /ShapeType 0 /Procession 0 /Lines << /WritingDirection 0 /Children [ << /Procession 0 /LineTop -39.52637 /Leading 0.09999 /WordStarts [ 0 7 ] /CharacterCount 7 /Segments << /WritingDirection 0 /Children [ << /Range [ 0.0 30000.0 ] /Words << /WritingDirection 0 /Children [ << /Type 0 /Base << /CharacterCount 7 /Advance 165.0 /TrailingAdvance 9.0 /Leading 0.09999 /TrailingCharacterCount 1 /StyleRunAlignment 2 /Language 0 /WordCode 1 /IsBrokenWord 0 /BreakType 0 /Strikes << /WritingDirection 0 /Children [ << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 50.0 50.0 ] /FontSize 50.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 0.0 0.0 ] /GlyphMaps [ 54 60 54 55 40 48 3 ] /LigatureMaps [ ] /Flags 100 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 165.0 0.0 ] /OutlineWidth 1.0 >> ] >> >> >> ] >> >> ] >> >> ] >> /Cookie << /Photoshop << /ShapeType 0 /PointBase [ 0.0 0.0 ] /Base << /ShapeType 0 /TransformPoint0 [ 1.0 0.0 ] /TransformPoint1 [ 0.0 1.0 ] /TransformPoint2 [ 0.0 0.0 ] >> >> >> >> ] >> >> >> /ResourceDict << /KinsokuSet [ << /Name (þÿPhotoshopKinsokuHard) /NoStart (þÿ!\),.:;?]}¢    0!! 0000 0 0 0000A0C0E0G0I0c0ƒ0…0‡0Ž0›0œ00ž0¡0£0¥0§0©0Ã0ã0å0ç0î0õ0ö0û0ü0ý0þÿÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ\([{£§  00 0 0000ÿÿÿÿ ÿ;ÿ[ÿå) /Keep (þÿ  %) /Hanging (þÿ,.00) >> << /Name (þÿPhotoshopKinsokuSoft) /NoStart (þÿ  0000 0 0 00000ž0û0ý0þÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ  00 0 000ÿÿ;ÿ[) /Keep (þÿ  %) /Hanging (þÿ,.00) >> ] /MojiKumiSet [ << /InternalName (þÿPhotoshop6MojiKumiSet1) >> << /InternalName (þÿPhotoshop6MojiKumiSet2) >> << /InternalName (þÿPhotoshop6MojiKumiSet3) >> << /InternalName (þÿPhotoshop6MojiKumiSet4) >> ] /TheNormalStyleSheet 0 /TheNormalParagraphSheet 0 /ParagraphSheetSet [ << /Name (þÿDefault) /DefaultStyleSheet 0 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> ] /StyleSheetSet [ << /Name (þÿNormal) /StyleSheetData << /Font 1 /FontSize 18.0 /FauxBold false /FauxItalic false /AutoLeading true /Leading 27.0 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /AutoKerning true /Kerning 0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 1 /Strikethrough false /Ligatures true /DLigatures true /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst true /OutlineWidth 1.0 >> >> << /StyleSheetData << >> >> ] /FontSet [ << /Name (þÿImpact) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.17627 /Ascent 1.16797 /Descent 0.33057 /CapHeight 0.80699 /DistanceToBaseline 0.79053 /UnderlinePosition 0.10010 /UnderlineThickness 0.04980 /HCJKProporitional false /VProporitional false >> >> << /Name (þÿTimesNewRomanPSMT) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.25000 /Ascent 1.00684 /Descent 0.30664 /CapHeight 0.67799 /DistanceToBaseline 0.69336 /UnderlinePosition 0.10889 /UnderlineThickness 0.04883 /HCJKProporitional false /VProporitional false >> >> ] /SuperscriptSize 0.58300 /SuperscriptPosition 0.33300 /SubscriptSize 0.58300 /SubscriptPosition 0.33300 /SmallCapSize 0.70000 >> >> ent 1.00049 /Descent 0.20752 /CapHeight 0.74199 /DistanceToBaseline 0.76465 /UnderlinePosition 0.06787 /UnderlineThickness 0.10303 /HCJKProporitional false /VProporitional false >> >> << /Name (þÿTimesNewRomanPSMT) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.25000 /Ascent 1.00684 /Descent 0.30664 /CapHeight 0.67799 /DistanceToBaseline 0.69336 /UnderlinePosition 0.10889 /UnderlineThickness 0.04883 /HCJKProporitional false /VProporitional false >> >> ] /SuperscriptSize 0.58300 /SuperscriptPosition 0.33300 /SubscriptSize 0.58300 /SubscriptPosition 0.33300 /SmallCapSize 0.70000 >> >> €€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿZ­]ñEÿÿ>à?+/ÿÿ¨GÜIL=ÿÿD„Ei;ÿÿBÁCô9ÿÿ9C¸D°:ÿÿ´8_94.ÿÿæ;—=Ž1ÿÿƒ?æ@÷5ÿÿË<Ë>j3ÿÿ¨>@³4ÿÿFfG¨;ÿÿ­BJ3ÿÿ”>}@…2ÿÿÜ@ÀBž8žAb9Í:'1š0@8á9ñ/š0^79:.š0X8…92š0<79K/š0y0|2:)š0,.œ/Í)š0ä.§0u)š03^4.Ó¦1f2Á,ÿÿ]Íãÿÿ;ç;o9š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿjþh@rÿÿé2ÿÿïØ,!ÿÿEÐVš0àX¹;š0€€€š0äc€1š0ÖÀš0b°cš0‰ò2š0€€€š0Å;ß8tSš0íJyÿÿO !O#ÿÿ/O¯ÿÿIHçEÁ[š0€€€š0€€€š0€€€š0 bKa~mš0 ´&çÏ÷ «æ$ÿÿMÚXš0_’]*kš0#MÀJ¢`š0È. š0%5!š0ôþ(ÿÿTV•Tœdÿÿ€€€š0Úÿ/š0O !O#š0ôþ(š0äc€1š0€€€ÿÿe#í½?ÿÿíJyÿÿ 37ÿÿ±zzM|š0ü"y¬?š0öžš0FedÍn‚j€€€‚j­›‚p€€€‚p€€€‚pÆ ‰%‚pý¨‚pÉÝ­‚p{ ,}%‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€†x´CCG3.ÓË2$5ÿ#×Ö×AŸCŽ:×Ö>Ø?‹3×Ö;;C=‡1ÓËÉ:¢<‹2Á‰3g5 *kvN?c@w6‡•OC_DÊ8´BD©7q†ï> AÞ4ÄÖ;;C=‡1¸ÈC<Œ>F2ÙÜŒ=û?{2ÿÿ(7a9?-ÿÿÍ3ƒ5*,ÿÿI8†9Þ/ÿÿR9:2ÿÿm7}9Ö.ÿÿÀ4P6^.ÿÿ©4G6Ö-ÿÿË2B4ž.ÿÿ.1Æ2Z-ÿÿ *§+\%ÿÿ{,éÿÿF]m^uZÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€š0Fgfépš0ö6Eš0ÛuFu—zš0€€€š0€€€š0·2v9š0Ù*ÿÿ€€€ÿÿ€€€Ü·Eí= š0BOMø`š0ÏF_D¸Zš0noš0€€€š0’ñ7š0½÷š0€€€š0€€€š0€€€«Tÿ­!ÿÿaa´ÿÿ€€€ÿÿ€€€ÿÿ€€€š0ö/Ã,Jš0qhš0€€€š0Ã2ã7š0‘uΚ0€€€š0<›š0€€€š0€€€Ï𤬕 ÿÿFgfépÿÿ€€€š0öžš01.ý*`Hš0€€€š0øqÇ0š0BTþçÏhêÁÿÿ€€€š0Éñš0€€€š0¦—§ š0åš0€€€š0€€€ÿÿØL¡Jî^š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€whù;é>þ*whz)(,eKb:ÜL6sZŒ<>>ž5lZ)8×9f/q[5y6H,£”Õ1#3G*þüp3û4+C3K6Õ7þ,& 68•-ÅËW5ø6v.¸¶¸1q3×)£¤u2Å3l,•Žq2€4+ÍÔü,i.º%×ÖÕ m"ïÍÔÚ(Â*Q$Ó˸m,njÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÿÿ´nômÐtÿÿ“.ÿÿ½Ž¼"ÿÿ<ÇUÿÿåC[A§XÏš>¼æ2š0¡ 4  )š0€€€š0€€€š0 ´&š0Ìd¡9š0YLWœgš0­éš0äc€1š057¨š0ƒ\ßZäiÿÿ€€€ÿÿ€€€ÿÿ€€€š0WmU»dš0J–_š0qhš0= œ%š0€€€š06A}>pWš0¯„š0Ò-}* IÿÿhêÁÿÿ¨â:žA€€€š0pôš0¢­.š0( ñn$š0éOZ6š0€€€š0€€€š0eXš0æ1¢.šLš0€€€š04µ Ë*ÿÿ¡%O"Ã@ÿÿÊ y è'ÿÿÓ>:«T§†="š0€€€š0‘uΚ0AIÅFŠ]š0{V¥T|eš0Z ;Ô"š0ä$i!SAš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0Ó:ö=ä)‚pÛ$d'&‚pê/Ü1#)‚p6¶7‚-‚p¬9ì:Ö2‚p{8:i/‚pŒ8h:0‚us;õ<‘2l9 ;Å1‚p'4µ5¥*‚pD2n4*|j°3Ô5·+‚jÜ,û-(rcx/ð0{)pT¿13Å)2û0½2Á(C'2—3Ú)O+³-q/j%Ž‹f!C#ÔçÛB!ÄƵrJ‡KdGXH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€¸¶jþh@raa´Êç r.q yÄÖ€€€ÄÖ€€€ÿÿÅ$l3ÿÿÉñÿÿ€€€ÿÿ€€€ÿÿBòÿÿ•@Ì=WWÿÿ“Q‹O+bÿÿŸçÙÿÿÝF0=ÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿBòÿÿça±8ÿÿYLWœg«TÔTš0ž*Õ.š0ï5æ2¹Nš0€€€š0ðll‰tš0ÔTš06A}>pWš0²‚Žš0ï#p ~@š0€€€š0€€€ûótëÿÿé:8ÈQš0€€€š0‰ Lþ$š04%×!²@š0€€€š0½÷š0J–_š0€€€š0u¸Òš0_åË.ÿÿ€€€ÿÿÎD·5š0ö6Eš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿkþlÀ_š0®+5.Uš0?S!š09'°)  š0…-µ/Ž$š0_5Ÿ6d.ÿÿ¥759Ø/ÿÿS4Ç5«+š05.0ë&š0ç&“(K!š0O+›,%š0T*#, $š0Ü'º(("ÿÿÔ&Œ(Ü ÿÿŠ$Œ&@ÿÿ· ¤"¿ÿÿÄ!o#š0áHÔJ•Bš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€œ±-`˜^m¦²_øÒ ¦²pd/c«nœ±€€€œ±€€€œ±€€€œ«­›œ«ÖÀœ«¹œ«Ò9 ¦²€€€œ®å*'ºE¥¬<›¥¬€€€œ¥øqÇ0œ¥lýœ¥Áyvy'|¦²€€€¦²€€€ÿÿ> úò$ÿÿÔTÿÿeÑ ¤.ÿÿ‘uÎÿÿ€€€ÿÿ@5=2àMÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ`ˆ^3lÿÿlýÿÿ€€€ÿÿkjRsÿÿ¤¬• ÿÿÙP¾NbÿÿÖ/¶,[Iÿÿç0ðÿÿöžÿÿ€€€ÿÿ+ ß&ÿÿÔC ü-ÿÿ€€€ÿÿäc€1ÿÿ†¸ÿÿ€€€ÿÿÌab`]mÿÿË$Jÿÿà ¢c$ÿÿZ ;Ô"ÿÿ=»ºÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿd”e<\ÿÿB;ápW£µpd/c«nœ±€€€œ±€€€œ±€€€”ª3EËBÜXœ® 7"4çNœ®Áyvy'|œ®€€€œ®Âooçu¦²OM`¦²€€€¦²€€€¦²€€€¦²€€€¦²ØL¡Jî^œ®€€€œ®€€€¥¬tRiP&cœ«îS Rbcœ¥ÄcUbvo“¢ÓTìR_dš›%LÜIÑ^óö€€€ÿÿÈb\ahnÿÿFedÍnÿÿ€€€ÿÿ€€€ÿÿ÷NùLC_ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ 7"4çNÿÿÏF_D¸Zÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ‹pÊqÏhÿÿÜ[[]ÐQÿÿŒGÑI­<ÿÿB3D<8ÿÿgBbDç5ÿÿ:JñKBÿÿ[j\ñSÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€warp warpStyleenum warpStylewarpNone warpValuedoubwarpPerspectivedoubwarpPerspectiveOtherdoub warpRotateenumOrntHrzn8BIMluniSYSTEM8BIMlnsrrend8BIMlyid8BIMclbl8BIMinfx8BIMknko8BIMlspf8BIMlclr8BIMfxrp@PàÀ>fSÆÿÿÚVVV8BIMnormÿ(Bô(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿSECURITY8BIMTyShAü?à?à@Y€@T 2TxLrTxt TEXT SECURITYTxtCObjcnullHrzndoubVrtcdoub textGriddingenum textGriddingRnd OrntenumOrntHrznAntAenumAnntAnSm EngineDatatdta@ << /EngineDict << /Editor << /Text (þÿSECURITY ) >> /ParagraphRun << /DefaultRunData << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> /RunArray [ << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> ] /RunLengthArray [ 9 ] /IsJoinable 1 >> /StyleRun << /DefaultRunData << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 50.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> /RunArray [ << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 50.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> ] /RunLengthArray [ 9 ] /IsJoinable 2 >> /GridInfo << /GridIsOn false /ShowGrid false /GridSize 0.0 /GridLeading 0.0 /GridColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /GridLeadingFillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /AlignLineHeightToGridFlags false >> /AntiAlias 3 /UseFractionalGlyphWidths false /Rendered << /Version 1 /Shapes << /WritingDirection 0 /Children [ << /ShapeType 0 /Procession 0 /Lines << /WritingDirection 0 /Children [ << /Procession 0 /LineTop -39.52637 /Leading 0.09999 /WordStarts [ 0 9 ] /CharacterCount 9 /Segments << /WritingDirection 0 /Children [ << /Range [ 0.0 30000.0 ] /Words << /WritingDirection 0 /Children [ << /Type 0 /Base << /CharacterCount 9 /Advance 200.24512 /TrailingAdvance 9.0 /Leading 0.09999 /TrailingCharacterCount 1 /StyleRunAlignment 2 /Language 0 /WordCode 1 /IsBrokenWord 0 /BreakType 0 /Strikes << /WritingDirection 0 /Children [ << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 50.0 50.0 ] /FontSize 50.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 0.0 0.0 ] /GlyphMaps [ 54 40 38 56 53 44 55 ] /LigatureMaps [ ] /Flags 36 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 166.0 0.0 ] /OutlineWidth 1.0 >> << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 50.0 50.0 ] /FontSize 50.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 167.24512 0.0 ] /GlyphMaps [ 60 ] /LigatureMaps [ ] /Flags 36 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 191.24512 0.0 ] /OutlineWidth 1.0 >> << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 50.0 50.0 ] /FontSize 50.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 191.24512 0.0 ] /GlyphMaps [ 3 ] /LigatureMaps [ ] /Flags 100 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 200.24512 0.0 ] /OutlineWidth 1.0 >> ] >> >> >> ] >> >> ] >> >> ] >> /Cookie << /Photoshop << /ShapeType 0 /PointBase [ 0.0 0.0 ] /Base << /ShapeType 0 /TransformPoint0 [ 1.0 0.0 ] /TransformPoint1 [ 0.0 1.0 ] /TransformPoint2 [ 0.0 0.0 ] >> >> >> >> ] >> >> >> /ResourceDict << /KinsokuSet [ << /Name (þÿPhotoshopKinsokuHard) /NoStart (þÿ!\),.:;?]}¢    0!! 0000 0 0 0000A0C0E0G0I0c0ƒ0…0‡0Ž0›0œ00ž0¡0£0¥0§0©0Ã0ã0å0ç0î0õ0ö0û0ü0ý0þÿÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ\([{£§  00 0 0000ÿÿÿÿ ÿ;ÿ[ÿå) /Keep (þÿ  %) /Hanging (þÿ,.00) >> << /Name (þÿPhotoshopKinsokuSoft) /NoStart (þÿ  0000 0 0 00000ž0û0ý0þÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ  00 0 000ÿÿ;ÿ[) /Keep (þÿ  %) /Hanging (þÿ,.00) >> ] /MojiKumiSet [ << /InternalName (þÿPhotoshop6MojiKumiSet1) >> << /InternalName (þÿPhotoshop6MojiKumiSet2) >> << /InternalName (þÿPhotoshop6MojiKumiSet3) >> << /InternalName (þÿPhotoshop6MojiKumiSet4) >> ] /TheNormalStyleSheet 0 /TheNormalParagraphSheet 0 /ParagraphSheetSet [ << /Name (þÿDefault) /DefaultStyleSheet 0 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> ] /StyleSheetSet [ << /Name (þÿNormal) /StyleSheetData << /Font 1 /FontSize 18.0 /FauxBold false /FauxItalic false /AutoLeading true /Leading 27.0 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /AutoKerning true /Kerning 0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 1 /Strikethrough false /Ligatures true /DLigatures true /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst true /OutlineWidth 1.0 >> >> << /StyleSheetData << >> >> ] /FontSet [ << /Name (þÿImpact) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.17627 /Ascent 1.16797 /Descent 0.33057 /CapHeight 0.80699 /DistanceToBaseline 0.79053 /UnderlinePosition 0.10010 /UnderlineThickness 0.04980 /HCJKProporitional false /VProporitional false >> >> << /Name (þÿTimesNewRomanPSMT) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.25000 /Ascent 1.00684 /Descent 0.30664 /CapHeight 0.67799 /DistanceToBaseline 0.69336 /UnderlinePosition 0.10889 /UnderlineThickness 0.04883 /HCJKProporitional false /VProporitional false >> >> ] /SuperscriptSize 0.58300 /SuperscriptPosition 0.33300 /SubscriptSize 0.58300 /SubscriptPosition 0.33300 /SmallCapSize 0.70000 >> >> ÜIL=ÿÿD„Ei;ÿÿBÁCô9ÿÿ9C¸D°:ÿÿ´8_94.ÿÿæ;—=Ž1ÿÿƒ?æ@÷5ÿÿË<Ë>j3ÿÿ¨>@³4ÿÿFfG¨;ÿÿ­BJ3ÿÿ”>}@…2ÿÿÜ@ÀBž8žAb9Í:'1š0@8á9ñ/š0^79:.š0X8…92š0<79K/š0y0|2:)š0,.œ/Í)š0ä.§0u)š03^4.Ó¦1f2Á,ÿÿ]Íãÿÿ;ç;o9š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿjþh@rÿÿé2ÿÿïØ,!ÿÿEÐVš0àX¹;š0€€€š0äc€1š0ÖÀš0b°cš0‰ò2š0€€€š0Å;ß8tSš0íJyÿÿO !O#ÿÿ/O¯ÿÿIHçEÁ[š0€€€š0€€€š0€€€š0 bKa~mš0 ´&çÏ÷ «æ$ÿÿMÚXš0_’]*kš0#MÀJ¢`š0È. š0%5!š0ôþ(ÿÿTV•Tœdÿÿ€€€š0Úÿ/š0O !O#š0ôþ(š0äc€1š0€€€ÿÿe#í½?ÿÿíJyÿÿ 37ÿÿ±zzM|š0ü"y¬?š0öžš0FedÍn‚j€€€‚j­›‚p€€€‚p€€€‚pÆ ‰%‚pý¨‚pÉÝ­‚p{ ,}%‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€†x´CCG3.ÓË2$5ÿ#×Ö×AŸCŽ:×Ö>Ø?‹3×Ö;;C=‡1ÓËÉ:¢<‹2Á‰3g5 *kvN?c@w6‡•OC_DÊ8´BD©7q†ï> AÞ4ÄÖ;;C=‡1¸ÈC<Œ>F2ÙÜŒ=û?{2ÿÿ(7a9?-ÿÿÍ3ƒ5*,ÿÿI8†9Þ/ÿÿR9:2ÿÿm7}9Ö.ÿÿÀ4P6^.ÿÿ©4G6Ö-ÿÿË2B4ž.ÿÿ.1Æ2Z-ÿÿ *§+\%ÿÿ{,éÿÿF]m^uZÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€š0Fgfépš0ö6Eš0ÛuFu—zš0€€€š0€€€š0·2v9š0Ù*ÿÿ€€€ÿÿ€€€Ü·Eí= š0BOMø`š0ÏF_D¸Zš0noš0€€€š0’ñ7š0½÷š0€€€š0€€€š0€€€«Tÿ­!ÿÿaa´ÿÿ€€€ÿÿ€€€ÿÿ€€€š0ö/Ã,Jš0qhš0€€€š0Ã2ã7š0‘uΚ0€€€š0<›š0€€€š0€€€Ï𤬕 ÿÿFgfépÿÿ€€€š0öžš01.ý*`Hš0€€€š0øqÇ0š0BTþçÏhêÁÿÿ€€€š0Éñš0€€€š0¦—§ š0åš0€€€š0€€€ÿÿØL¡Jî^š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€whù;é>þ*whz)(,eKb:ÜL6sZŒ<>>ž5lZ)8×9f/q[5y6H,£”Õ1#3G*þüp3û4+C3K6Õ7þ,& 68•-ÅËW5ø6v.¸¶¸1q3×)£¤u2Å3l,•Žq2€4+ÍÔü,i.º%×ÖÕ m"ïÍÔÚ(Â*Q$Ó˸m,njÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÿÿ´nômÐtÿÿ“.ÿÿ½Ž¼"ÿÿ<ÇUÿÿåC[A§XÏš>¼æ2š0¡ 4  )š0€€€š0€€€š0 ´&š0Ìd¡9š0YLWœgš0­éš0äc€1š057¨š0ƒ\ßZäiÿÿ€€€ÿÿ€€€ÿÿ€€€š0WmU»dš0J–_š0qhš0= œ%š0€€€š06A}>pWš0¯„š0Ò-}* IÿÿhêÁÿÿ¨â:žA€€€š0pôš0¢­.š0( ñn$š0éOZ6š0€€€š0€€€š0eXš0æ1¢.šLš0€€€š04µ Ë*ÿÿ¡%O"Ã@ÿÿÊ y è'ÿÿÓ>:«T§†="š0€€€š0‘uΚ0AIÅFŠ]š0{V¥T|eš0Z ;Ô"š0ä$i!SAš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0Ó:ö=ä)‚pÛ$d'&‚pê/Ü1#)‚p6¶7‚-‚p¬9ì:Ö2‚p{8:i/‚pŒ8h:0‚us;õ<‘2l9 ;Å1‚p'4µ5¥*‚pD2n4*|j°3Ô5·+‚jÜ,û-(rcx/ð0{)pT¿13Å)2û0½2Á(C'2—3Ú)O+³-q/j%Ž‹f!C#ÔçÛB!ÄƵrJ‡KdGXH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€¸¶jþh@raa´Êç r.q yÄÖ€€€ÄÖ€€€ÿÿÅ$l3ÿÿÉñÿÿ€€€ÿÿ€€€ÿÿBòÿÿ•@Ì=WWÿÿ“Q‹O+bÿÿŸçÙÿÿÝF0=ÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿBòÿÿça±8ÿÿYLWœg«TÔTš0ž*Õ.š0ï5æ2¹Nš0€€€š0ðll‰tš0ÔTš06A}>pWš0²‚Žš0ï#p ~@š0€€€š0€€€ûótëÿÿé:8ÈQš0€€€š0‰ Lþ$š04%×!²@š0€€€š0½÷š0J–_š0€€€š0u¸Òš0_åË.ÿÿ€€€ÿÿÎD·5š0ö6Eš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿkþlÀ_š0®+5.Uš0?S!š09'°)  š0…-µ/Ž$š0_5Ÿ6d.ÿÿ¥759Ø/ÿÿS4Ç5«+š05.0ë&š0ç&“(K!š0O+›,%š0T*#, $š0Ü'º(("ÿÿÔ&Œ(Ü ÿÿŠ$Œ&@ÿÿ· ¤"¿ÿÿÄ!o#š0áHÔJ•Bš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€œ±-`˜^m¦²_øÒ ¦²pd/c«nœ±€€€œ±€€€œ±€€€œ«­›œ«ÖÀœ«¹œ«Ò9 ¦²€€€œ®å*'ºE¥¬<›¥¬€€€œ¥øqÇ0œ¥lýœ¥Áyvy'|¦²€€€¦²€€€ÿÿ> úò$ÿÿÔTÿÿeÑ ¤.ÿÿ‘uÎÿÿ€€€ÿÿ@5=2àMÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ`ˆ^3lÿÿlýÿÿ€€€ÿÿkjRsÿÿ¤¬• ÿÿÙP¾NbÿÿÖ/¶,[Iÿÿç0ðÿÿöžÿÿ€€€ÿÿ+ ß&ÿÿÔC ü-ÿÿ€€€ÿÿäc€1ÿÿ†¸ÿÿ€€€ÿÿÌab`]mÿÿË$Jÿÿà ¢c$ÿÿZ ;Ô"ÿÿ=»ºÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿd”e<\ÿÿB;ápW£µpd/c«nœ±€€€œ±€€€œ±€€€”ª3EËBÜXœ® 7"4çNœ®Áyvy'|œ®€€€œ®Âooçu¦²OM`¦²€€€¦²€€€¦²€€€¦²€€€¦²ØL¡Jî^œ®€€€œ®€€€¥¬tRiP&cœ«îS Rbcœ¥ÄcUbvo“¢ÓTìR_dš›%LÜIÑ^óö€€€ÿÿÈb\ahnÿÿFedÍnÿÿ€€€ÿÿ€€€ÿÿ÷NùLC_ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ 7"4çNÿÿÏF_D¸Zÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ‹pÊqÏhÿÿÜ[[]ÐQÿÿŒGÑI­<ÿÿB3D<8ÿÿgBbDç5ÿÿ:JñKBÿÿ[j\ñSÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€warp warpStyleenum warpStylewarpNone warpValuedoubwarpPerspectivedoubwarpPerspectiveOtherdoub warpRotateenumOrntHrzn8BIMluniSECURITY8BIMlnsrrend8BIMlyid8BIMclbl8BIMinfx8BIMknko8BIMlspf8BIMlclr8BIMfxrpÀÀ+¡7Æÿÿ~2228BIMnormÿ(Bè(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿAcegi8BIMTyShAø?à?à@d @J@2TxLrTxt TEXTAcegiTxtCObjcnullHrzndoubVrtcdoub textGriddingenum textGriddingRnd OrntenumOrntHrznAntAenumAnntAnSm EngineDatatdta@ << /EngineDict << /Editor << /Text (þÿAcegi ) >> /ParagraphRun << /DefaultRunData << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> /RunArray [ << /ParagraphSheet << /DefaultStyleSheet 1 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> /Adjustments << /Axis [ 1.0 0.0 1.0 ] /XY [ 0.0 0.0 ] >> >> ] /RunLengthArray [ 6 ] /IsJoinable 1 >> /StyleRun << /DefaultRunData << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 24.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> /RunArray [ << /StyleSheet << /StyleSheetData << /AutoKerning true /Font 0 /FontSize 24.0 /FauxBold false /FauxItalic false /AutoLeading false /Leading 0.09999 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 0 /Strikethrough false /Ligatures true /DLigatures false /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst false /OutlineWidth 1.0 >> >> >> ] /RunLengthArray [ 6 ] /IsJoinable 2 >> /GridInfo << /GridIsOn false /ShowGrid false /GridSize 0.0 /GridLeading 0.0 /GridColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /GridLeadingFillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /AlignLineHeightToGridFlags false >> /AntiAlias 3 /UseFractionalGlyphWidths false /Rendered << /Version 1 /Shapes << /WritingDirection 0 /Children [ << /ShapeType 0 /Procession 0 /Lines << /WritingDirection 0 /Children [ << /Procession 0 /LineTop -18.35156 /Leading 0.09999 /WordStarts [ 0 6 ] /CharacterCount 6 /Segments << /WritingDirection 0 /Children [ << /Range [ 0.0 30000.0 ] /Words << /WritingDirection 0 /Children [ << /Type 0 /Base << /CharacterCount 6 /Advance 82.0 /TrailingAdvance 8.0 /Leading 0.09999 /TrailingCharacterCount 1 /StyleRunAlignment 2 /Language 0 /WordCode 1 /IsBrokenWord 0 /BreakType 0 /Strikes << /WritingDirection 0 /Children [ << /Font 0 /Direction 0 /GlyphDirection 0 /Scale [ 24.0 24.0 ] /FontSize 24.0 /Tracking 0.0 /AntiAlias 3 /Kerning 0.0 /Origin [ 0.0 0.0 ] /GlyphMaps [ 36 70 72 74 76 3 ] /LigatureMaps [ ] /Flags 100 /FillColor << /Type 1 /Values [ 1.0 0.20001 0.20001 0.60001 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /OriginEnd [ 82.0 0.0 ] /OutlineWidth 1.0 >> ] >> >> >> ] >> >> ] >> >> ] >> /Cookie << /Photoshop << /ShapeType 0 /PointBase [ 0.0 0.0 ] /Base << /ShapeType 0 /TransformPoint0 [ 1.0 0.0 ] /TransformPoint1 [ 0.0 1.0 ] /TransformPoint2 [ 0.0 0.0 ] >> >> >> >> ] >> >> >> /ResourceDict << /KinsokuSet [ << /Name (þÿPhotoshopKinsokuHard) /NoStart (þÿ!\),.:;?]}¢    0!! 0000 0 0 0000A0C0E0G0I0c0ƒ0…0‡0Ž0›0œ00ž0¡0£0¥0§0©0Ã0ã0å0ç0î0õ0ö0û0ü0ý0þÿÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ\([{£§  00 0 0000ÿÿÿÿ ÿ;ÿ[ÿå) /Keep (þÿ  %) /Hanging (þÿ,.00) >> << /Name (þÿPhotoshopKinsokuSoft) /NoStart (þÿ  0000 0 0 00000ž0û0ý0þÿÿ ÿ ÿÿÿÿÿ=ÿ]) /NoEnd (þÿ  00 0 000ÿÿ;ÿ[) /Keep (þÿ  %) /Hanging (þÿ,.00) >> ] /MojiKumiSet [ << /InternalName (þÿPhotoshop6MojiKumiSet1) >> << /InternalName (þÿPhotoshop6MojiKumiSet2) >> << /InternalName (þÿPhotoshop6MojiKumiSet3) >> << /InternalName (þÿPhotoshop6MojiKumiSet4) >> ] /TheNormalStyleSheet 0 /TheNormalParagraphSheet 0 /ParagraphSheetSet [ << /Name (þÿDefault) /DefaultStyleSheet 0 /Properties << /Justification 0 /FirstLineIndent 0.0 /StartIndent 0.0 /EndIndent 0.0 /SpaceBefore 0.0 /SpaceAfter 0.0 /AutoHyphenate true /HyphenatedWordSize 8 /PreHyphen 3 /PostHyphen 3 /ConsecutiveHyphens 2 /Zone 36.0 /HyphenateCapitalized true /WordSpacing [ 0.80000 1.0 1.33000 ] /LetterSpacing [ 0.0 0.0 0.0 ] /GlyphSpacing [ 1.0 1.0 1.0 ] /AutoLeading 1.20000 /LeadingType 0 /Hanging false /Burasagari false /KinsokuOrder 0 /EveryLineComposer false >> >> ] /StyleSheetSet [ << /Name (þÿNormal) /StyleSheetData << /Font 1 /FontSize 18.0 /FauxBold false /FauxItalic false /AutoLeading true /Leading 27.0 /Tracking 0 /HorizontalScale 1.0 /VerticalScale 1.0 /AutoKerning true /Kerning 0 /BaselineShift 0.0 /FontCaps 0 /FontBaseline 0 /Underline false /YUnderline 1 /Strikethrough false /Ligatures true /DLigatures true /OldStyleFigures false /ProportionalNumbers true /BaselineDirection 1 /Tsume 0.0 /StyleRunAlignment 2 /Language 0 /WariChuLineCount 1 /WariChuScale 1.0 /WariChuWidowPercentage 25 /WariChuOrphanPercentage 25 /NoBreak false /FillColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /StrokeColor << /Type 1 /Values [ 1.0 0.0 0.0 0.0 ] >> /FillFlag true /StrokeFlag false /FillFirst true /OutlineWidth 1.0 >> >> << /StyleSheetData << >> >> ] /FontSet [ << /Name (þÿVerdana-Bold) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.34180 /Ascent 1.00049 /Descent 0.20752 /CapHeight 0.74199 /DistanceToBaseline 0.76465 /UnderlinePosition 0.06787 /UnderlineThickness 0.10303 /HCJKProporitional false /VProporitional false >> >> << /Name (þÿTimesNewRomanPSMT) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.25000 /Ascent 1.00684 /Descent 0.30664 /CapHeight 0.67799 /DistanceToBaseline 0.69336 /UnderlinePosition 0.10889 /UnderlineThickness 0.04883 /HCJKProporitional false /VProporitional false >> >> ] /SuperscriptSize 0.58300 /SuperscriptPosition 0.33300 /SubscriptSize 0.58300 /SubscriptPosition 0.33300 /SmallCapSize 0.70000 >> >> t) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.17627 /Ascent 1.16797 /Descent 0.33057 /CapHeight 0.80699 /DistanceToBaseline 0.79053 /UnderlinePosition 0.10010 /UnderlineThickness 0.04980 /HCJKProporitional false /VProporitional false >> >> << /Name (þÿTimesNewRomanPSMT) /Script 0 /FontType 1 /Synthetic 0 /FontMetrics << /FontSize 1.0 /SpaceGlyphWidth 0.25000 /Ascent 1.00684 /Descent 0.30664 /CapHeight 0.67799 /DistanceToBaseline 0.69336 /UnderlinePosition 0.10889 /UnderlineThickness 0.04883 /HCJKProporitional false /VProporitional false >> >> ] /SuperscriptSize 0.58300 /SuperscriptPosition 0.33300 /SubscriptSize 0.58300 /SubscriptPosition 0.33300 /SmallCapSize 0.70000 >> >> ÜIL=ÿÿD„Ei;ÿÿBÁCô9ÿÿ9C¸D°:ÿÿ´8_94.ÿÿæ;—=Ž1ÿÿƒ?æ@÷5ÿÿË<Ë>j3ÿÿ¨>@³4ÿÿFfG¨;ÿÿ­BJ3ÿÿ”>}@…2ÿÿÜ@ÀBž8žAb9Í:'1š0@8á9ñ/š0^79:.š0X8…92š0<79K/š0y0|2:)š0,.œ/Í)š0ä.§0u)š03^4.Ó¦1f2Á,ÿÿ]Íãÿÿ;ç;o9š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿjþh@rÿÿé2ÿÿïØ,!ÿÿEÐVš0àX¹;š0€€€š0äc€1š0ÖÀš0b°cš0‰ò2š0€€€š0Å;ß8tSš0íJyÿÿO !O#ÿÿ/O¯ÿÿIHçEÁ[š0€€€š0€€€š0€€€š0 bKa~mš0 ´&çÏ÷ «æ$ÿÿMÚXš0_’]*kš0#MÀJ¢`š0È. š0%5!š0ôþ(ÿÿTV•Tœdÿÿ€€€š0Úÿ/š0O !O#š0ôþ(š0äc€1š0€€€ÿÿe#í½?ÿÿíJyÿÿ 37ÿÿ±zzM|š0ü"y¬?š0öžš0FedÍn‚j€€€‚j­›‚p€€€‚p€€€‚pÆ ‰%‚pý¨‚pÉÝ­‚p{ ,}%‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€‚p€€€†x´CCG3.ÓË2$5ÿ#×Ö×AŸCŽ:×Ö>Ø?‹3×Ö;;C=‡1ÓËÉ:¢<‹2Á‰3g5 *kvN?c@w6‡•OC_DÊ8´BD©7q†ï> AÞ4ÄÖ;;C=‡1¸ÈC<Œ>F2ÙÜŒ=û?{2ÿÿ(7a9?-ÿÿÍ3ƒ5*,ÿÿI8†9Þ/ÿÿR9:2ÿÿm7}9Ö.ÿÿÀ4P6^.ÿÿ©4G6Ö-ÿÿË2B4ž.ÿÿ.1Æ2Z-ÿÿ *§+\%ÿÿ{,éÿÿF]m^uZÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€š0Fgfépš0ö6Eš0ÛuFu—zš0€€€š0€€€š0·2v9š0Ù*ÿÿ€€€ÿÿ€€€Ü·Eí= š0BOMø`š0ÏF_D¸Zš0noš0€€€š0’ñ7š0½÷š0€€€š0€€€š0€€€«Tÿ­!ÿÿaa´ÿÿ€€€ÿÿ€€€ÿÿ€€€š0ö/Ã,Jš0qhš0€€€š0Ã2ã7š0‘uΚ0€€€š0<›š0€€€š0€€€Ï𤬕 ÿÿFgfépÿÿ€€€š0öžš01.ý*`Hš0€€€š0øqÇ0š0BTþçÏhêÁÿÿ€€€š0Éñš0€€€š0¦—§ š0åš0€€€š0€€€ÿÿØL¡Jî^š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€whù;é>þ*whz)(,eKb:ÜL6sZŒ<>>ž5lZ)8×9f/q[5y6H,£”Õ1#3G*þüp3û4+C3K6Õ7þ,& 68•-ÅËW5ø6v.¸¶¸1q3×)£¤u2Å3l,•Žq2€4+ÍÔü,i.º%×ÖÕ m"ïÍÔÚ(Â*Q$Ó˸m,njÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÓË€€€ÿÿ´nômÐtÿÿ“.ÿÿ½Ž¼"ÿÿ<ÇUÿÿåC[A§XÏš>¼æ2š0¡ 4  )š0€€€š0€€€š0 ´&š0Ìd¡9š0YLWœgš0­éš0äc€1š057¨š0ƒ\ßZäiÿÿ€€€ÿÿ€€€ÿÿ€€€š0WmU»dš0J–_š0qhš0= œ%š0€€€š06A}>pWš0¯„š0Ò-}* IÿÿhêÁÿÿ¨â:žA€€€š0pôš0¢­.š0( ñn$š0éOZ6š0€€€š0€€€š0eXš0æ1¢.šLš0€€€š04µ Ë*ÿÿ¡%O"Ã@ÿÿÊ y è'ÿÿÓ>:«T§†="š0€€€š0‘uΚ0AIÅFŠ]š0{V¥T|eš0Z ;Ô"š0ä$i!SAš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0Ó:ö=ä)‚pÛ$d'&‚pê/Ü1#)‚p6¶7‚-‚p¬9ì:Ö2‚p{8:i/‚pŒ8h:0‚us;õ<‘2l9 ;Å1‚p'4µ5¥*‚pD2n4*|j°3Ô5·+‚jÜ,û-(rcx/ð0{)pT¿13Å)2û0½2Á(C'2—3Ú)O+³-q/j%Ž‹f!C#ÔçÛB!ÄƵrJ‡KdGXH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€XH€€€¸¶jþh@raa´Êç r.q yÄÖ€€€ÄÖ€€€ÿÿÅ$l3ÿÿÉñÿÿ€€€ÿÿ€€€ÿÿBòÿÿ•@Ì=WWÿÿ“Q‹O+bÿÿŸçÙÿÿÝF0=ÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿBòÿÿça±8ÿÿYLWœg«TÔTš0ž*Õ.š0ï5æ2¹Nš0€€€š0ðll‰tš0ÔTš06A}>pWš0²‚Žš0ï#p ~@š0€€€š0€€€ûótëÿÿé:8ÈQš0€€€š0‰ Lþ$š04%×!²@š0€€€š0½÷š0J–_š0€€€š0u¸Òš0_åË.ÿÿ€€€ÿÿÎD·5š0ö6Eš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€ÿÿkþlÀ_š0®+5.Uš0?S!š09'°)  š0…-µ/Ž$š0_5Ÿ6d.ÿÿ¥759Ø/ÿÿS4Ç5«+š05.0ë&š0ç&“(K!š0O+›,%š0T*#, $š0Ü'º(("ÿÿÔ&Œ(Ü ÿÿŠ$Œ&@ÿÿ· ¤"¿ÿÿÄ!o#š0áHÔJ•Bš0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€š0€€€œ±-`˜^m¦²_øÒ ¦²pd/c«nœ±€€€œ±€€€œ±€€€œ«­›œ«ÖÀœ«¹œ«Ò9 ¦²€€€œ®å*'ºE¥¬<›¥¬€€€œ¥øqÇ0œ¥lýœ¥Áyvy'|¦²€€€¦²€€€ÿÿ> úò$ÿÿÔTÿÿeÑ ¤.ÿÿ‘uÎÿÿ€€€ÿÿ@5=2àMÿÿö6Eÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ`ˆ^3lÿÿlýÿÿ€€€ÿÿkjRsÿÿ¤¬• ÿÿÙP¾NbÿÿÖ/¶,[Iÿÿç0ðÿÿöžÿÿ€€€ÿÿ+ ß&ÿÿÔC ü-ÿÿ€€€ÿÿäc€1ÿÿ†¸ÿÿ€€€ÿÿÌab`]mÿÿË$Jÿÿà ¢c$ÿÿZ ;Ô"ÿÿ=»ºÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿd”e<\ÿÿB;ápW£µpd/c«nœ±€€€œ±€€€œ±€€€”ª3EËBÜXœ® 7"4çNœ®Áyvy'|œ®€€€œ®Âooçu¦²OM`¦²€€€¦²€€€¦²€€€¦²€€€¦²ØL¡Jî^œ®€€€œ®€€€¥¬tRiP&cœ«îS Rbcœ¥ÄcUbvo“¢ÓTìR_dš›%LÜIÑ^óö€€€ÿÿÈb\ahnÿÿFedÍnÿÿ€€€ÿÿ€€€ÿÿ÷NùLC_ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ 7"4çNÿÿÏF_D¸Zÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ‹pÊqÏhÿÿÜ[[]ÐQÿÿŒGÑI­<ÿÿB3D<8ÿÿgBbDç5ÿÿ:JñKBÿÿ[j\ñSÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€ÿÿ€€€warp warpStyleenum warpStylewarpNone warpValuedoubwarpPerspectivedoubwarpPerspectiveOtherdoub warpRotateenumOrntHrzn8BIMluniAcegi8BIMlnsrrend8BIMlyid 8BIMclbl8BIMinfx8BIMknko8BIMlspf8BIMlclr8BIMfxrp@E€ÀSàÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿ´ÿ†ðÿ´¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿¿„ÿ¿´ÿ†ðÿ´# &(*+($"   !  '*037:=?@AABBC@BCD@CCCD>>H>EHFHKJIKJIHIGIIFEHEG>ECB@>=<:86431/-*'$ ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ¶ÿþüøõþòñóôùüÙÿ¹ÿýøòííîïîïíéäáãçíóúÜÿ»ÿûõïëêìæÝÔδÃç÷ñéäàáãêôþßÿ½ÿüóîñäÕ˦ ƒy_8Bp°æãÜÞþßèøàÿ¿ÿþöíîçÓ¼´©›´ÌÔàñÏP_¸äßáâßÝßîþâÿÀÿ úóìëØÇÁ¨˜Øýúÿ ä1%‘ÖäàâÞØÚêâÿÁÿ ùïðàÆÉÍUƒºáà·­¯µ½ÖÍI~çåæçÛÕØëãÿÂÿ"øñì×ÄÖý¨85K:FQRZ`x}~„p8 ´îìëäÐÒÜòäÿÃÿ$öñìÓ»çÿÝX)Aaeqޤ¬±´½·ª›—‹s4ƒÞìðêÞÈÑÝúåÿÄÿ%øõîÔÀâÿöf^‡—ª¸ÁÎÜçãæçãØÃ§•ƒ¥ÎíóðãÌÁÖêåÿÅÿùñõ鿼ýêi>o—ª¸ÓëöùÿûäÞ’ÖíóïæË¤ÇÝûæÿÆÿûòôëÁ‚ëôya©±Äïôÿ ûÛªíóíäÚWyßðæÿÇÿýñôõÓaÂçp|¢´¹Úúñÿ Ü‘ÛöðèÙ'FßçæÿÇÿÿô õàQôW`®·¾èïÿ ý¨Ãøïî½+×ÞæÿÈÿ úòõö~>÷l6•··ííÿ ÈÅõñö™%×ÚýçÿÉÿ ýôøù·$¸Ž„º¼éìÿ ÌÎóîù]6áÙýçÿÉÿ öôøïAn± c´ºáëÿ ÉÚõñÜ"TêØýçÿÊÿ ûõûÿ#™ 3Ÿ½Ôþìÿ üÇïñø–‹èÖæÿÊÿ óøýÜUŒºÄ÷ëÿ íÎöñôU §äÙæÿËÿ øòúÿa=RªÂèêÿ ÙàôôÆÖÙãæÿÌÿ ýõùÿ³‰1”·Õêÿ ûÐôð÷gLðÐïæÿÌÿ õøüõ6Rvn°¿öêÿ 䨸øÆ“èÏþæÿÍÿ úóûÿ“Œ>œ´Ýêÿ ýÅîò÷[&ÛÑÜåÿÍÿ ðøÿÜ yM rÇþêÿ áÎøøÉ{íÆïåÿÎÿ öðüÿ]3 R§ëêÿ ýÂîðö_ ÏÙ×þåÿÏÿ ýïùÿº žB‘Ëéÿ ÜÍøü¸wðÐïäÿÏÿ ôõüõEj“O‚¬÷êÿ ùÍïîò@ÝæÝãÿÐÿ ûð÷øœ(Â!(uÝéÿ Ûãõü}ùÚòãÿÐÿÿõùâ0™z i¯éÿ ôÓòòá$ØâàâÿÑÿ ùö÷ý†=¹ T‹äéÿ Öèóý-ˆòÒôâÿÒÿ ýïñöÒ7¸^&Œ„¾éÿ ë×øø× *âàÞáÿÒÿóèî奜И°º¯ÍÖÖÛéöþðÿ þÏïõø]3›ôÕöáÿÔÿúîâßÛÖÏÚÕÛÛÓÐÎÈÅÄÄÅÊÚðòÿ àÓùÿ¿3?ìÚáàÿ×ÿøëâÜÜááßãâßÛÚØÔÎÎÉÌÉÌÎǺ½Óíõÿ üÌïóð8D»îÒøàÿÙÿùíßÚÝâáâÞßâÞÙÙÕ×ÕÒÊÈÉÇÎÉÌÍǾ·Ìó÷ÿ ØÎõøa SúÒâßÿÛÿ!õèââàáàÝßáÜØÛÝØÒÓÓÑÓÔÖËÌÍËÎÈÉÈÇ»¾âùÿ õÃîñÑgm ÊéÎúßÿÝÿúãÜããÞÛÛ×þÓÐÍÊËÎÍÐÓÄHU’¬¼¹ÏËÈÌÈÉÇÆ´Ïüûÿ ÕÙïêpˆrüÊãÞÿÞÿ'òÝÝäæâØÐÅÉÉÌÎÑÎ˾ÍŸÁ¹+C—†£ÍÏÍÉÌÉÄÂòÁ÷ýÿ éÊïéÂ)ŽfÚßÉüÞÿàÿ*úëÞáæÛÛÖÍÆÀ¿¾É·—Œ’x’¯”ˆYœÆÏ¼»½ÑÖÌÍÈÌÄ»½²¹ùþÿ ÈæôçyW¢‰öÃâÝÿáÿ:ôåàäâÖÒËÍѽ[Vl$'F?)AQ8<…¼Õĺ¼ÓÑËËÇÆ½½°¼øÿãÊ÷ò¸HªG.ëØÆþÝÿãÿ;üëâãäÛÓÍÆ¹”Xb, w Q·-ÊDnˆ'ÌÓ®®ÏÔÎÏÊÃÁÂÁÿÇèðèLa›¦ñ¿æÜÿäÿ;üæàåÛÔÔ¾‘hM#´JD0,0 <^K¯"wŠ YÃÍ·¬ÂÖÐËÊŹ¦¨ËÙðó˜®7;ñÎÇÛÿåÿ<úâáåØÐÉ–J Af76A-(" ¯6LJ=1§ÏÀ¥ÁÑÎÎÆ»±«Ÿìîâ+iŸ ¿ì½ïÛÿæÿ<ýâÜáÔÖµZ5087'&$ ^V;<§5)¯ËÁ£¿ÑÌÇÃÀ´·÷‡!Ë0^÷ÅÌÚÿçÿüäàÝÓÍ. ƒ…†Šzþ;r0²Â°žÉÐÉÄĵžˆ·&•ŒÍà¹óÚÿçÿäàßËÉ‚4$  Iw¢AüN®TKŤ«ÒÇÄǹ°”D7ÎmòÁÓÙÿèÿïãßÊÎyF   wzý6•À«Ž½ÐÊÉÁ¸™m¿‡×Ù»úÙÿéÿ=öãÞÌÕ>*  . s¹†>Dz‘–ÑÑÎËĤ~¥ˆñ·ÚØÿêÿüéÞÇÔ¯H\/ þÿh/šÆ›|¶ÔÍÎΫcq=åÒ¶ýØÿêÿ íàÎÓ¯EJþû,r'KÈœ†˜ÐÍËɹP…¸é¶ä×ÿëÿöàÓÌÍ.<þ 87 o ·Ž)µ¡MdÄËÄ¿½:p©ÈÂÖÿëÿéÕÍÊ^o˜1 þþ!~Yom1`6 ¦&«Ã¿½¹1_’˜åÖÿìÿóÛÐÑpRi+ ý]d†mþ7bi­ˆÇÀ¿³*[™‚ÂÖÿíÿþäÑÖž"# ýÿÿýUtUŠ’-M¸aÄÁº«V›‚‘ï×ÿíÿôÚÕÃDh­‰3 ùþþýþ/·"8½Ã¿˜NŠƒ¼×ÿíÿåÜÐq Qz1  ú ûÿý'%'¸0$¬Â»|]¢ŠéØÿîÿøÚà©  þÿ þ¥¡b)¶)•ºªTh¤‹Š€¹ØÿîÿìÙÒUšŽ,!þ ó '¯"€´›#o ƒŠóÙÿîÿßÞ¨*.c +ýýÿý 0£k‹H‚¡•ƒzÎÙÿïÿùÚÞk   ü   þþ\·™66˜)?"–ž—‰€v¦ÙÿïÿñÜÍ.dr   (%))þÿüþü 8R!Nw 6% ;§›–Š‚yüÚÿïÿîÛ²-kþ þük\B+T¥˜˜Žz‡óÚÿïÿ+é×        ,K þ_”V}8OA%u¢™–“ƒ~èÚÿïÿãÕs"U%  "21'4'8'ýÿ  ŒP[â”þ+p¦g†dx0 @ ›…ƒvÚÚÿðÿþãÖk¸, ! «C % ýý  ]™Ž0"þB{2oŒ;Bk² ›”Ž„‡w×ÚÿðÿþáÊr/ ‰O|Vþþÿþ#']fÇ“Ba„d}ŒVt‡°Ÿ–‹‚„uÏÚÿðÿþãÅk-.¾z[þÿüþ$!pɧµ7$¡—~˜‚¬¨ ›šŽ~tÊÚÿïÿãÅkv¥ rÍ‹›Lþýþþ"I B¸ì ¢¹›Œ¶‰µ¥ œ–yypÑÚÿïÿãÄz?JY;ªŒ².  # üþÿÿ "îä½â­ÌŒ£±§¡™’…|uÜÚÿïÿ 㬚‚Æ>E·þ/!"6þþý»xPÞú·Àè°Í»…²®ª¡—Žz‚îÚÿïÿ䤪(À«% . þ(- Nûþ#|$²ÿá¶æÛÔï‹«®­©¢œ™zw‡ùÚÿïÿ!é«­S!`   062*€;Œaýÿÿ2 …ôÿîÞöÕú¬“±¯«¤¢ —‘zsšÙÿïÿñ·¥ ªHxÁW ý˜j¡}žþþtÈ3\ìþÿýùþÚŽ¬©­¨£¢ –Ž~t³Ùÿïÿûʼn®É€þþ+¹5H•,þ°Wƒž<rNCÖûÿ펤§ª­¨ž£Ÿ”…x{ÓÙÿîÿ Üx¤cY"Qþ¢žK¤šs‚d ý}•.Æûÿ󤜨¦©¬¨š–ˆxŠðÙÿîÿBøšn°"¿vošÓ¥i‡‚"'Ï{/·ôüÿþÿÿôŽ‘©¦©«ª¤š˜“†w¦ØÿíÿÓQŸ[…0ƒm• ýþ#“M ·A.a1±¯~¤öÿ÷ð‰« ¢¨«¨£œ––’‹yÕØÿíÿõƒMÂV…d]þ(s«fº L†CCR‚Жm–²¨¤¢¥¥¢ž•“—”‹˜ùØÿìÿÕNeË6DÀ1rüþû"Õ2§IhD%+1RZޱ§¡£¦ £œ™™š•ˆÊ×ÿìÿý¸sÁ3$L·´G(þÿ( ” ro$Co§«¦¢¡¥ª¦¦Ÿ£š™”Žšø×ÿëÿ=ú›uÅH„\?¾®D>Ofh™C¿JyR 1~««¡¢Ÿ¢¤¦¨¥Ÿ£›š‘†ÍÖÿêÿ<ùŸ[¼w ŸÀ‰'ÍQÅ/.=<:86431/-*'$ ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ¶ÿþüúøþõóõ÷úþÙÿ¸ÿûõðîìíïïëæãÝãèïöûÜÿ»ÿþùóëæåÜÓÈÆ®ºÜëçàÙÛßâìöþßÿ½ÿýõïðàÌÁŸ˜‰v\7@k§×ÓÐÕ×Ûâëúàÿ¿ÿþøîëâζ¯¢™³ÊÕÞðÍŸUY©ÕÒ×ÚÛÜâñáÿÀÿ ýôèãп»¢Òýúÿ ã:%ŠÈ×ÖÚØÖÜïâÿÁÿ ûòéÓºÁÈ‹Nr¬Ýܲ§©®¸ÏÇM" wØÙÝß×ÓÛíãÿÂÿ"úòåɺÓý¢22H;CHMW\murx„m@¨àääßËÍÞòäÿÃÿ$ùóãİæÿÚL%<]`k‚—žŸ¢¯¯ Žˆ|i0zÑäéæÛÀÎÞûåÿÄÿ%úöçǸàÿöbW}ˆ˜¥²ÃÔáÞâäÞÒºš‡t½äìíâ¼ÔëåÿÅÿúôðÞ¶¼þêg;gŒ™¦Éèõùÿûá¼|ÃàêíæÆ¢ÃÞüæÿÆÿüõï⻃ìôuX‚š£½îôÿ ûÕ‘˜áéåß×VsÛðæÿÇÿþôóîÍdÄèns”£±×ûñÿ Ø„Ííêá×)DÙææÿÇÿ ÷õñÚV…õXXœ©·çïÿ ýŸµíèæ¼)ÑÞæÿÈÿ ûõòí„Føo5†¨²ìíÿ À´ëèò™$ÕÚýçÿÉÿ þöøöµ-º‘zª´éìÿ Ľêæö[4ß×ýçÿÉÿ ÷öøîKw³_¤±áëÿ ¿ÎïìÚ"Sç×ýçÿÊÿ üöùÿ2¢#1”±Ñëÿ û¹æíó”ŠåÖæÿÊÿ öùþÜ‹Zƒ­Àøëÿ ê¿óìïT¨áØæÿËÿ ùôûÿaFˆNŸºéêÿ ÑÕñìÃרäæÿÌÿ ý÷ùÿ³ “2‹®Öêÿ ûÆíêñfMíÌïæÿÌÿ ÷ûüõ7Z€f¤½÷êÿ âÑóðà “ãÌþæÿÍÿ ûóýÿ•“8‘«Þêÿ ýÁéìòX&ÚÊÚåÿÍÿ ïöÿà#€Rk“Æéÿ ßÈïïÇ|çÀïåÿÎÿ öïüÿ_6¦L†¡ìêÿ ý¿êéï_ÎÑÓäÿÏÿ þíöÿ¾£Hx‹Êéÿ ØÆñ÷¸wîÌðäÿÏÿ ÷óöñFpšK{¨øêÿ úÇéèïAÛãÜãÿÐÿ ýðïïœ+Ç&#o‹Ýéÿ ØÞòùœ}öÖòãÿÐÿ øïòÞ0ž} cz¯éÿ óËíðá%!ØÞÞâÿÑÿ ûôî÷…?¾ R†Žäéÿ Óäîû‚8ˆïÏôâÿÒÿ þîçìÍ9ºb$‡¾éÿ êÓöôØ*àÜÝáÿÒÿòàäॢӜ±»²ÐÙÙÝê÷þðÿ þÌíôö]=œïÓöáÿÔÿûðäàÝÚÒÜØÜÛÕÒÐÊÉÈÅÆÌÚðòÿ ßÑùÿÁ> @ëÕáàÿ×ÿùíåÞàåæäåãàÝÛÚÕÏÑËÏËÍÐȼ¿Ôíõÿ üÈêñï:&P½ëÎùàÿÙÿúñåÞàååæáãåßÚÚÖØÕÒËÈÉÈÐËÌÎÉ¿ºÍó÷ÿ ×ÈíðŒ oTúÏâßÿÛÿ!öíççåäáààãÜØÞßÙÓÔÓÒÔÔ×ÌÌÏÌÐÉÊÊȼÀãùÿ ô¾çêÌ!rq ÍæËûßÿÝÿ%üçáêåßÝÜÖÒÔÔÑÑÏÍÒÏÐÓÅJ\“°¾»ÐÊÈÍÊÊÉÆ¶Ðüûÿ ÑÏæát,“sûÈäÞÿÞÿ'õäãéêäÚÐÆÊËÏÐÐÎÌÁÎǻŽ9 §ÍÐÏÉÌËÆÂĶÂ÷ýÿ éÆçá¿7˜nÛÛÉüÞÿàÿ*ûïäèíÝßÛÐÉÁÀÁÊ·”˜€‡—¯•’XÃÓ¾¾ÀÔ×ÍÎÈÌÆ¿¿´½ùþÿ ÄÞëÞeª‹öÀãÝÿáÿ:öëèéçÚÓÏÎÒ–mjRLS>cV>;I\IM‹¾ÕǾ¾ÓÏËÍÉÇ¿Àµ¾øÿãÇôí´S´M0ìÖÆþÝÿãÿ;üîæçêÞÖÑÊ»œmr\Q›°cŒËgvØ}Uš<)!1’ÎÕ±°ÐÔÎÐÌÆÂ¢ÄÿÄâêãRn£©ï¼èÜÿäÿ;üéåêàØÖÅ›shPeȇmugsq]‘VÂiZ£¡1 _ÇÏ»°ÄØÑÊÊŽ«°ËÓçê˜&¶9=óËÇÛÿåÿ<úäæêÛÕÍŸ^Dc~{€oljqha^`XQcÃoT\ƒf\rB6ªÐêÃÒÍÍÆ½³¯¡äåÜ6v¢ ÃéºïÛÿæÿ<üäâäÕÙ¼lS]}‚wtrmomdYfe]\‹…QqOYZTTxÀy',´ÍçÂÒÌǸ–³í‡.Ï0aúÄÎÚÿçÿ=üæäâÕÑ™EJk{qmpsrpnml^P^bY¥¢¦¥žcTYWbZP~… ;¹Æ³¤ËÒËÇŸ£µ.žÌÞ»ôÚÿçÿ<çäãÏÎ’NYxqnoppopommki^HNY®w–¶uMQTWXUˆÅ1SȽ©®ÔÊÇȽ´œM=ÑlìÁ×Ùÿèÿ=ñéäÍЄ=z|mnooppopnnmjie@6A¨•œZKOQSVVh^JiIð”ÀÒÍÊż¡vÀ‰ÓÔ½úÙÿéÿ=÷èáÑØŒ9xillmmnopponljfgU-LjRIOPMQSWUYÌ«Cʶ˜šÔÕÑÎǧ†© †î¸ÜØÿêÿ üìâÊ×µ]ˆ€ypiýk.lnonlkefdP,?0CNLKNORSVV]•oRA É „»ØÏÏѰqz<àкýØÿêÿ=ðãÑ×´?}x{sghiijklmmljhfdM0BR%4UJIJOQNOURISoŸ8NͤŸÔÏÌÎÀ^·ç¸æ×ÿëÿ=÷ä×ÏÏE\ˆywuvmghghhjllkjhgaK,JA+>PGIGSpsUhœºÉ´T»§WnÇÍÆÄÃGz­ÇÃÖÿëÿ ìØÏÊk}·{wuvuogþh,ijjkllij]G&I?8!@FDX …“qq^KL“¬ .²ÅÂÁÂ;iš›æÖÿìÿ>õÝÓÕ{6Œ˜zwwvusighhiijiijjf`D$O6"%+A;†„W§—NSW]yš2l· ’ÉÃÁ¹2`¢‹ÆÖÿíÿþèÕÙ¦!`lsztuttslýhÿj*ihge^]/1L2"%3G©”ok|fbeggfb^_fhggisT4Mph)&!!4NRSVYZ]Z`]R27±,–^'©›ŽŽ‰ÒÙÿïÿûâàwUfinkrm]]hg\þX0\coo[E7M`RM; $=OSVYY\]TË»W=¤ 8Y::Ÿ¥ž“Œ…¯ÙÿïÿEôãÑ?” pmllneZ[fov~|€pTACUSQ50E&5 (FOSVXY[\Z_t‚8U…&K@Q®¢Ÿ•…šýÚÿïÿEóá¹,8¹–mmlinoa^SZksni^RPY^dH2?,5;6)FGPPNVXWZUNK; pnZK 9f¬ Ÿ—†ôÚÿïÿEîÚ›@ignljhefigg\ZTVX_ghpPO\,57%6-+EALj¥b‚XUUS’µŽJ‰J j_-C‚©ŸœšŠŠéÚÿïÿEë×U–wllggjaakss~†{ƒdLR3SC!4(204_Dª{‰å²MRUk˜¾‚™-'}Š@$Z¤¦ —˜…ÝÚÿïÿEë×vªÐzmgk·½\[[\`rZcSZ]3SA5W..)I#kRHж¬Ÿ¤qgPKLDM’$B‰—P\z¶§£›—ŽƒÚÚÿðÿþçÌ|!gþn=iª~›ˆXWWQUYOF^G\C7S1AL0C#jaOUNi^ŽY“Ö´}X=m˜!zŽ–l…¶¥¥Ÿ•Œ‚ÓÚÿïÿEèÈw \~skzÌ«ŠfRURPX\AORDY0>E(LC5#J_RUUTRSRQSd˜ÕÉ3œ¿RB³¡‹¦Œ²¯§£¡—ˆ‹€ÏÚÿïÿ'èÉyŠÂpffÓ¥±‡KLRMSYS5V?GG(MIL=(/HXSTTUTþUÿVPJ[nSÃò¨­Ä¢™¼“¹­©££œ„…}ÖÚÿïÿEèĈ cw`ˆ“|¾«ÇwWLMQYa`M?aQvFTM48HPWUTSTUTUUVVZjQWžñìÆìµ—Ó“ªµ®©¥ ™‰€ÞÚÿïÿE實%9rªÒ„Èh``bYNMSYhh^{paL@Aez[QSUVUTTUXWWRbÒ¦[^äÿÆÊî·Ñ¾Ž¸²±©£Ÿ–‡„‹ïÚÿïÿ$æ©¶/4×Äucj}med`^YNNYnlib_fu~udRNˆ\QTUþVWXQTRf¡4(¿ÿïÌïàÞñ’²´³®©£ —…ƒ‘ùÚÿïÿDê°·c!cfqiehec_]XQTM]l~€|l_Sa¦w¯JUVUUWWUv^Qk)”÷ÿøíúâý°›µµ²«©§ž™‡€¢Ùÿïÿ0ò¼ªž AvÀ‰fiheca[T£Ô‡PNGIIFGNRµ‹½¤ºQVWVVTWNžØw@jñýÿþÿÙ“±­±¯«ª¦œ—йÙÿïÿ#ûÈ’¸#&ݦbchgeb`WqÇh€¶lLNOMJM]Ç@ƒ¥¸xPþW`USP¡nPÞûÿí’««®³¯§«§›„†ÖÙÿîÿ-àƒ¯kdsŽee`_]V[¸·¾WRRQNJLO¹œ¥ŒdfURVM¤µQZ:=Ðûÿò¤¡°¬¯±­¤¥¡’„“òÙÿîÿ.ù¡y»%iÓ£Z_]ZXWœ²Ü¹•KSPOLINM\«¤bNTZlUTaÛ¨-=Å÷üýÿô‘–°­°±°ª£¢ š„­ØÿíÿAÕ\ªŒi°Y\e[XVPl¦”²cPRPONKLSPMF³LVÌzPPmw?¾¯†¯÷ÿû𓱧©¯°¯ª¢Ÿž™“…ÙØÿíÿõŒ\Ë]D^®–NQVP]J_RþQ+PMKKRTTIœÄMKÍXN"Y¨ˆ@F^Õ r›¶¬«ª¬¬©¤œŸ›“ ùØÿìÿ?×ZnÒ=j×`SrTIœ¶IGORPNNKJNQPPRcâoLOÃux›K*0:^f•¶­¨«®¦¨£¢¡¡¢Í×ÿìÿý¾,Ì:HU‰ËQLÊwEh]þL*PKGNR^dTM»¶XS3,„z2  Ox®³®ª¨«°­¬§ª¡¢›”¡ù×ÿëÿ=û¢-ÎN!§HzÏMLÅxByƒG_—PG˜·IP€ÓF\Š] #'=‡°±¨«§©«¬¯®©«¢¡˜ÐÖÿêÿ/ú§+eÄ EfİGbÑ\@¬¦@iÜWE‡×wn?&I…~J 'Y£¹°¥Ÿ©þª §­­®¥šœ‘§ûÖÿéÿ:ö³Nb­ªV o\RÍ_ZÁ Zxá}pj\0J“¡o7-$ %.Au­¹¯«¬©ª®®«ª¯¨¬¤›™˜åÕÿèÿ8õÌ•iŽº˜\&*F:YqhYPS(4p­¾‚N94?>*0k«º³°¬­¯¯«­«¨¬¬ª¨ šÌÔÿçÿ7ï×·…™·¼§€Y?*4Y®Ýë´fF2>C8P|©¼¶±°¬«®­®«¨¨©¬©«¤¡–±ûÔÿçÿ6ýéÙμÃáÛÚÍÌÁ­ž¢£·ÆÖìýÿúš@%LNTpޝº´¬®¯°¬«¬­«©ª©¨©¥¨£œªôÓÿæÿ4úÞÐÏÉÆÒÙäëóøûÿýüÿÿûõíØ±^JhƒŸ±½»¸¶¯ª¯¯®®±­¬¨«¯«ª©¨¦ž¥éÒÿåÿ2õÖÏÊÂÆÈÄÄËÊÌÆÌÑËij«¨£¢­¼Äý¶¶·±­³°±²°¯®©©¬°¬¨««¦¡žÞÑÿäÿ0ïÐÍË¿ÄÇÆÅÇÁ±°¿¾Á¾»½¿Ä»¼½»»º¸²¯°¯¯±°®¦§§¬¯ª¨©ª¢œÔÐÿãÿ.äÈÇÈËÄÅÄÄ¿À·½Áº¼¹¸»»º¸·¹º»¾·¶¶²´³±²®¦¦§©ª«ª©¡ÔÏÿãÿüÛÂÄľ¿ÃÀ¼º¹Á¼½¿½¿½»þº¼½¹²²·³´´³¯®¯¬¨¦¨ªª¢§ØÎÿâÿù̼¾¿»½¹µ¹«¯¹»¾ÁÁ¿¾¼·¹½¶µþ°´²´²°°­­©«¦©¨ž§çÍÿáÿñÁ¶¹º¹±°··§²·¸º¾¼¸µµ²±®°þ¯ÿ°²­®­­þª¨¤µìÌÿàÿ'í¼®µ¶´³´º°¨¶²³ºº·´³®®¬­¬°±¯­­¬¨ª«¦¨£ž§ÐùËÿßÿ$óÀª²³±¯±´²µ¶³¸¸±¯«©¬®¨¥©ª¬¬ª«¬§¨¥¡¦ÅíÉÿÞÿ!üÔ¬¤ª¬®±°°µ¶´µ²¯¬¨ª§¡¡ ¤£¨¦§¬¥œ¤¾çÇÿÜÿìĨŸ¦ª®««±¯¯©§¢šž ž£ ¡¥¨££ §ÀäüÆÿÚÿíȬœ›™œ¤¦£™š™˜ ¤¢ŸŸž¤µÐðþÄÿØÿ÷áÇ® žþ˜ —›˜™œš¤±¹ÑåûÁÿÕÿúíäØÎÁ¾½»ÂËÒÞñùþ¾ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ" &(*+($#    &+038:=?AAABBCACCDBCDDFFGHIKJKKKKLLLKLKKJJGFEGGEECB@>><:86431/-*'$ ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ‚ÿ¶ÿ ýøòíæèêæëîöúþÚÿ¹ÿüòãÙÔÐÏÎÏÍÇÆÁÉÒÞëùÜÿ»ÿùêÙËÄĺ²¦¡…³ÆÀ¾¹ºÂËÞñþßÿ½ÿúãÐÎÀ© |pcYN3Ax£©®¶¶¾ÊÝ÷àÿ¿ÿýëÓž°—‘ˆ~œ¼ÊÕ齇=*o§°´»ÁÅÑêáÿÀÿ ÷Ûü¯§¨k·üúÿ ÌT–³±¹¾ÁÆæâÿÁÿ òÔî ¶Å1Bq±¸€tz|­•'M¥­·¿ÂÁÇçãÿÂÿ"îѾ¬«Îÿ¤ 11BJ@@Q9n¯½Àú¸ÌïäÿÃÿ$ìл§¥æÿØ9 3>Lcry{{‹‘}g[N8G˜¹ÄÊɲ¸ÏûåÿÄÿ%ïÕÀ¥ªßÿóS,Sdu€‘§½ÒÍÓØÍ¼œw];J€±ÂÍθ­ÃæåÿÅÿòÓÉÁª¼ÿéXEds…³ÞòùÿöРj?~¨¼È픪ÏüæÿÆÿ÷ÖÈí„îòf<[v…¤çôÿ ø½dQ¦»¾ÅÎPPÂîæÿÇÿýÜÌ̾`Äèe\s‚”Êúòÿ ýÃI‘¾ÁÈÎ*+¹áæÿÇÿ èÐÊÁNƒöT@yˆ¤âïÿ úrvÀÁË´¶ØæÿÈÿ öÖËÏ}G÷n!eˆœèíÿ ¢x½ÃÛ“»ÕþçÿÉÿ ýÜÓן*»’ VŠãìÿ ¦…¼ÀãZ&ÃÓþçÿÉÿ ëÍÔ×A{³ A‚™Ûëÿ ›—ÃÈÉ DÏÐþçÿÊÿ ÷ÖÓâ9°"r”Æëÿ ú޶ÅÖŒlÐÎæÿÊÿ ßÑÞÆ”`a°õëÿ áŽÉÈÙPËÒæÿËÿ ìÈÖêSM‘/~¨åêÿ »¤Ëγ½ÆâæÿÌÿ ýÙÑç ™9b™Íêÿ û ÃÇÙa>Ô¾ðæÿÌÿ çÖÝÛ.]‚@ˆ²÷êÿ פÍд ~ÌÁþæÿÍÿ õÑÚꀘi™Ûéÿ ¤¾ÈÜTÁ·ÕåÿÍÿ ÖÏæÇT>v¼éÿ ÖŸÇÏ·kͯîåÿÎÿ êÆÙéS4§+`èêÿ þ£¿ÂÓW ²¼ËäÿÏÿ ýÌÌß«©MOpÂéÿ ÍÉÕ¨cλïäÿÏÿ åÉÊÑ=t£-[™÷êÿ ù©¿ÂÖ<ÀÊÓãÿÐÿ ÷ÊÃÊ…*È(LwÛéÿ Ê·ÊÚ’jÛÈòãÿÐÿ ß¾ÅÂ*¡€?]£éÿ ñ¬ÃÉÌ#¹Å×âÿÑÿ ïȾÓt?½ 1gáéÿ »Èáz1uоôâÿÒÿ û̳Á´2º^fn¹éÿ å±ÐÕÈ"ÆÅ×áÿÒÿݳ¼Ä—˜Ê «¥ÈÑÒÙèöþïÿ µÄÔáW?…ÖÆöáÿÕÿþ÷çÌÇËÇ¿ÉÂÊÊÆÆÄ¼¾¿¼ÀÇÙðòÿ ×¬Ôæ¶B$4ÎÀÛàÿ×ÿõãÓÇËÑÎÌÍÉÇÆÅÄÃÇÈÁÆÄÆÈ¿³¸Òíõÿ ý°ÀËÛ7%V¤ÓÂùàÿÙÿõáÏÇÇËÍËÆÊÊÄÂÁÁÃÃÊÃÂÄ¿ÉÄÆÇÀ·²Êñ÷ÿ ÌŸÂÏ€pFà»ÝßÿÜÿ"þðÝÑÍÊÉÅÂÇÈÁ¿ÄÆÁ¾À¿¿ÈÌÒÆÀÅÅÈÂÃÂÁµ·àùÿ ôœ»Äµhx·Ð¾úßÿÝÿ%ùÙÊÍÌÅÃÄ¿º¿ÁÀ¿¾»ÂÂÁÁµAT‰¡²­ÆÃÂÆÂÄ¿®Ìüûÿ Ä£¾Çj'›`àµáÞÿÞÿ'íÏÌÒÏÆ¿¼µºº½¼»»¹ª¼´¢¬«/•‹š½ÇÈÃÅÅÁÁÀ®À÷ýÿ 梻¾¯4›rÀÿýÞÿàÿ*ùáÍÏÓÂÈÆ¼µ®«¬»¡x€bp}–trHi³Ð»µ²ÊÎÅÇÂÇ»»±¸øþÿ ®¯ÅÂyl²xÞ°àÝÿâÿ;þîØÎÑÎÂÀ¾ÁÀ­{PSpFCˆQ@cN;::E/3u«É½´¶ÌÉÃÅÂÅ»¾´¹÷ÿÝžÇÍ£O¼Y$ÒÆÀþÝÿãÿ;ûßÍÎÏÆÁÁ¹¦‡VaTX¡¯nšÎy‡Û‰j©¢G-|ÀÓ±ªÇÎÅÉÅÁ¾Ãœ¿ÿ©³ÀÈGm®’Ö¯çÜÿäÿ;ü×ÈÍÅÁƳ…^TJiÉ}‹}uƒ~n‰—eÇvo¯©7 K¶Í¹«ÀÓËÂÆÃ·©¬¿©¹ÅŠ$¿C2Û»ÂÛÿåÿ<øÓÉÎÂÁ¼ŒK6\އƒ†zyw€ztrogctÇ|hnŽwr€D$™Ë¨¾ÍÅÆÃ¶²³¹¼Æ3x««Ö±ïÛÿæÿ<ûÑÄÊÀɲ^BY…Ž„~}zqkxwpp•“e€epojj‰É‹2!£ÈǦºÉÅÿ¾·’Ë}/Õ6L߸ËÚÿçÿ=ûÕÇÈ¿ÀŽ:Hw…€‚…„ƒ„€}pfrso±¬³¯¥vlnqtok‘Š$©Æ¶ ÈÏÈö¨|œ.¢›¯Ë¶õÚÿçÿÖÇȹŠF[‹…€€‚ý€(radj¹†£½€dlmonl—Éœ@@½¿ª¬ÓÇÀÆ»¹žE9ÔWÒµÕÙÿèÿ=ãÌɸȇ;y‚‚‚€~~yY8MWµ¢§meglknn|rd~T†Âµ™ÀÔÎËÈĪt½¹Â¸ûÙÿéÿ=ðÉüЋ5y†‚‚ƒ€€}}xzp57Ga|h`glhkoqmn¨Ï¶$1À½Ÿž×ØÓÔÑ´„£#rÖ¯ÛØÿêÿ>úÓÀµÏ´Q‡‚‚‚‚‚~yyxgC-SJ`jghmjmoppvŸ}iX ‰ÊªŠ¾ØÑÕܽqu2Á¾¸þØÿêÿÞÆºÌ²9w€‚€€ý‚ÿ'~|t^JUgBTpihglmijqqajƒ°B<Æ­—¦ÙÔÔ×Í`‡¦Ð³ç×ÿëÿ=ñżÁÌ=\‡~€|{|}}‚‚~}|qcLgaE>Ykggel…‰o€§À˼g¬±^sÏÔÐÏÒMsªÀÅÖÿìÿ>þ×»½Êeu³~‚‚}}€~€‚‚~k^Gf^M?;[hbl«•œ¢†›ref€³*·ÏÊÌÐC\ ¢çÖÿìÿ>êÂÁÏx0‰‘|€‚~{|}~€€€~t_ElTCE>IaZ‘“n¬¢jmqr‰©8Xµ•ÕËËÇYklnqtuvwv„„]"µ=0»ÍÆ—$_« ¬ïØÿîÿôÎЭ&0pghpn|z}}{yyþ~,~qjhUx~JEC94:;Qhmpsu{|vyÂÅ‘(µ<,©Ã¸xn­–œ›ÊØÿîÿ åÏÄ^¦¦tmwcq{}þ{2yx€€xqaNrŒ`FAA<4>9Tlnqusy|vyvtW$°2#—À°O&u¦™š¤÷Ùÿðÿÿþ ÔС/>£Œgj€hamþxÿv1wuz}{|€cNi‡DF??=>;9\mpsxvx|z{toO*¨*4¤o,/Š©¡“–ÙÙÿïÿDöÎËhShgjfpt_`rtplnror}zjUOjzgXP=<9:>7AapruvxzypÌÃg0¡CmP5&Aœ¦¡—‘ºÙÿïÿEìϼ3 ‰˜qnghqr`\hw~ˆ…‰‡w`S[prfMJS?88BV2Ohqtvuyywuw‡”FFŠ"[Y5,7Z«¤¤–ŽŒ¥üÚÿïÿEéͨ3¯Žnmihiqpj[`kqpmb\`ntvbLRKKJ;2VN=igmmptvtvojf]b ld7&Nj¨¡£šŽ‹›öÚÿïÿEàÄ‹ =ijnkkjdajowmfafhqvvzb]eFIKAK?Kj3ep|«pnuxrº™e }c€uD/X¦¡›“Ž“ìÚÿïÿEÛÁnLvmjg_b[]esyƒ…†Ž„€hZ\F\TFO>Wc°…Žá¸jqo~¤É’—G=™šXAgœ¤¡“š”–àÚÿðÿFþÜÁe£Éyohb¤¨oWTY]^lcjZ^`I_RJ^C;CCf„„mqgtr ×¸ŒrZ fµK4™ª«†œŽ®¢¡ž•”ŒØÚÿðÿ(üÖ²dYysoy¼—qYSQOQY^OXZO_DNP=ZPMA>h{nqppþoÿny¤ØÐE ÛxcÑ»¥¸˜©¨¢žž–†ˆÓÚÿðÿ#þÕ²gƒ¼pph•ÃŽ›zMMONTWZGZGMQ@ZX_M>Kgvþpþqrpqtmet†JÎýÇÆÞÀ²Æ•²©§¡¢œ€‡ƒ×Úÿðÿ$þÒ­xb|f‰Žw°¥Âq[QNQW]\TIb[wRbZAC]osqpþqrponrsziw+Ÿ÷úå÷ҹߛ£®ª¦¤ ˜Š‡àÚÿïÿEÏ”™;v§Ì~ŠÀihfiaUVVWbd_zreTJN`rpkqqnqppqqonpzÒ­vWèÿìçõ×âÆŽ¬¬ª£¢¡”†…“ñÚÿïÿEÖ§*1ÒÁxlt†uppmkh`acnmhbenz„„q`bomqlkppqpmrn{²=¿ÿüñúîðô˜§§«¬©£¡˜ƒƒ–úÚÿïÿDÝ”¥Xkmsrrvppmlj`^^mzˆŠ‰‡|tim§}³–brmlpnor‡oj†? Œùÿýúýòÿ·•ª®­¦¦§ œ†¨Ùÿïÿ0å•“Ex¹ˆqxwponnc¡Í…\dacc_^cd´‘Á¤»emmnqloi©×„T^ñþÿÿþÿÜ“§¥­ª¥¥¦œ—ˆ¼Ùÿïÿõ®y­#פlqvurpnk}Âl‚³xcþgaemÇNŒ¦¹‡golmpfli¯{DÚûÿð–¢£§¬©£ª¦ŠÙÙÿîÿ-Îc¡c |mzqvtqpke³³|»eihhecgc»›¡“r{mooc©¶dqN/Ìûÿôªœ¦£¤¬© ¡¡ž“„˜òÙÿîÿ,ï`±lΤkrqmlh›«Ö¯”`kggdbgeo±ªmbkn{ihmÝ­:.Äûÿö—¥¢¥¥©£žš š†²ØÿíÿA¿:™f¯eholmlfzª—¯nhgfgeegkgdZ´ejÍ…ef~0ÃÊ©Ëûÿÿõš‡¤››¤§§Ÿ›œ˜’‡ÛØÿíÿAìj?¾SGk®™cekgj‘]thifggecdkkl`£ÅaeœÎig.M°¤RWy¡å¹y‘«¢Ÿž¢¢ œ–—œ™“ ùØÿìÿ?À5\Æ1hÔjfyf`´\bhkhheadejihhqß|edÈ} k£W,7Ioe‡§ ›£œŸ›™œž™‘Ï×ÿìÿ?öŸoº/FaÉc`Ç|Zsnfb`he^fknqh_¿¸hg?|3Rm™£ œ›¥££ž¥œ›”¥ù×ÿëÿ%ð‚o½A¡“XÌ[^Ã[€ƒ[sš`bŸ¸[eÕNMƒX þ -x¡¡ššŸþ£Ÿ¦ž¡šÓÖÿêÿ<í…Q±kChÄ®\mÍgV¯¦TxÛeYÙwF) :yv<Bލ¡™•œ›¡¤¨¤ ˜œ‘¨úÖÿéÿ:â,G›˜IlWW‘ÌkfÁže€àvrf4 5€•`%_›© œž›Ÿ¤¦¢¢¥¡£Ÿ—–šåÕÿèÿ8Þ¬sIw£‚L(F:WpdWOU(V“ªp5(W™ª¤¢£¡ ¢¢¡Ÿ š–ÍÔÿèÿ8ý×»˜du•œŒgD/   üÿÅUáþÿó‚düÿØ>ûjêýÿ£býÿüºdüÿØ>Jýÿ¾bÿÿ¶ÿ@Ïýÿçq ÿì‚~~[<ùÿŸL|üÿpcÿèhmÙÿÇý"6ÿÿ{A\­·bÿèfïÿ“cÿèhmÙÿÇjèÿ¦Hcþÿeÿ/ïÿÈ]J€ò²ŸÿÓü£ÿÇþ ÿÜ`ÿЂÿÔý/gÿùR bÿÒžÿ¼aÿЂÿÔÓÿZcÿìÿêvÿ ÿÓþ; ŸÿùÜÛàkÎÿ„þ Jÿú\ÿæftßÿƒü4,÷ÿÿñÂt cÿ×,Õÿ”bÿæftßÿƒÕÿccÿœ°ÿ˜yÿ|Ïÿ‡>jd_4 ŸÿùÜÛàjÕÿ|þCÿü\üÿ‡ûC»õþÿ ·`ÿÿýÿÿÛ%cüÿ‡Õÿccÿ’%òøÔÿ|Õÿ~¢þÿ¥ ŸÿÖ ±ÿ±þ wÿé_ÿÝYãÿ¡ûI©ÿÿ\ÿï£ucÿÝYãÿ¡ý Ôÿ^cÿzþÿ ~±ÿ¿#Láÿ ŸÿÔýWÿýhBçÿbÿÒNÿÿxü f¸Luÿò ^ÿÓû"cÿÒNÿÿx 2ÜÿcÿÏÿÿ€Pÿÿ—# Öÿ¢ªÿäüˆÿÿþÿÿµjÿäÿÿWý_þÿþÿôfiÿäü jÿäÿÿLBýÿ½hÿ¨Bÿÿ‰øýÿþ—P€kû@‡¢‘U2€kw‚dþ K„ŸŸz.2€kü2€kw‚^$‚€€‚^0€Oþ_€@þ5€Ÿœw>­3­3­3­3­3­3­3­3­3­3­3­3­3­3­3­3­3­3­3­3­™­™­™­™­™­™­™­™­™­™G93?ECCBC>@>@GEFKG9=Gÿ%?|œžŒ[ GHGK+2JGHD?|œžŒ[;IùGJLüGHE CHþGL$9IþGI;±ûÿêh Üþÿ°Ñþÿ½±ûÿêhÔ÷ÿRqúÿø'ðüÿ‘ âüÿÔ°øÿRœþÿÛóþÿ{°øÿPÔ÷ÿRqúÿø(ðüÿ¸ôüÿÔ]÷þÿíÉýþÿ§\þÿô>þÿû. ÷þÿíÉýþÿ£Õ÷ÿUqúÿø(ðüÿÛ:ýüÿÓ‘ýÿ{ßþÿËñÿÿþ2dþÿ×Sýÿ{ßþÿÉ •¼¹óýÿ˵¾6uýÿã´¹² ðüÿôWûÿÓ¢ýÿ`ÖþÿÙ»þÿY…þÿ”eýÿ`ÖþÿÙ ÓýÿGþ€ýÿ›ýðûÿ1nûÿÓŸýÿ ˜“½·½˜xþÿ‰²þÿPcýÿ ˜“½·½˜ÓýÿGþ€ýÿ›ýðûÿ\…ûÿÓyþýÿŒ û 5ûÿÿ·áÿÿèBþýÿŒ úÓýÿGþ€ýÿ–ýðþÿïúÿ‡¥ÿøçþÿÓ;ÞüÿÒCü Øÿÿñûÿÿ«ÞüÿÒCûÓýÿGþ€ýÿÎ{ƒjðþÿÑñÿ´ÍÿïÉþÿÓeûÿûƒý—ûÿhþeûÿûƒýÓýÿGþ€úÿÙ ðþÿ°èÿáõÿâ«þÿÓÿkøûÿ¤þYüÿö'ýkøûÿ¤þÓýÿGþ€úÿÔ ðþÿ’ÞÿþÿÿÇ¡þÿÓþ6Ïûÿ|þïýÿÃü6Ïûÿ|þÓýÿGþ€úÿÔ ðþÿ†¿ýÿ¨™þÿÓýŒüÿÚ þ¸ýÿ}úŒüÿÚ ÓýÿGþ€ýÿ·@H;ðþÿ}¢ýÿ‡þÿÓNœ AZýÿ÷(þƒýÿLþ,œ AZýÿ÷(ÓýÿGþ€ýÿ˜ýðþÿt‚ýÿm‹þÿÓƒýÿ}¼ýÿFþ€ýÿFþKýÿ}¼ýÿFÓýÿGþ€ýÿœýðþÿoeýÿMþÿÓýÿ~™ýÿIþ€ýÿGþGýÿ~™ýÿIÓýÿGþ€ýÿ–ýðþÿsDþÿû/’þÿÓdùþÿ„¨þÿþAþ€ýÿGþ0ùþÿ„¨þÿþAÓýÿGþ€ýÿÎ{€…-ðþÿv&üÿÿñ–þÿÓ>èþÿÚ‹ðþÿõ!þ€ýÿGþèþÿÚ‹ðþÿõ!ÓýÿGþ€ùÿeðþÿzòÿÿÛ˜þÿÓ •øÿ·ý€ýÿGý•øÿ·þÓýÿGþ€ùÿ_ðþÿ|Ûÿÿ½™þÿÓ«úÿÇ!ý€ýÿKý«úÿÇ!þ ÙýÿKþ€ùÿeðþÿ}»ÿÿœþÿÙÿOÇ×ʤZ ü@‰€$üOÇ×ʤZ ýj„€$þ@‰ü€…0x‚€‰?O‡‰@N‡€„j´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´3´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™´™WKBRZXXUVNGJTUTTWVDJXÿ?|œžŒ[þCHüGK+ý%k– cý$LGGK*BHGHE CHþGI:)ý$LGGK'IùGI6&KGHG EHGL,±ûÿêhðúÿœˆ÷üÿñyþ€ýÿ—îþÿø'ðüÿüùì–€ýÿZ÷ÿÈWýÿ^Býÿj°øÿTðúÿœ–øÿ„€ýÿ˜îþÿø(ðøÿª€ýÿ[÷ÿÏéþÿ…rþÿ÷(]÷þÿíÉýþÿ§ðúÿ5ûþÿôÃ÷þÿò€ýÿ—îþÿø'ðýÿûýÿû6€ýÿ]÷ÿÕ¬þÿ¨•þÿÄ‘ýÿ{ßþÿË ðþÿýõÁpyýÿ™®ýÿU€ýÿ—îþÿø'ðþÿøL˜ýÿi€ýÿ‘>½´Óýÿë·¼˜lþÿÌÀþÿ‚¢ýÿ`ÖþÿÙ ðþÿø+ý‘ýÿ~™ýÿq€ýÿ—îþÿø'ðþÿ÷@ýÿ€ýÿœþcýÿ·ý -øÿÿéäÿÿþ?Ÿýÿ ˜“½·½˜ ðþÿø+ýýÿ~œýÿ€€ýÿ—îþÿø'ðþÿø!=ýÿ€€ýÿœþcýÿ·ý ÎÿÿñgñÿÿÛ yþýÿŒ üðþÿö&ýœýÿ~œýÿ€€ýÿ—îþÿø'ðþÿöMýÿs€ýÿœþcýÿ·ü ‹ÿÿ÷°ùÿÿ˜;ÞüÿÒCýðþÿû–}…1œýÿ~œýÿ€€ýÿ—îþÿø'ðþÿú•ÏýÿD€ýÿœþcýÿ·üLÿÿýóþÿYeûÿûƒðúÿhœýÿ +KGGL$€ýÿ—îþÿø'ðúÿþí€ýÿœþcýÿ·üèüÿíÿkøûÿ¤ðúÿcœýÿ€ù€ýÿ—îþÿø'ðúÿý¨€ýÿœþcýÿ·û«üÿ²þþ6Ïûÿ|ðúÿcœýÿ€ù€ýÿ—îþÿø'ðþÿû¯àþÿÑ€ýÿœþcýÿ·ûküÿnþýŒüÿÚ ðþÿúfBJœýÿ N‡€€‰@€ýÿ—îþÿø'ðþÿ÷[ýÿd€ýÿœþcýÿ·û*÷þÿ÷*þNœ AZýÿ÷$ðþÿ÷(ýœýÿ~žýÿ€€ýÿ—îþÿø'ðþÿø ?ýÿ€€ýÿœþcýÿ·û ØþÿØ þƒýÿ}¼ýÿBðþÿø,ýýÿ~œýÿ€€ýÿ—îþÿø(ðþÿø ?ýÿ€€ýÿœþcýÿ·ûÓþÿÓþýÿ~™ýÿEðþÿö&ýŠýÿ~™ýÿq~ýÿ–îþÿø'ðþÿø ?ýÿ€€ýÿœþcýÿ·ûÓþÿÓþdùþÿ„¨þÿþ=ðþÿû–|„jrýÿˆªýÿUfýÿš ðþÿò ðþÿø ?ýÿ€€ýÿœþcýÿ·ûÓþÿÓþ>èþÿÚ‹ðþÿõ ðúÿÙ=þþÿ߉ìþÿö&?þþÿß¡ýþÿÒ ðþÿø ?ýÿ€€ýÿœþcýÿ·ûÓþÿÓþ •øÿ· ðúÿÓÄøÿ˜þºøÿhðþÿø ?ýÿ€€ýÿœþcýÿ·ûÓþÿÓþ«úÿÇ!ðúÿÙ ,Ðúÿž þÀúÿŠðþÿù"Cýÿ€€ýÿžþiýÿ»û ÙþÿÙ þÿ OÇ×ʤZ x‚ü€ „jeªË×ÇFûW¤Ê×ÊžFþx‚€‚| €‰@@‰€€‡Nþ2…€†\ûj„€„jþ¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡3¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™¡™%&&&&&&& þ.LCç ˜ž<ÿ ×ÿÿOçêô]ÿLþÿ ý >i^&Bl\þ \](+%8:ÿ ¡ÿ¼öí½þÿñ ½ÿúÿè<1ßÿýñþÎ çñ[$ïø-ËÿfšÿÂ1<­(“ÿ}hÿ½±ÿ¯&rÿÖ óý` fÿ¿„ÿ» éÿ>þåÿ²Ÿ´ÿìîÿ6EÿÖ óü` »ÿòÚíÿù+óü+þñÿ²¥¥š‚ðþ2DÿÖ óü`$,úû¾¾»ëÿ|Âÿ}B¿ÿt A Àÿ­?ÿÔ óü`ÿ³þ‚ÿÜGùÿÍÔù$Cùÿ׿õÝFòÿÿïÿÖ óýbaŽ<þ!4—ľ{ 2¿Å£T#T:jÿÊz0è?³zåÿ|üè6Ýÿÿá…üÜ3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3Ü3ܙܙܙܙܙܙܙܙܙܙܙܙ8BIMPatt!%"(*,-85IHIIHJII,,""#"""!xmk~Œ‘”†Š”˜—˜˜˜‡Ž—EEEF@@J@‚}Š“‰‰‰‰”‘“’‚††GEDB@?><:‰І…~~yus!$"(*,-85IHIIHIII,,"!""""!xmk~Œ‘”†Š”˜—˜š™‡šEEFGGIJK‘„‚“‘‘‘‹Œ‹•‘”‘„†GEDB@?><:‰І…~~yus!$"(*,-85JHIIHIII,,!!""""!xmjŒ’”Œ‡Š”˜—˜˜˜‡Ž™EFFHHIJK“„‚“‘’‘‹Œ‹•’’„†GEDB@@><:‰І…~~yprÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿ¹ÿþüøõþòñóôùüÕÿ©ÿ¼ÿýøòííîïîïíéäáãçíóúØÿ©ÿ¾ÿûõïëêìæÝÔδÃç÷ñéäàáãêôþÛÿ©ÿÀÿüóîñäÕ˦ ƒy_8Bp°æãÜÞþßèøÜÿ©ÿÂÿþöíîçÓ¼´©›´ÌÔàñÏP_¸äßáâßÝßîþÞÿ©ÿÃÿ úóìëØÇÁ¨˜Øýúÿ ä1%‘ÖäàâÞØÚêÞÿ©ÿÄÿ ùïðàÆÉÍUƒºáà·­¯µ½ÖÍI~çåæçÛÕØëßÿ©ÿÅÿ"øñì×ÄÖý¨85K:FQRZ`x}~„p8 ´îìëäÐÒÜòàÿ©ÿÆÿ$öñìÓ»çÿÝX)Aaeqޤ¬±´½·ª›—‹s4ƒÞìðêÞÈÑÝúáÿ©ÿÇÿ%øõîÔÀâÿöf^‡—ª¸ÁÎÜçãæçãØÃ§•ƒ¥ÎíóðãÌÁÖêáÿ©ÿÈÿùñõ鿼ýêi>o—ª¸ÓëöùÿûäÞ’ÖíóïæË¤ÇÝûâÿÝÿÚÂÉúçÿ÷…ÏïÿÉÿûòôëÁ‚ëôya©±Äïôÿ ûÛªíóíäÚWyßðâÿÞÿ÷S33ÀçÿóD<µïÿÊÿýñôõÓaÂçp|¢´¹Úúñÿ Ü‘ÛöðèÙ'FßçâÿÞÿÂþ3ýÿ úÍ«´áÿÿûÊ©µëþÿ ìµµßÝáÿýÒÑíïÿÊÿÿô õàQôW`®·¾èïÿ ý¨Ãøïî½+×ÞâÿÞÿ ~3i:Aìÿÿêhþ3>åñh373EÏÿØM35>4ZýöF>¶ïÿËÿ úòõö~>÷l6•··ííÿ ÈÅõñö™%×Úýãÿßÿ#ì@9Û]3­ÿÿ„3dØÏu߉3›ÿ¬3hÿq3sá¤3Týõ=5²ïÿÌÿ ýôøù·$¸Ž„º¼éìÿ ÌÎóîù]6áÙýãÿßÿ ­3fÿ•3iÿ÷E3ÍþÿóH3q€o3BæA3ÔÿÈ3Týõ=5²ïÿÌÿ öôøïAn± c´ºáëÿ ÉÚõñÜ"TêØýãÿßÿ i3=QA38Ýù=5Ýþÿó>3q{{„—ì?4×ÿÉ3Týõ=5²ïÿÍÿ ûõûÿ#™ 3Ÿ½Ôþìÿ üÇïñø–‹èÖâÿàÿ$Ü76ggiC3œÿd3›ÿþÊéf3¢ÿÿøËøe3uÍ3Uýõ=5²ïÿÍÿ óøýÜUŒºÄ÷ëÿ íÎöñôU §äÙâÿàÿ3pþÿ—3OýÆ83[U8âÉ83Sf;NÿÇ=33@3Týõ=5±ïÿÎÿ øòúÿa=RªÂèêÿ ÙàôôÆÖÙãâÿàÿ±Ïþÿ嘘ìÿÕ†bgöÿ×fa}¼ÿÿã¼Ñª3]ýû™ÙïÿÏÿ ýõùÿ³‰1”·Õêÿ ûÐôð÷gLðÐïâÿÇÿÍp˜H3œêÿÏÿ õøüõ6Rvn°¿öêÿ 䨸øÆ“èÏþâÿÇÿÔN33K•ùêÿÐÿ úóûÿ“Œ>œ´Ýêÿ ýÅîò÷[&ÛÑÜáÿ©ÿÐÿ ðøÿÜ yM rÇþêÿ áÎøøÉ{íÆïáÿ©ÿÑÿ öðüÿ]3 R§ëêÿ ýÂîðö_ ÏÙ×þáÿ©ÿÒÿ ýïùÿº žB‘Ëéÿ ÜÍøü¸wðÐïàÿ©ÿÒÿ ôõüõEj“O‚¬÷êÿ ùÍïîò@ÝæÝßÿ©ÿÓÿ ûð÷øœ(Â!(uÝéÿ Ûãõü}ùÚòßÿ©ÿÓÿÿõùâ0™z i¯éÿ ôÓòòá$ØâàÞÿ©ÿÔÿ ùö÷ý†=¹ T‹äéÿ Öèóý-ˆòÒôöÿýÍœ‚¶íþÿüÉÅüÆÃÝþÿÿᩇŒ°çýÿâÂÆÆÃÝýÊÅÆÅÈöýÉÅþÆÅÑÞôýÿâÂÆÆÃàëÅùÆÅÔáÃÆÅÆðÿöÈÅÆÂÜïÿÕÿ ýïñöÒ7¸^&Œ„¾éÿ ë×øø× *âàÞöÿéqû3D¬ÿÿó?ú3‚ÿÿù’9ü3>žþÿ™ý3†úAþ39àù?ü358B‡ñÿÿ™ý3Ž·÷3_¹ý3´ÿÊý3ªïÿÕÿóèî奜И°º¯ÍÖÖÛéöþðÿ þÏïõø]3›ôÕö÷ÿìrø3¼ÿó?ú3‚ÿÿ‡ø3•ÿÿ™ý3…úAþ39ßù?ø3wÿÿ™ý3޶÷3YèEþ3•ÿ¤þ39ßïÿ×ÿúîâßÛÖÏÚÕÛÛÓÐÎÈÅÄÄÅÊÚðòÿ àÓùÿ¿3?ìÚáöÿµ9þ3A^5þ3yÿô?ú3ÿÕ6þ3­>33PøîÿàÿúãÜããÞÛÛ×þÓÐÍÊËÎÍÐÓÄHU’¬¼¹ÏËÈÌÈÉÇÆ´Ïüûÿ ÕÙïêpˆrüÊãôÿž4ý3öüÿó?þ3:áýÿ‚3þ3šÿ‚ý3™ÿ™ý3†úAþ39àù?þ3:ëÁý3£ÿ™ý3‚þÿ°ý3müÿ339r833…íÿáÿ'òÝÝäæâØÐÅÉÉÌÎÑÎ˾ÍŸÁ¹+C—†£ÍÏÍÉÌÉÄÂòÁ÷ýÿ éÊïéÂ)ŽfÚßÉüôÿÐMü3WÉýÿó?þ36‡›•Øÿ‚3þ3šÿ‚ý3™ÿ™ý3†úAþ39àù?þ37ˆYý3Éÿ™ý3‚þÿ°ý3müÿÂ335=þ3¸íÿãÿ*úëÞáæÛÛÖÍÆÀ¿¾É·—Œ’x’¯”ˆYœÆÏ¼»½ÑÖÌÍÈÌÄ»½²¹ùþÿ ÈæôçyW¢‰öÃâòÿ®û36–ûÿÿó?ú3¬ÿ‚3þ3 ™ÿÝÃÆÆÂâÿ™ý3†úAþ39àù?ú34AŒþÿ™ý3‚þÿ°ý3müÿñEü3Aííÿäÿ:ôåàäâÖÒËÍѽ[Vl$'F?)AQ8<…¼Õĺ¼ÓÑËËÇÆ½½°¼øÿãÊ÷ò¸HªG.ëØÆþñÿ©9û3|ûÿó?ú3°ÿ‚3þ3™ùÿ™ý3†úAþ39àù?ú35yëÿÿ™ý3‚þÿ°ý3mûÿvü3qìÿæÿ;üëâãäÛÓÍÆ¹”Xb, w Q·-ÊDnˆ'ÌÓ®®ÏÔÎÏÊÃÁÂÁÿÇèðèLa›¦ñ¿æïÿÔYû3œÿó?ú3°ÿ‚3þ3™ùÿ™ý3†úAþ39àù?þ36sLþ3Xíÿ™ý3‚þÿ°ý3mûÿ©ü3§ìÿçÿ;üæàåÛÔÔ¾‘hM#´JD0,0 <^K¯"wŠ YÃÍ·¬ÂÖÐËÊŹ¦¨ËÙðó˜®7;ñÎÇíÿùü3Qûõ?þ37­ÊÄéÿ‚3þ3 ™ÿÁ“™™‘Ìÿ™ý3†úAþ39àù?þ39é¶ý3¯ÿ™ý3‚þÿ°ý3mûÿÝ9þ39Ýìÿèÿ<úâáåØÐÉ–J Af76A-(" ¯6LJ=1§ÏÀ¥ÁÑÎÎÆ»±«Ÿìîâ+iŸ ¿ì½ïñÿÁ‚Ë·ý39âù?þ39ßýÿ‚3þ3šÿý3™ÿ™ý3†úAþ39àù?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿøRþ3Røìÿéÿ<ýâÜáÔÖµZ5087'&$ ^V;<§5)¯ËÁ£¿ÑÌÇÃÀ´·÷‡!Ë0^÷ÅÌðÿ–ý3›ÿiý3Êü?þ39Üýÿ3þ3šÿ‚ý3™ÿ™ý3†úAþ39ßù?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3VùìÿêÿüäàÝÓÍ. ƒ…†Šzþ;r0²Â°žÉÐÉÄĵžˆ·&•ŒÍà¹óðÿ™ý3šÿ…ý3Èü?þ3:áýÿ‘3þ3šÿ…ý3¥ÿšý3‡ûAþ39àù?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3VùìÿêÿäàßËÉ‚4$  Iw¢AüN®TKŤ«ÒÇÄǹ°”D7ÎmòÁÓïÿ¯8þ3•ÿyþ34Îû?þ36‡œ•ªÿ¤3þ3’ÿwý3»ÿ­ý3„õ?þ3=ð÷?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3VùìÿëÿïãßÊÎyF   wzý6•À«Ž½ÐÊÉÁ¸™m¿‡×Ù»úïÿÍEþ3Q?þ3;éø?ú3QÿÎ4þ3M‘Bþ3:áÿÍ4þ3M~5þ3Wýõ?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3Vùìÿìÿ=öãÞÌÕ>*  . s¹†>Dz‘–ÑÑÎËĤ~¥ˆñ·Úîÿøˆø3mÿõ?ú3Vüÿbø3…þÿjø3¬ÿó?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3VùìÿíÿüéÞÇÔ¯H\/ þÿh/šÆ›|¶ÔÍÎΫcq=åÒ¶ýíÿòvú3`åÿó?ú3QøÿÜYú3õþÿèeú3‘ÿÿó?þ38äÉý3™ÿ™ý3þÿ«ý3iûÿøQþ3Qøìÿíÿ íàÎÓ¯EJþû,r'KÈœ†˜ÐÍËɹP…¸é¶äëÿ ýÀ`S]|·÷ÿÿùŸ—ü™•ªüÿÿô®w]S`Çûÿù¹|]S]ÇþÿùŸ—™—œò嘘™‘ÌÿÌ‘™™“Áþÿו˜™”µûÿüª•™•ªüìÿîÿöàÓÌÍ.<þ 87 o ·Ž)µ¡MdÄËÄ¿½:p©ÈÂÒÿ©ÿîÿéÕÍÊ^o˜1 þþ!~Yom1`6 ¦&«Ã¿½¹1_’˜åÒÿ©ÿïÿóÛÐÑpRi+ ý]d†mþ7bi­ˆÇÀ¿³*[™‚ÂÒÿ©ÿðÿþäÑÖž"# ýÿÿýUtUŠ’-M¸aÄÁº«V›‚‘ïÓÿ©ÿðÿôÚÕÃDh­‰3 ùþþýþ/·"8½Ã¿˜NŠƒ¼Óÿ©ÿðÿåÜÐq Qz1  ú ûÿý'%'¸0$¬Â»|]¢ŠéÔÿ©ÿñÿøÚà©  þÿ þ¥¡b)¶)•ºªTh¤‹Š€¹Ôÿ©ÿñÿìÙÒUšŽ,!þ ó '¯"€´›#o ƒŠóÕÿ©ÿñÿßÞ¨*.c +ýýÿý 0£k‹H‚¡•ƒzÎÜÿýÍœ‚¶íÿÿöÆÅÆÃÝÿÿ×ÄÆÅÉûÿýÍœ‚¶íÿÿýÐÅùÆÄíæÂüÆÅÈöýÉÅþÆÂâÿþÑÅþÆÅÐíÿòÿùÚÞk   ü   þþ\·™66˜)?"–ž—‰€v¦Ýÿéqû3D¬ÿ÷Oþ3rÿüXþ3hÿëqû3D¬ÿúU÷3½¥ú39àù?ü3‹ÿöJü3UíÿòÿñÜÍ.dr   (%))þÿüþü 8R!Nw 6% ;§›–Š‚yüßÿìrú3ÿ3½ÿ‚þ3Pýë=þ3ÿrø3¿ÿU÷3½¥ú39ßù?ü3lÿè<ü3UíÿòÿîÛ²-kþ þük\B+T¥˜˜Žz‡óßÿµ9þ3A^53ÿ3yÿµþ3<ñÍþ36Úå9þ3A^5þ3}ýU÷3»¥ú39ßù?ü3PÿÑ5ü3Víÿòÿ+é×        ,K þ_”V}8OA%u¢™–“ƒ~èßÿ‹ý3ÿM3ÿ3]ÿë>334ׯþ3Sÿ½ý3ÿMþ3^÷ˆik=ý3]ngÔ¡ý3Iokqé÷?ü3<ó¹û3VíÿòÿãÕs"U%  "21'4'8'ýÿ  ŒP[â”þ+p¦g†dx0 @ ›…ƒvÚßÿ}ý3²ÿT3ÿ3Qúÿiþ3¸•þ3‰ÿ®ý3²ÿTþ3QøÿÿùVý3Æþÿ™ý3ƒýÿó?û3اû3VíÿóÿþãÖk¸, ! «C % ýý  ]™Ž0"þB{2oŒ;Bk² ›”Ž„‡w×ßÿ€ý3…ÿ‰hmh…ûÿŸþ3‘qþ3¿ÿ°ý3 …ÿ‰hmh…ûÿÿùVý3Æþÿ™ý3ƒýÿó?û3µ•û3VíÿóÿþáÊr/ ‰O|Vþþÿþ#']fÇ“Ba„d}ŒVt‡°Ÿ–‹‚„uÏßÿž4ý3öÿüÿ Õ633mK33EðÿÊ4ý3öúÿùVý3Æþÿ™ý3‡ýÿó?þ3@73“{39Fþ3VíÿóÿþãÅk-.¾z[þÿüþ$!pɧµ7$¡—~˜‚¬¨ ›šŽ~tÊßÿÐMü3WÉüÿ øR33>633vÿÿñMü3WÉûÿùVý3Æþÿ™ý3Z–ªÿô?þ3X>3o[3@^þ3VíÿòÿãÅkv¥ rÍ‹›Lþýþþ"I B¸ì ¢¹›Œ¶‰µ¥ œ–yypÑÞÿ®û36–ûýÿ†û3¬þÿ®û36–ûýÿùVý3Æþÿ™ú3Qüõ?þ3rE3K;3Jvþ3VíÿòÿãÄz?JY;ªŒ².  # üþÿÿ "îä½â­ÌŒ£±§¡™’…|uÜÝÿ©9ü33|ûþÿ¸ü3:àýÿ©9û3|ûþÿùVý3Æþÿ™ú3Uýõ?þ3ŠM3433`~þ3Víÿòÿ 㬚‚Æ>E·þ/!"6þþý»xPÞú·Àè°Í»…²®ª¡—Žz‚îÜÿÔYý3ÿ3œþÿì@ý3cýüÿÔYû3œþÿùVý3Æþÿ™ú3Uýõ?þ3”fý3y…þ3Víÿòÿ䤪(À«% . þ(- Nûþ#|$²ÿá¶æÛÔï‹«®­©¢œ™zw‡ùÛÿùþ3ÿ3Qøþÿlý3›úÿùü3QøÿÿùVý3Æþÿ™ý3mÌÅÐÿô?þ3›}ý3“þ3Víÿòÿ!é«­S!`   062*€;Œaýÿÿ2 …ôÿîÞöÕú¬“±¯«¤¢ —‘zsšÞÿÁ‚Ë·33ÿ39ßþÿ–ý3Âþÿ܂˷ý39ßÿÿùVý3Æþÿ™ý3…ýÿó?þ3¢—ý3¨þ3Víÿòÿñ·¥ ªHxÁW ý˜j¡}žþþtÈ3\ìþÿýùþÚŽ¬©­¨£¢ –Ž~t³Þÿ–ý3›ÿi3þ3Çþÿ™ý3ÇþÿÃý3›ÿiý3ÇÿÿùVý3Æþÿ™ý3‚ýÿó?þ3¦®ý3Áþ3Víÿòÿûʼn®É€þþ+¹5H•,þ°Wƒž<rNCÖûÿ펤§ª­¨ž£Ÿ”…x{ÓÞÿ™ý3šÿ…3þ3Åþÿ™ý3ÆþÿÆý3šÿ…ý3ÅÿÿùVý3Æþÿ™ý3‡ýÿó?þ3£Éþ36ÙŠþ3Víÿñÿ Üx¤cY"Qþ¢žK¤šs‚d ý}•.Æûÿ󤜨¦©¬¨š–ˆxŠðÞÿ¯8þ3•ÿy3ÿ34Ëþÿ™ý3ÆþÿÙ8þ3•ÿyþ34ËÿÿùVý3Æþÿ™ý3Z™•Ûù?þ3¡á533>ó‡þ3VíÿñÿBøšn°"¿vošÓ¥i‡‚"'Ï{/·ôüÿþÿÿôŽ‘©¦©«ª¤š˜“†w¦ÝÿÍEþ3Q?3ÿ3;åþÿ™ý3ÆþÿñEþ3Q?þ3;åÿÿùVý3Æþÿ™ù3®ÿ?þ3ù=33Pÿ…þ3VíÿðÿÓQŸ[…0ƒm• ýþ#“M ·A.a1±¯~¤öÿ÷ð‰« ¢¨«¨£œ––’‹yÕÝÿøˆú3ÿ3mýÿ™ý3Æýÿˆø3mþÿùVý3Æþÿ™ù3³þ?þ3œÿP33hÿ…þ3VíÿðÿõƒMÂV…d]þ(s«fº L†CCR‚Жm–²¨¤¢¥¥¢ž•“—”‹˜ùÜÿòvû33`åýÿ™ý3Ãýÿòvú3`åþÿøQý3Ãþÿ™ù3®ÿ?þ3›ÿi33‚ÿþ3QíÿïÿÕNeË6DÀ1rüþû"Õ2§IhD%+1RZޱ§¡£¦ £œ™™š•ˆÊÚÿýÀ`S]|·÷üÿÌ‘™˜˜âüÿýÀ`S]|·÷ýÿüª•™˜˜âþÿÌ‘ü™˜•ÙÿŸ—™‘ÍÿÀ“‘ÌÿÁ“™•ªíÿïÿý¸sÁ3$L·´G(þÿ( ” ro$Co§«¦¢¡¥ª¦¦Ÿ£š™”ŽšøÓÿ©ÿîÿ=ú›uÅH„\?¾®D>Ofh™C¿JyR 1~««¡¢Ÿ¢¤¦¨¥Ÿ£›š‘†ÍÒÿ©ÿíÿ<ùŸ[¼w ŸÀ‰'ÍQÅ/.d¢÷ÿ°3SñÜU3‰ÿ±3G­¢M3–ÿÿùU3°ÿÿ°3‚r3…ž3œÿY3“ÿͪ¯³Õíÿãÿ'츪¯²±¯±µ«¦²¬®¶¶´³²ªª§§¨¬­¬©©¨¥§§¡¤Ÿš¢Ìù×ÿ €38OPLªÿU3œþÿÉ35èµü3“üûÿÉi;þ3 mþ²33533Páÿ°ü3“üÿÿùU3°ÿÿ°3Šá=9U3œÿU3šÿ}þ3{íÿâÿ$ò»¤­°­«®²¯±²°´µ­¬©¥§ª£ ¤¥©ª¦¦¨¤£Ÿ›¡ÁìÕÿ €3Tôùøýÿq3qþÿ 3Eý³3N¸I3~ûÿòÿÿíÅx33ëµ3@}¡íÿÿ°3N¸I3~ýÿ U3´ÿÿ°3ÿþ3 šÿq3fÿãÂK3íÿáÿüѧž¤§¨þ¬±³±²®ª§¢¥¢œ ž¢¢¤§ —ž¸åÓÿ€3Uüýÿ¹35¬óÊF3 ÿ±3WÿÁ33Ÿüÿ ­lÂñü¡3=õ´3Vûÿ"°3WÿÁ33Ÿÿ÷×O3™êÿ°3ÿùY33™ÿ¿33†ãøT3}íÿßÿë¿£™¢§§¨­«¬¥£ž•šœ™ œ¡¤Ÿœ›¡ºâüÒÿw3Iùüÿ’33433n ñÿª3IúÿŽ33¹ýÿ³þ343<­ÿ«3Iúüÿ ª3IúÿŽ33ÂÊý3hÿ¬3yÿÿÊ33‘ÿÿ˜9ý34†íÿÝÿìŨ—””™Ÿ¡¡š–”““œ œ›™™Ÿ¯ÍïþÐÿ¿™©üûÿÌ“}‹»ýÿÿ ×™©üÿù —¯þþÿ øÃ•€€Úÿÿ×™©üüÿ×™©üÿù —´â—™™—´ÿÙ™Àþÿ³™ÌþÿÕ™€‚ ÍòíÿÛÿ÷ßꜙ˜”••“—””—• ¬µÎäû½ÿ©ÿØÿúëâÖʽ»¸¸ÀÉÏÜðùþºÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿ¹ÿþüúøþõóõ÷úþÕÿ©ÿ»ÿûõðîìíïïëæãÝãèïöûØÿ©ÿ¾ÿþùóëæåÜÓÈÆ®ºÜëçàÙÛßâìöþÛÿ©ÿÀÿýõïðàÌÁŸ˜‰v\7@k§×ÓÐÕ×ÛâëúÜÿ©ÿÂÿþøîëâζ¯¢™³ÊÕÞðÍŸUY©ÕÒ×ÚÛÜâñÝÿ©ÿÃÿ ýôèãп»¢Òýúÿ ã:%ŠÈ×ÖÚØÖÜïÞÿ©ÿÄÿ ûòéÓºÁÈ‹Nr¬Ýܲ§©®¸ÏÇM" wØÙÝß×ÓÛíßÿ©ÿÅÿ"úòåɺÓý¢22H;CHMW\murx„m@¨àääßËÍÞòàÿ©ÿÆÿ$ùóãİæÿÚL%<]`k‚—žŸ¢¯¯ Žˆ|i0zÑäéæÛÀÎÞûáÿ©ÿÇÿ%úöçǸàÿöbW}ˆ˜¥²ÃÔáÞâäÞÒºš‡t½äìíâ¼Ôëáÿ©ÿÈÿúôðÞ¶¼þêg;gŒ™¦Éèõùÿûá¼|ÃàêíæÆ¢ÃÞüâÿÝÿÚÂÉúçÿ÷…ÏïÿÉÿüõï⻃ìôuX‚š£½îôÿ ûÕ‘˜áéåß×VsÛðâÿÞÿ÷S33ÀçÿóD<µïÿÊÿþôóîÍdÄèns”£±×ûñÿ Ø„Ííêá×)DÙæâÿÞÿÂþ3ýÿ úÍ«´áÿÿûÊ©µëþÿ ìµµßÝáÿýÒÑíïÿÊÿ ÷õñÚV…õXXœ©·çïÿ ýŸµíèæ¼)ÑÞâÿÞÿ ~3i:Aìÿÿêhþ3>åñh373EÏÿØM35>4ZýöF>¶ïÿËÿ ûõòí„Føo5†¨²ìíÿ À´ëèò™$ÕÚýãÿßÿ#ì@9Û]3­ÿÿ„3dØÏu߉3›ÿ¬3hÿq3sá¤3Týõ=5²ïÿÌÿ þöøöµ-º‘zª´éìÿ Ľêæö[4ß×ýãÿßÿ ­3fÿ•3iÿ÷E3ÍþÿóH3q€o3BæA3ÔÿÈ3Týõ=5²ïÿÌÿ ÷öøîKw³_¤±áëÿ ¿ÎïìÚ"Sç×ýãÿßÿ i3=QA38Ýù=5Ýþÿó>3q{{„—ì?4×ÿÉ3Týõ=5²ïÿÍÿ üöùÿ2¢#1”±Ñëÿ û¹æíó”ŠåÖâÿàÿ$Ü76ggiC3œÿd3›ÿþÊéf3¢ÿÿøËøe3uÍ3Uýõ=5²ïÿÍÿ öùþÜ‹Zƒ­Àøëÿ ê¿óìïT¨áØâÿàÿ3pþÿ—3OýÆ83[U8âÉ83Sf;NÿÇ=33@3Týõ=5±ïÿÎÿ ùôûÿaFˆNŸºéêÿ ÑÕñìÃרäâÿàÿ±Ïþÿ嘘ìÿÕ†bgöÿ×fa}¼ÿÿã¼Ñª3]ýû™ÙïÿÏÿ ý÷ùÿ³ “2‹®Öêÿ ûÆíêñfMíÌïâÿÇÿÍp˜H3œêÿÏÿ ÷ûüõ7Z€f¤½÷êÿ âÑóðà “ãÌþâÿÇÿÔN33K•ùêÿÐÿ ûóýÿ•“8‘«Þêÿ ýÁéìòX&ÚÊÚáÿ©ÿÐÿ ïöÿà#€Rk“Æéÿ ßÈïïÇ|çÀïáÿ©ÿÑÿ öïüÿ_6¦L†¡ìêÿ ý¿êéï_ÎÑÓàÿ©ÿÒÿ þíöÿ¾£Hx‹Êéÿ ØÆñ÷¸wîÌðàÿ©ÿÒÿ ÷óöñFpšK{¨øêÿ úÇéèïAÛãÜßÿ©ÿÓÿ ýðïïœ+Ç&#o‹Ýéÿ ØÞòùœ}öÖòßÿ©ÿÓÿ øïòÞ0ž} cz¯éÿ óËíðá%!ØÞÞÞÿ©ÿÔÿ ûôî÷…?¾ R†Žäéÿ Óäîû‚8ˆïÏôöÿýÍœ‚¶íþÿüÉÅüÆÃÝþÿÿᩇŒ°çýÿâÂÆÆÃÝýÊÅÆÅÈöýÉÅþÆÅÑÞôýÿâÂÆÆÃàëÅùÆÅÔáÃÆÅÆðÿöÈÅÆÂÜïÿÕÿ þîçìÍ9ºb$‡¾éÿ êÓöôØ*àÜÝöÿéqû3D¬ÿÿó?ú3‚ÿÿù’9ü3>žþÿ™ý3†úAþ39àù?ü358B‡ñÿÿ™ý3Ž·÷3_¹ý3´ÿÊý3ªïÿÕÿòàäॢӜ±»²ÐÙÙÝê÷þðÿ þÌíôö]=œïÓö÷ÿìrø3¼ÿó?ú3‚ÿÿ‡ø3•ÿÿ™ý3…úAþ39ßù?ø3wÿÿ™ý3޶÷3YèEþ3•ÿ¤þ39ßïÿ×ÿûðäàÝÚÒÜØÜÛÕÒÐÊÉÈÅÆÌÚðòÿ ßÑùÿÁ> @ëÕáöÿµ9þ3A^5þ3yÿô?ú3ÿÕ6þ3­>33Pøîÿàÿ%üçáêåßÝÜÖÒÔÔÑÑÏÍÒÏÐÓÅJ\“°¾»ÐÊÈÍÊÊÉÆ¶Ðüûÿ ÑÏæát,“sûÈäôÿž4ý3öüÿó?þ3:áýÿ‚3þ3šÿ‚ý3™ÿ™ý3†úAþ39àù?þ3:ëÁý3£ÿ™ý3‚þÿ°ý3müÿ339r833…íÿáÿ'õäãéêäÚÐÆÊËÏÐÐÎÌÁÎǻŽ9 §ÍÐÏÉÌËÆÂĶÂ÷ýÿ éÆçá¿7˜nÛÛÉüôÿÐMü3WÉýÿó?þ36‡›•Øÿ‚3þ3šÿ‚ý3™ÿ™ý3†úAþ39àù?þ37ˆYý3Éÿ™ý3‚þÿ°ý3müÿÂ335=þ3¸íÿãÿ*ûïäèíÝßÛÐÉÁÀÁÊ·”˜€‡—¯•’XÃÓ¾¾ÀÔ×ÍÎÈÌÆ¿¿´½ùþÿ ÄÞëÞeª‹öÀãòÿ®û36–ûÿÿó?ú3¬ÿ‚3þ3 ™ÿÝÃÆÆÂâÿ™ý3†úAþ39àù?ú34AŒþÿ™ý3‚þÿ°ý3müÿñEü3Aííÿäÿ:öëèéçÚÓÏÎÒ–mjRLS>cV>;I\IM‹¾ÕǾ¾ÓÏËÍÉÇ¿Àµ¾øÿãÇôí´S´M0ìÖÆþñÿ©9û3|ûÿó?ú3°ÿ‚3þ3™ùÿ™ý3†úAþ39àù?ú35yëÿÿ™ý3‚þÿ°ý3mûÿvü3qìÿæÿ;üîæçêÞÖÑÊ»œmr\Q›°cŒËgvØ}Uš<)!1’ÎÕ±°ÐÔÎÐÌÆÂ¢ÄÿÄâêãRn£©ï¼èïÿÔYû3œÿó?ú3°ÿ‚3þ3™ùÿ™ý3†úAþ39àù?þ36sLþ3Xíÿ™ý3‚þÿ°ý3mûÿ©ü3§ìÿçÿ;üéåêàØÖÅ›shPeȇmugsq]‘VÂiZ£¡1 _ÇÏ»°ÄØÑÊÊŽ«°ËÓçê˜&¶9=óËÇíÿùü3Qûõ?þ37­ÊÄéÿ‚3þ3 ™ÿÁ“™™‘Ìÿ™ý3†úAþ39àù?þ39é¶ý3¯ÿ™ý3‚þÿ°ý3mûÿÝ9þ39Ýìÿèÿ<úäæêÛÕÍŸ^Dc~{€oljqha^`XQcÃoT\ƒf\rB6ªÐêÃÒÍÍÆ½³¯¡äåÜ6v¢ ÃéºïñÿÁ‚Ë·ý39âù?þ39ßýÿ‚3þ3šÿý3™ÿ™ý3†úAþ39àù?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿøRþ3Røìÿéÿ<üäâäÕÙ¼lS]}‚wtrmomdYfe]\‹…QqOYZTTxÀy',´ÍçÂÒÌǸ–³í‡.Ï0aúÄÎðÿ–ý3›ÿiý3Êü?þ39Üýÿ3þ3šÿ‚ý3™ÿ™ý3†úAþ39ßù?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3Vùìÿêÿ=üæäâÕÑ™EJk{qmpsrpnml^P^bY¥¢¦¥žcTYWbZP~… ;¹Æ³¤ËÒËÇŸ£µ.žÌÞ»ôðÿ™ý3šÿ…ý3Èü?þ3:áýÿ‘3þ3šÿ…ý3¥ÿšý3‡ûAþ39àù?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3Vùìÿêÿ<çäãÏÎ’NYxqnoppopommki^HNY®w–¶uMQTWXUˆÅ1SȽ©®ÔÊÇȽ´œM=ÑlìÁ×ïÿ¯8þ3•ÿyþ34Îû?þ36‡œ•ªÿ¤3þ3’ÿwý3»ÿ­ý3„õ?þ3=ð÷?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3Vùìÿëÿ=ñéäÍЄ=z|mnooppopnnmjie@6A¨•œZKOQSVVh^JiIð”ÀÒÍÊż¡vÀ‰ÓÔ½úïÿÍEþ3Q?þ3;éø?ú3QÿÎ4þ3M‘Bþ3:áÿÍ4þ3M~5þ3Wýõ?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3Vùìÿìÿ=÷èáÑØŒ9xillmmnopponljfgU-LjRIOPMQSWUYÌ«Cʶ˜šÔÕÑÎǧ†© †î¸Üîÿøˆø3mÿõ?ú3Vüÿbø3…þÿjø3¬ÿó?þ39åÍý3™ÿ™ý3‚þÿ°ý3mûÿùVþ3Vùìÿíÿ üìâÊ×µ]ˆ€ypiýk.lnonlkefdP,?0CNLKNORSVV]•oRA É „»ØÏÏѰqz<àкýíÿòvú3`åÿó?ú3QøÿÜYú3õþÿèeú3‘ÿÿó?þ38äÉý3™ÿ™ý3þÿ«ý3iûÿøQþ3Qøìÿíÿ=ðãÑ×´?}x{sghiijklmmljhfdM0BR%4UJIJOQNOURISoŸ8NͤŸÔÏÌÎÀ^·ç¸æëÿ ýÀ`S]|·÷ÿÿùŸ—ü™•ªüÿÿô®w]S`Çûÿù¹|]S]ÇþÿùŸ—™—œò嘘™‘ÌÿÌ‘™™“Áþÿו˜™”µûÿüª•™•ªüìÿîÿ=÷ä×ÏÏE\ˆywuvmghghhjllkjhgaK,JA+>PGIGSpsUhœºÉ´T»§WnÇÍÆÄÃGz­ÇÃÒÿ©ÿîÿ ìØÏÊk}·{wuvuogþh,ijjkllij]G&I?8!@FDX …“qq^KL“¬ .²ÅÂÁÂ;iš›æÒÿ©ÿïÿ>õÝÓÕ{6Œ˜zwwvusighhiijiijjf`D$O6"%+A;†„W§—NSW]yš2l· ’ÉÃÁ¹2`¢‹ÆÒÿ©ÿðÿþèÕÙ¦!`lsztuttslýhÿj*ihge^]/1L2"%3G©”ok|fbeggfb^_fhggisT4Mph)&!!4NRSVYZ]Z`]R27±,–^'©›ŽŽ‰ÒÜÿýÍœ‚¶íÿÿöÆÅÆÃÝÿÿ×ÄÆÅÉûÿýÍœ‚¶íÿÿýÐÅùÆÄíæÂüÆÅÈöýÉÅþÆÂâÿþÑÅþÆÅÐíÿòÿûâàwUfinkrm]]hg\þX0\coo[E7M`RM; $=OSVYY\]TË»W=¤ 8Y::Ÿ¥ž“Œ…¯Ýÿéqû3D¬ÿ÷Oþ3rÿüXþ3hÿëqû3D¬ÿúU÷3½¥ú39àù?ü3‹ÿöJü3UíÿòÿEôãÑ?” pmllneZ[fov~|€pTACUSQ50E&5 (FOSVXY[\Z_t‚8U…&K@Q®¢Ÿ•…šýßÿìrú3ÿ3½ÿ‚þ3Pýë=þ3ÿrø3¿ÿU÷3½¥ú39ßù?ü3lÿè<ü3UíÿòÿEóá¹,8¹–mmlinoa^SZksni^RPY^dH2?,5;6)FGPPNVXWZUNK; pnZK 9f¬ Ÿ—†ôßÿµ9þ3A^53ÿ3yÿµþ3<ñÍþ36Úå9þ3A^5þ3}ýU÷3»¥ú39ßù?ü3PÿÑ5ü3VíÿòÿEîÚ›@ignljhefigg\ZTVX_ghpPO\,57%6-+EALj¥b‚XUUS’µŽJ‰J j_-C‚©ŸœšŠŠéßÿ‹ý3ÿM3ÿ3]ÿë>334ׯþ3Sÿ½ý3ÿMþ3^÷ˆik=ý3]ngÔ¡ý3Iokqé÷?ü3<ó¹û3VíÿòÿEë×U–wllggjaakss~†{ƒdLR3SC!4(204_Dª{‰å²MRUk˜¾‚™-'}Š@$Z¤¦ —˜…Ýßÿ}ý3²ÿT3ÿ3Qúÿiþ3¸•þ3‰ÿ®ý3²ÿTþ3QøÿÿùVý3Æþÿ™ý3ƒýÿó?û3اû3VíÿòÿEë×vªÐzmgk·½\[[\`rZcSZ]3SA5W..)I#kRHж¬Ÿ¤qgPKLDM’$B‰—P\z¶§£›—ŽƒÚßÿ€ý3…ÿ‰hmh…ûÿŸþ3‘qþ3¿ÿ°ý3 …ÿ‰hmh…ûÿÿùVý3Æþÿ™ý3ƒýÿó?û3µ•û3VíÿóÿþçÌ|!gþn=iª~›ˆXWWQUYOF^G\C7S1AL0C#jaOUNi^ŽY“Ö´}X=m˜!zŽ–l…¶¥¥Ÿ•Œ‚Óßÿž4ý3öÿüÿ Õ633mK33EðÿÊ4ý3öúÿùVý3Æþÿ™ý3‡ýÿó?þ3@73“{39Fþ3VíÿòÿEèÈw \~skzÌ«ŠfRURPX\AORDY0>E(LC5#J_RUUTRSRQSd˜ÕÉ3œ¿RB³¡‹¦Œ²¯§£¡—ˆ‹€ÏßÿÐMü3WÉüÿ øR33>633vÿÿñMü3WÉûÿùVý3Æþÿ™ý3Z–ªÿô?þ3X>3o[3@^þ3Víÿòÿ'èÉyŠÂpffÓ¥±‡KLRMSYS5V?GG(MIL=(/HXSTTUTþUÿVPJ[nSÃò¨­Ä¢™¼“¹­©££œ„…}ÖÞÿ®û36–ûýÿ†û3¬þÿ®û36–ûýÿùVý3Æþÿ™ú3Qüõ?þ3rE3K;3Jvþ3VíÿòÿEèĈ cw`ˆ“|¾«ÇwWLMQYa`M?aQvFTM48HPWUTSTUTUUVVZjQWžñìÆìµ—Ó“ªµ®©¥ ™‰€ÞÝÿ©9ü33|ûþÿ¸ü3:àýÿ©9û3|ûþÿùVý3Æþÿ™ú3Uýõ?þ3ŠM3433`~þ3VíÿòÿE實%9rªÒ„Èh``bYNMSYhh^{paL@Aez[QSUVUTTUXWWRbÒ¦[^äÿÆÊî·Ñ¾Ž¸²±©£Ÿ–‡„‹ïÜÿÔYý3ÿ3œþÿì@ý3cýüÿÔYû3œþÿùVý3Æþÿ™ú3Uýõ?þ3”fý3y…þ3Víÿòÿ$æ©¶/4×Äucj}med`^YNNYnlib_fu~udRNˆ\QTUþVWXQTRf¡4(¿ÿïÌïàÞñ’²´³®©£ —…ƒ‘ùÛÿùþ3ÿ3Qøþÿlý3›úÿùü3QøÿÿùVý3Æþÿ™ý3mÌÅÐÿô?þ3›}ý3“þ3VíÿòÿDê°·c!cfqiehec_]XQTM]l~€|l_Sa¦w¯JUVUUWWUv^Qk)”÷ÿøíúâý°›µµ²«©§ž™‡€¢ÞÿÁ‚Ë·33ÿ39ßþÿ–ý3Âþÿ܂˷ý39ßÿÿùVý3Æþÿ™ý3…ýÿó?þ3¢—ý3¨þ3Víÿòÿ0ò¼ªž AvÀ‰fiheca[T£Ô‡PNGIIFGNRµ‹½¤ºQVWVVTWNžØw@jñýÿþÿÙ“±­±¯«ª¦œ—йÞÿ–ý3›ÿi3þ3Çþÿ™ý3ÇþÿÃý3›ÿiý3ÇÿÿùVý3Æþÿ™ý3‚ýÿó?þ3¦®ý3Áþ3Víÿòÿ#ûÈ’¸#&ݦbchgeb`WqÇh€¶lLNOMJM]Ç@ƒ¥¸xPþW`USP¡nPÞûÿí’««®³¯§«§›„†ÖÞÿ™ý3šÿ…3þ3Åþÿ™ý3ÆþÿÆý3šÿ…ý3ÅÿÿùVý3Æþÿ™ý3‡ýÿó?þ3£Éþ36ÙŠþ3Víÿñÿ-àƒ¯kdsŽee`_]V[¸·¾WRRQNJLO¹œ¥ŒdfURVM¤µQZ:=Ðûÿò¤¡°¬¯±­¤¥¡’„“òÞÿ¯8þ3•ÿy3ÿ34Ëþÿ™ý3ÆþÿÙ8þ3•ÿyþ34ËÿÿùVý3Æþÿ™ý3Z™•Ûù?þ3¡á533>ó‡þ3Víÿñÿ.ù¡y»%iÓ£Z_]ZXWœ²Ü¹•KSPOLINM\«¤bNTZlUTaÛ¨-=Å÷üýÿô‘–°­°±°ª£¢ š„­ÝÿÍEþ3Q?3ÿ3;åþÿ™ý3ÆþÿñEþ3Q?þ3;åÿÿùVý3Æþÿ™ù3®ÿ?þ3ù=33Pÿ…þ3VíÿðÿAÕ\ªŒi°Y\e[XVPl¦”²cPRPONKLSPMF³LVÌzPPmw?¾¯†¯÷ÿû𓱧©¯°¯ª¢Ÿž™“…ÙÝÿøˆú3ÿ3mýÿ™ý3Æýÿˆø3mþÿùVý3Æþÿ™ù3³þ?þ3œÿP33hÿ…þ3VíÿðÿõŒ\Ë]D^®–NQVP]J_RþQ+PMKKRTTIœÄMKÍXN"Y¨ˆ@F^Õ r›¶¬«ª¬¬©¤œŸ›“ ùÜÿòvû33`åýÿ™ý3Ãýÿòvú3`åþÿøQý3Ãþÿ™ù3®ÿ?þ3›ÿi33‚ÿþ3Qíÿïÿ?×ZnÒ=j×`SrTIœ¶IGORPNNKJNQPPRcâoLOÃux›K*0:^f•¶­¨«®¦¨£¢¡¡¢ÍÚÿýÀ`S]|·÷üÿÌ‘™˜˜âüÿýÀ`S]|·÷ýÿüª•™˜˜âþÿÌ‘ü™˜•ÙÿŸ—™‘ÍÿÀ“‘ÌÿÁ“™•ªíÿïÿý¾,Ì:HU‰ËQLÊwEh]þL*PKGNR^dTM»¶XS3,„z2  Ox®³®ª¨«°­¬§ª¡¢›”¡ùÓÿ©ÿîÿ=û¢-ÎN!§HzÏMLÅxByƒG_—PG˜·IP€ÓF\Š] #'=‡°±¨«§©«¬¯®©«¢¡˜ÐÒÿ©ÿíÿ/ú§+eÄ EfİGbÑ\@¬¦@iÜWE‡×wn?&I…~J 'Y£¹°¥Ÿ©þª §­­®¥šœ‘§ûÒÿ©ÿìÿ:ö³Nb­ªV o\RÍ_ZÁ Zxá}pj\0J“¡o7-$ %.Au­¹¯«¬©ª®®«ª¯¨¬¤›™˜åÑÿ©ÿëÿ8õÌ•iŽº˜\&*F:YqhYPS(4p­¾‚N94?>*0k«º³°¬­¯¯«­«¨¬¬ª¨ šÌÐÿ©ÿêÿ7ï×·…™·¼§€Y?*4Y®Ýë´fF2>C8P|©¼¶±°¬«®­®«¨¨©¬©«¤¡–±ûÐÿ©ÿêÿ6ýéÙμÃáÛÚÍÌÁ­ž¢£·ÆÖìýÿúš@%LNTpޝº´¬®¯°¬«¬­«©ª©¨©¥¨£œªôÏÿ©ÿéÿ4úÞÐÏÉÆÒÙäëóøûÿýüÿÿûõíØ±^JhƒŸ±½»¸¶¯ª¯¯®®±­¬¨«¯«ª©¨¦ž¥éÎÿ©ÿèÿ2õÖÏÊÂÆÈÄÄËÊÌÆÌÑËij«¨£¢­¼Äý¶¶·±­³°±²°¯®©©¬°¬¨««¦¡žÞÍÿ©ÿçÿ0ïÐÍË¿ÄÇÆÅÇÁ±°¿¾Á¾»½¿Ä»¼½»»º¸²¯°¯¯±°®¦§§¬¯ª¨©ª¢œÔÜÿ¿—þ™—µþÿΕx‰¿ùÿÿ×—™—–¤Õùÿ(ÇŽx…­áÿ×—™–˜°éÿÿ×—™—–¤Õÿÿá–™™•´ÿØ—˜ÔÿÿÌ’ÌþÿÜ¢|zÍóíÿæÿ.äÈÇÈËÄÅÄÄ¿À·½Áº¼¹¸»»º¸·¹º»¾·¶¶²´³±²®¦¦§©ª«ª©¡ÔÛÿü3aÿÿ»Kþ3=—ÿÿ¯ü3RÍûÿªDý3}ÿ±ý35jçÿ¯ü3RÍÿÄý3gÿ±33mýÿ˜3˜ÿÿÌYý3F¥íÿæÿüÛÂÄľ¿ÃÀ¼º¹Á¼½¿½¿½»þº¼½¹²²·³´´³¯®¯¬¨¦¨ªª¢§ØÚÿ3B—šš¶ÿÏ83€Âœ53 ¥ÿ°3E¬¨Q3`üýÿ"Ô33˵umÿ±3E­™@3‰ÿ°3E¬¨Q3`üéªE3zÅÿ°þ3®ÿ˜3˜ÿÙ@3_µÄ™=qíÿåÿù̼¾¿»½¹µ¹«¯¹»¾ÁÁ¿¾¼·¹½¶µþ°´²´²°°­­©«¦©¨ž§çÙÿ€3Vüÿ}3`þÿŒ3 Oÿ²3Yÿÿ—3Uûýÿ/­38½øÿÿéÿ±3Wÿÿ3iÿ±3Yÿÿ—3UûÿÿV3·ÿÿ°3B3Dí¡3™ÿ3VñþÿèÐíÿäÿñÁ¶¹º¹±°··§²·¸º¾¼¸µµ²±®°þ¯ÿ°²­®­­þª¨¤µìØÿ €38OPL©ÿZ3•þÿÄ3 7íµ3G­¢M3–üÿ4Ü933>d¢÷ÿ°3SñÜU3‰ÿ±3G­¢M3–ÿÿùU3°ÿÿ°3‚r3…ž3œÿY3“ÿͪ¯³Õíÿãÿ'í¼®µ¶´³´º°¨¶²³ºº·´³®®¬­¬°±¯­­¬¨ª«¦¨£ž§Ðù×ÿ €38OPLªÿU3œþÿÉ35èµü3“üûÿÉi;þ3 mþ²33533Páÿ°ü3“üÿÿùU3°ÿÿ°3Šá=9U3œÿU3šÿ}þ3{íÿâÿ$óÀª²³±¯±´²µ¶³¸¸±¯«©¬®¨¥©ª¬¬ª«¬§¨¥¡¦ÅíÕÿ €3Tôùøýÿq3qþÿ 3Eý³3N¸I3~ûÿòÿÿíÅx33ëµ3@}¡íÿÿ°3N¸I3~ýÿ U3´ÿÿ°3ÿþ3 šÿq3fÿãÂK3íÿáÿ!üÔ¬¤ª¬®±°°µ¶´µ²¯¬¨ª§¡¡ ¤£¨¦§¬¥œ¤¾çÓÿ€3Uüýÿ¹35¬óÊF3 ÿ±3WÿÁ33Ÿüÿ ­lÂñü¡3=õ´3Vûÿ"°3WÿÁ33Ÿÿ÷×O3™êÿ°3ÿùY33™ÿ¿33†ãøT3}íÿßÿìĨŸ¦ª®««±¯¯©§¢šž ž£ ¡¥¨££ §ÀäüÒÿw3Iùüÿ’33433n ñÿª3IúÿŽ33¹ýÿ³þ343<­ÿ«3Iúüÿ ª3IúÿŽ33ÂÊý3hÿ¬3yÿÿÊ33‘ÿÿ˜9ý34†íÿÝÿíȬœ›™œ¤¦£™š™˜ ¤¢ŸŸž¤µÐðþÐÿ¿™©üûÿÌ“}‹»ýÿÿ ×™©üÿù —¯þþÿ øÃ•€€Úÿÿ×™©üüÿ×™©üÿù —´â—™™—´ÿÙ™Àþÿ³™ÌþÿÕ™€‚ ÍòíÿÛÿ÷áÇ® žþ˜ —›˜™œš¤±¹Ñåû½ÿ©ÿØÿúíäØÎÁ¾½»ÂËÒÞñùþºÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿÿ©ÿ¹ÿ ýøòíæèêæëîöúþÖÿ©ÿ¼ÿüòãÙÔÐÏÎÏÍÇÆÁÉÒÞëùØÿ©ÿ¾ÿùêÙËÄĺ²¦¡…³ÆÀ¾¹ºÂËÞñþÛÿ©ÿÀÿúãÐÎÀ© |pcYN3Ax£©®¶¶¾ÊÝ÷Üÿ©ÿÂÿýëÓž°—‘ˆ~œ¼ÊÕ齇=*o§°´»ÁÅÑêÝÿ©ÿÃÿ ÷Ûü¯§¨k·üúÿ ÌT–³±¹¾ÁÆæÞÿ©ÿÄÿ òÔî ¶Å1Bq±¸€tz|­•'M¥­·¿ÂÁÇçßÿ©ÿÅÿ"îѾ¬«Îÿ¤ 11BJ@@Q9n¯½Àú¸Ìïàÿ©ÿÆÿ$ìл§¥æÿØ9 3>Lcry{{‹‘}g[N8G˜¹ÄÊɲ¸Ïûáÿ©ÿÇÿ%ïÕÀ¥ªßÿóS,Sdu€‘§½ÒÍÓØÍ¼œw];J€±ÂÍθ­Ãæáÿ©ÿÈÿòÓÉÁª¼ÿéXEds…³ÞòùÿöРj?~¨¼È픪ÏüâÿÝÿíáäýçÿûÂÀçïÿÉÿ÷ÖÈí„îòf<[v…¤çôÿ ø½dQ¦»¾ÅÎPPÂîâÿÞÿû©™™ßçÿù¡ÚïÿÊÿýÜÌ̾`Äèe\s‚”Êúòÿ ýÃI‘¾ÁÈÎ*+¹áâÿÞÿáþ™¿ýÿ ýæÕÙðÿÿýåÔÚõþÿ õÚÚïîðÿþéèöïÿÊÿ èÐÊÁNƒöT@yˆ¤âïÿ úrvÀÁË´¶ØâÿÞÿ ¿™´ õÿÿõ³þ™Ÿòø³™›™¢çÿë¦™šŸ™­þû£ŸÛïÿËÿ öÖËÏ}G÷n!eˆœèíÿ ¢x½ÃÛ“»Õþãÿßÿ#õŸœí®™ÖÿÿÁ™±ëçºïÄ™ÍÿÕ™³ÿ¸™¹ðÑ™©þúžšÙïÿÌÿ ýÜÓן*»’ VŠãìÿ ¦…¼ÀãZ&ÃÓþãÿßÿ Ö™³ÿÊ™´ÿû¢™æþÿù£™¸¿·™¡ó ™éÿ㙩þúžšÙïÿÌÿ ëÍÔ×A{³ A‚™Ûëÿ ›—ÃÈÉ DÏÐþãÿßÿ ´™ž¨ ™›îüžšîþÿùŸ™¸½½ÁËõŸ™ëÿ䙩þúžšÙïÿÍÿ ÷ÖÓâ9°"r”Æëÿ ú޶ÅÖŒlÐÎâÿàÿ$í››³³´¡™Íÿ±™Íÿÿåô³™Ñÿÿûåû²™ºæÀ™ªþúžšÙïÿÍÿ ßÑÞÆ”`a°õëÿ áŽÉÈÙPËÒâÿàÿÆ™·þÿË™§þã›™­ª›ñä›™©³§ÿãž™™Ÿ™©þúžšØïÿÎÿ ìÈÖêSM‘/~¨åêÿ »¤Ëγ½ÆââÿàÿØÆçþÿòËËõÿêñ³ÎûÿëÆ³°¾ÝÿÿñÝèÕ™®þýÎÌìïÿÏÿ ýÙÑç ™9b™Íêÿ û ÃÇÙa>Ô¾ðâÿÇÿæ·ÎË£™ÍêÿÏÿ çÖÝÛ.]‚@ˆ²÷êÿ פÍд ~ÌÁþâÿÇÿé§™™¥ÊüêÿÐÿ õÑÚꀘi™Ûéÿ ¤¾ÈÜTÁ·Õáÿ©ÿÐÿ ÖÏæÇT>v¼éÿ ÖŸÇÏ·kͯîáÿ©ÿÑÿ êÆÙéS4§+`èêÿ þ£¿ÂÓW ²¼Ëàÿ©ÿÒÿ ýÌÌß«©MOpÂéÿ ÍÉÕ¨cλïàÿ©ÿÒÿ åÉÊÑ=t£-[™÷êÿ ù©¿ÂÖ<ÀÊÓßÿ©ÿÓÿ ÷ÊÃÊ…*È(LwÛéÿ Ê·ÊÚ’jÛÈòßÿ©ÿÓÿ ß¾ÅÂ*¡€?]£éÿ ñ¬ÃÉÌ#¹Å×Þÿ©ÿÔÿ ïȾÓt?½ 1gáéÿ »Èáz1uоôöÿþæÍÁÀÇÛöþÿýäâüãáîþÿÿðÔÿÅ×óýÿñáããáîþåâãâãûþäâþãâèïùýÿñáããáïõâùãâéðáãâã÷ÿûãâãáíïÿÕÿ û̳Á´2º^fn¹éÿ å±ÐÕÈ"ÆÅ×öÿô¸û™¡ÕÿÿùŸú™ÁÿÿüÉœü™ŸÏþÿÌý™Ãý þ™œïüŸü™š›¡ÃøÿÿÌý™ÇÛ÷™¯Üý™Ùÿåý™ÕïÿÕÿݳ¼Ä—˜Ê «¥ÈÑÒÙèöþïÿ µÄÔáW?…ÖÆö÷ÿõ¹ø™ÝÿùŸú™ÁÿÿÃø™ÊÿÿÌý™Âý þ™œïüŸø™»ÿÿÌý™ÇÛ÷™¬ó¢þ™ÊÿÑþ™œïïÿØÿþ÷çÌÇËÇ¿ÉÂÊÊÆÆÄ¼¾¿¼ÀÇÙðòÿ ×¬Ôæ¶B$4ÎÀÛöÿÚœþ™ ¯šþ™¼ÿùŸú™Àÿê›þ™±œþ™žóÿÌý™Ãý þ™œïüŸý™›ý™›éÿÌý™ÇÚ÷™ªýºþ™¼ÿÃþ™±þïÿÚÿõãÓÇËÑÎÌÍÉÇÆÅÄÃÇÈÁÆÄÆÈ¿³¸Òíõÿ ý°ÀËÛ7%V¤ÓÂùöÿÅý™Îÿ¦þ™®ÿúŸþ™š±·²ÒÿÏ™þ™Âÿ¹ý™ÝÿÌý™Ãý þ™œïüŸþ™œáÂý™ÕÿÌý™Åæ³·«ý™¡¶´ÂÿÔþ™­ü²þ™ËîÿÜÿõáÏÇÇËÍËÆÊÊÄÂÁÁÃÃÊÃÂÄ¿ÉÄÆÇÀ·²Êñ÷ÿ ÌŸÂÏ€pFà»Ýõÿ¾ý™Ùÿ©þ™¨ýúŸþ™œîýÿÅ™þ™ÍÿÂý™ÒÿÌý™Ãý þ™œïüŸþ™œóåý™ÌÿÌý™Áþÿ×ý™¶ýÿ휙™¢ó¤þ™æîÿßÿ"þðÝÑÍÊÉÅÂÇÈÁ¿ÄÆÁ¾À¿¿ÈÌÒÆÀÅÅÈÂÃÂÁµ·àùÿ ôœ»Äµhx·Ð¾úõÿ¿ý™ Âÿij¶³ÂÿúŸþ™œîýÿÀ™þ™ÍÿÁý™ÌÿÌý™Ãý þ™œïüŸþ™œòçý™ÌÿÌý™Áþÿ×ý™¶ýÿ ý­™™ŸÖŸ™™§ûîÿàÿ%ùÙÊÍÌÅÃÄ¿º¿ÁÀ¿¾»ÂÂÁÁµAT‰¡²­ÆÃÂÆÂÄ¿®Ìüûÿ Ä£¾Çj'›`àµáôÿÏü™ÇûüÿùŸþ™ðýÿÁ™þ™ÍÿÁý™ÌÿÌý™Ãý þ™œïüŸþ™õàý™ÑÿÌý™Áþÿ×ý™¶üÿÇ™™œ¹›™™Âíÿáÿ'íÏÌÒÏÆ¿¼µºº½¼»»¹ª¼´¢¬«/•‹š½ÇÈÃÅÅÁÁÀ®À÷ýÿ 梻¾¯4›rÀÿýôÿç¦ü™«äýÿùŸþ™›ÃÍÊëÿÁ™þ™ÍÿÁý™ÌÿÌý™Ãý þ™œïüŸþ™›Ã¬ý™äÿÌý™Áþÿ×ý™¶üÿá™™šžþ™Ûíÿãÿ*ùáÍÏÓÂÈÆ¼µ®«¬»¡x€bp}–trHi³Ð»µ²ÊÎÅÇÂÇ»»±¸øþÿ ®¯ÅÂyl²xÞ°àòÿ×û™›ËýÿÿùŸú™ÕÿÁ™þ™ ÌÿîáããáñÿÌý™Ãý þ™œïüŸù™ ÅÿÿÌý™Áþÿ×ý™¶üÿø¢ü™ öíÿåÿ;þîØÎÑÎÂÀ¾ÁÀ­{PSpFCˆQ@cN;::E/3u«É½´¶ÌÉÃÅÂÅ»¾´¹÷ÿÝžÇÍ£O¼Y$ÒÆÀþñÿÔœû™½ýÿùŸú™×ÿÁ™þ™ÌùÿÌý™Ãý þ™œïüŸú™š¼õÿÿÌý™Áþÿ×ý™¶ûÿ»ü™¸ìÿæÿ;ûßÍÎÏÆÁÁ¹¦‡VaTX¡¯nšÎy‡Û‰j©¢G-|ÀÓ±ªÇÎÅÉÅÁ¾Ãœ¿ÿ©³ÀÈGm®’Ö¯çïÿé¬û™ÍÿùŸú™×ÿÁ™þ™ÌùÿÌý™Ãý þ™œïüŸþ™›¹¥þ™«öÿÌý™Áþÿ×ý™¶ûÿÔü™Óìÿçÿ;ü×ÈÍÅÁƳ…^TJiÉ}‹}uƒ~n‰—eÇvo¯©7 K¶Í¹«ÀÓËÂÆÃ·©¬¿©¹ÅŠ$¿C2Û»ÂíÿüÇü™¨ýúŸþ™›ÖåáôÿÁ™þ™ ÌÿàÉÌÌÈåÿÌý™Ãý þ™œïüŸþ™œôÛý™×ÿÌý™Áþÿ×ý™¶ûÿîœþ™œîìÿèÿ<øÓÉÎÂÁ¼ŒK6\އƒ†zyw€ztrogctÇ|hnŽwr€D$™Ë¨¾ÍÅÆÃ¶²³¹¼Æ3x««Ö±ïñÿàÀÀÁ¿åÛý™œñüŸþ™œïýÿÁ™þ™ÍÿÀý™ÌÿÌý™Ãý þ™œïüŸþ™œòæý™ÌÿÌý™Áþÿ×ý™¶ûÿû©þ™©ûìÿéÿ<ûÑÄÊÀɲ^BY…Ž„~}zqkxwpp•“e€epojj‰É‹2!£ÈǦºÉÅÿ¾·’Ë}/Õ6L߸ËðÿËý™Íÿ´ý™åýŸþ™œíýÿÀ™þ™ÍÿÁý™ÌÿÌý™Ãý þ™œïüŸþ™œòæý™ÌÿÌý™Áþÿ×ý™¶ûÿü«þ™«üìÿêÿ=ûÕÇÈ¿ÀŽ:Hw…€‚…„ƒ„€}pfrso±¬³¯¥vlnqtok‘Š$©Æ¶ ÈÏÈö¨|œ.¢›¯Ë¶õðÿÌý™ÍÿÂý™ãýŸþ™ðýÿÈ™þ™ÍÿÂý™ÒÿÍý™Ãý þ™œïüŸþ™œòæý™ÌÿÌý™Áþÿ×ý™¶ûÿü«þ™«üìÿêÿÖÇȹŠF[‹…€€‚ý€(radj¹†£½€dlmonl—Éœ@@½¿ª¬ÓÇÀÆ»¹žE9ÔWÒµÕïÿ×›þ™Êÿ¼ý™çýŸþ™›ÃÍÊÕÿÑ™þ™Éÿ»ý™ÝÿÖý™ÁúŸþ™ž÷ûŸþ™œòæý™ÌÿÌý™Áþÿ×ý™¶ûÿü«þ™«üìÿëÿ=ãÌɸȇ;y‚‚‚€~~yY8MWµ¢§meglknn|rd~T†Âµ™ÀÔÎËÈĪt½¹Â¸ûïÿæ¢þ™¨ÇŸþ™ôûŸú™¨ÿç™þ™¦È¡þ™ðÿæý™¦¿šþ™«þúŸþ™œòæý™ÌÿÌý™Áþÿ×ý™¶ûÿü«þ™«üìÿìÿ=ðÉüЋ5y†‚‚ƒ€€}}xzp57Ga|h`glhkoqmn¨Ï¶$1À½Ÿž×ØÓÔÑ´„£#rÖ¯ÛîÿûÃø™¶ÿúŸú™«ýÿ±ø™Âþÿµø™ÕÿùŸþ™œòæý™ÌÿÌý™Áþÿ×ý™¶ûÿü«þ™«üìÿíÿ>úÓÀµÏ´Q‡‚‚‚‚‚~yyxgC-SJ`jghmjmoppvŸ}iX ‰ÊªŠ¾ØÑÕܽqu2Á¾¸þíÿù»ú™¯òÿùŸú™¨ûÿí¬ú™Àúþÿó²ú™ÈÿÿùŸþ™›ñäý™ÌÿÌý™ÀþÿÕý™´ûÿû¨þ™¨ûìÿíÿÞÆºÌ²9w€‚€€ý‚ÿ'~|t^JUgBTpihglmijqqajƒ°B<Æ­—¦ÙÔÔ×Í`‡¦Ð³çëÿ þßÀ¯©®½ÛûÿÿüÏËüÌÊÕýÿÿù×»®©¯Àãûÿüܽ®©®ÀãþÿüÏËÌËÍùòËËÌÈåÿåÈÌÌÉàþÿëÊËÌÉÚûÿýÕÊÌÊÕýìÿîÿ=ñżÁÌ=\‡~€|{|}}‚‚~}|qcLgaE>Ykggel…‰o€§À˼g¬±^sÏÔÐÏÒMsªÀÅÒÿ©ÿïÿ>þ×»½Êeu³~‚‚}}€~€‚‚~k^Gf^M?;[hbl«•œ¢†›ref€³*·ÏÊÌÐC\ ¢çÒÿ©ÿïÿ>êÂÁÏx0‰‘|€‚~{|}~€€€~t_ElTCE>IaZ‘“n¬¢jmqr‰©8Xµ•ÕËËÇYklnqtuvwv„„]"µ=0»ÍÆ—$_« ¬ïÔÿ©ÿñÿôÎЭ&0pghpn|z}}{yyþ~,~qjhUx~JEC94:;Qhmpsu{|vyÂÅ‘(µ<,©Ã¸xn­–œ›ÊÔÿ©ÿñÿ åÏÄ^¦¦tmwcq{}þ{2yx€€xqaNrŒ`FAA<4>9Tlnqusy|vyvtW$°2#—À°O&u¦™š¤÷Õÿ©ÿóÿÿþ ÔС/>£Œgj€hamþxÿv1wuz}{|€cNi‡DF??=>;9\mpsxvx|z{toO*¨*4¤o,/Š©¡“–ÙÜÿþæÍÁÀÇÛöÿÿûãâãáîÿÿëáãâäýÿþæÍÁÀÇÛöÿÿþçâùãáöóáüãâãûþäâþãáñÿÿèâþãâçíÿòÿDöÎËhShgjfpt_`rtplnror}zjUOjzgXP=<9:>7AapruvxzypÌÃg0¡CmP5&Aœ¦¡—‘ºÝÿô¸û™¡Õÿû§þ™¹ÿý«þ™³ÿõ¸û™¡Õÿýª÷™ÞÒú™œïüŸü™Åÿû¥ü™ªíÿòÿEìϼ3 ‰˜qnghqr`\hw~ˆ…‰‡w`S[prfMJS?88BV2Ohqtvuyywuw‡”FFŠ"[Y5,7Z«¤¤–ŽŒ¥üßÿõ¹ú™ÿ™ÞÿÁþ™§þõžþ™Îÿ¹ø™ßÿª÷™ÞÒú™œïüŸü™µÿóü™ªíÿòÿEéͨ3¯Žnmihiqpj[`kqpmb\`ntvbLRKKJ;2VN=igmmptvtvojf]b ld7&Nj¨¡£šŽ‹›ößÿÚœþ™ ¯š™ÿ™¼ÿÚþ™øæþ™›íòœþ™ ¯šþ™¾þª÷™ÝÒú™œïüŸü™§ÿèšü™«íÿòÿEàÄ‹ =ijnkkjdajowmfafhqvvzb]eFIKAK?Kj3ep|«pnuxrº™e }c€uD/X¦¡›“Ž“ìßÿÅý™Îÿ¦™ÿ™®ÿõŸþ™ë×þ™©ÿÞý™Îÿ¦þ™¯ûôµžý™®·³éÐý™¤·µ¸ôûŸü™ùÜû™«íÿòÿEÛÁnLvmjg_b[]esyƒ…†Ž„€hZ\F\TFO>Wc°…Žá¸jqo~¤É’—G=™šXAgœ¤¡“š”–àßÿ¾ý™Ùÿ©™ÿ™¨ýÿ´þ™ÛÊþ™Äÿ×ý™Ùÿ©þ™¨ûÿÿü«ý™ãþÿÌý™ÁýÿùŸû™ëÓû™«íÿóÿFþÜÁe£Éyohb¤¨oWTY]^lcjZ^`I_RJ^C;CCf„„mqgtr ×¸ŒrZ fµK4™ª«†œŽ®¢¡ž•”ŒØßÿÏü™Çûÿüÿ ê›™™¶¥™™¢÷ÿåü™Çûúÿü«ý™ãþÿÌý™ÃýÿùŸþ™Ÿ›™É½™œ£þ™«íÿóÿ(üÖ²dYysoy¼—qYSQOQY^OXZO_DNP=ZPMA>h{nqppþoÿny¤ØÐE ÛxcÑ»¥¸˜©¨¢žž–†ˆÓßÿç¦ü™«äüÿ û©™™Ÿ›™™»ÿÿø¦ü™«äûÿü«ý™ãþÿÌý™­ÎËÕÿùŸþ™«Ÿ™·­™Ÿ¯þ™«íÿóÿ#þÕ²gƒ¼pph•ÃŽ›zMMONTWZGZGMQ@ZX_M>Kgvþpþqrpqtmet†JÎýÇÆÞÀ²Æ•²©§¡¢œ€‡ƒ×Þÿ×û™›ËýýÿÃû™Õþÿ×û™›Ëýýÿü«ý™ãþÿÌú™¨ýúŸþ™¹¢™¥™¥»þ™«íÿóÿ$þÒ­xb|f‰Žw°¥Âq[QNQW]\TIb[wRbZAC]osqpþqrponrsziw+Ÿ÷úå÷ҹߛ£®ª¦¤ ˜Š‡àÝÿÔœü™™½ýþÿÛü™ïýÿÔœû™½ýþÿü«ý™ãþÿÌú™ªþúŸþ™Ŧý™¯¿þ™«íÿòÿEÏ”™;v§Ì~ŠÀihfiaUVVWbd_zreTJN`rpkqqnqppqqonpzÒ­vWèÿìçõ×âÆŽ¬¬ª£¢¡”†…“ñÜÿé¬ý™ÿ™ÍþÿõŸý™±þüÿé¬û™Íþÿü«ý™ãþÿÌú™ªþúŸþ™ɳý™¼Âþ™«íÿòÿEÖ§*1ÒÁxlt†uppmkh`acnmhbenz„„q`bomqlkppqpmrn{²=¿ÿüñúîðô˜§§«¬©£¡˜ƒƒ–úÛÿüÇþ™ÿ™¨ûþÿµý™ÍúÿüÇü™¨ûÿÿü«ý™ãþÿÌý™¶åâçÿùŸþ™;ý™ÉÆþ™«íÿòÿDÝ”¥Xkmsrrvppmlj`^^mzˆŠ‰‡|tim§}³–brmlpnor‡oj†? Œùÿýúýòÿ·•ª®­¦¦§ œ†¨ÞÿàÀÀÁ¿åÛ™™ÿ™œïþÿËý™áþÿíÀÀÁ¿åÛý™œïÿÿü«ý™ãþÿÌý™ÂýÿùŸþ™ÑËý™ÓÇþ™«íÿòÿ0å•“Ex¹ˆqxwponnc¡Í…\dacc_^cd´‘Á¤»emmnqloi©×„T^ñþÿÿþÿÜ“§¥­ª¥¥¦œ—ˆ¼ÞÿËý™Íÿ´™þ™ãþÿÌý™ãþÿáý™Íÿ´ý™ãÿÿü«ý™ãþÿÌý™ÁýÿùŸþ™Ó×ý™àÆþ™«íÿòÿõ®y­#פlqvurpnk}Âl‚³xcþgaemÇNŒ¦¹‡golmpfli¯{DÚûÿð–¢£§¬©£ª¦ŠÙÞÿÌý™Íÿ™þ™âþÿÌý™ãþÿãý™ÍÿÂý™âÿÿü«ý™ãþÿÌý™ÃýÿùŸþ™Ñäþ™›ìÅþ™«íÿñÿ-Îc¡c |mzqvtqpke³³|»eihhecgc»›¡“r{mooc©¶dqN/Ìûÿôªœ¦£¤¬© ¡¡ž“„˜òÞÿ×›þ™Êÿ¼™þ™åþÿÌý™ãþÿì›þ™Êÿ¼ý™åÿÿü«ý™ãþÿÌý™­ÎÌÊíüŸþ™Ððš™™ŸùÃþ™«íÿñÿ,ï`±lΤkrqmlh›«Ö¯”`kggdbgeo±ªmbkn{ihmÝ­:.Äûÿö—¥¢¥¥©£žš š†²Ýÿæ¢þ™¨ÇŸ™ÿ™òþÿÌý™ãþÿø¢þ™¨ÇŸþ™òÿÿü«ý™ãþÿÌù™×ÿŸþ™Îüž™™§ÿÂþ™«íÿðÿA¿:™f¯eholmlfzª—¯nhgfgeegkgdZ´ejÍ…ef~0ÃÊ©Ëûÿÿõš‡¤››¤§§Ÿ›œ˜’‡ÛÝÿûÃú™ÿ™¶ýÿÌý™ãýÿÃø™¶þÿü«ý™ãþÿÌù™ÙÿŸþ™Íÿ§™™³ÿÂþ™«íÿðÿAìj?¾SGk®™cekgj‘]thifggecdkkl`£ÅaeœÎig.M°¤RWy¡å¹y‘«¢Ÿž¢¢ œ–—œ™“ ùÜÿù»û™™¯òýÿÌý™áýÿù»ú™¯òþÿû¨ý™áþÿÌù™×ÿŸþ™Íÿ´™™ÁÿÀþ™¨íÿïÿ?À5\Æ1hÔjfyf`´\bhkhheadejihhqß|edÈ} k£W,7Ioe‡§ ›£œŸ›™œž™‘ÏÚÿþßÀ¯©®½ÛûüÿåÈÌËËñüÿþßÀ¯©®½ÛûýÿýÕÊÌËËñþÿåÈüÌËÊìÿÏËÌÈæÿßÉÈåÿàÉÌÊÕíÿïÿ?öŸoº/FaÉc`Ç|Zsnfb`he^fknqh_¿¸hg?|3Rm™£ œ›¥££ž¥œ›”¥ùÓÿ©ÿîÿ%ð‚o½A¡“XÌ[^Ã[€ƒ[sš`bŸ¸[eÕNMƒX þ -x¡¡ššŸþ£Ÿ¦ž¡šÓÒÿ©ÿíÿ<í…Q±kChÄ®\mÍgV¯¦TxÛeYÙwF) :yv<Bލ¡™•œ›¡¤¨¤ ˜œ‘¨úÒÿ©ÿìÿ:â,G›˜IlWW‘ÌkfÁže€àvrf4 5€•`%_›© œž›Ÿ¤¦¢¢¥¡£Ÿ—–šåÑÿ©ÿëÿ8Þ¬sIw£‚L(F:WpdWOU(V“ªp5(W™ª¤¢£¡ ¢¢¡Ÿ š–ÍÐÿ©ÿëÿ8ý×»˜du•œŒgD/  m¹ôÃQŠ9»fͶïÃ^Á™¦ 7woã‘“+¦LüèeÃõXCÕ=UëYUϧoŽ‘úÙÆÕg_ç~:û–íÍGAO¾½û÷Ðl‡cŸX~úðó믬þ~óþOàþ·ß€¶à&t` èàƒ -XEƒI¸…f¨!=j÷Ÿ}%m(âˆ,u(†ü˜ˆŠ$¶è"2 îT^ŒV°øâ8ŽD#f´©x„9)¤)>ø¡pç ©ä’.íqE$“TV’óyR¾Ýµ[r–䤇V¾SOj“T#Òre¢%ƒ”ÅeM}Éœ#Û½9Ä”B"Ò ¸ˆÖ¦›c&)žiMWgV~†æÔ£×ñUšiºÞ ¨4*[jŒ> écœÊ9• áuZ•¢§¦j¥˜’†eGq6¢Ûq Òªœ­„½b«)ÙꘜµÞYS¾ê¥éj¿Ë+n–þúw¨_ÊNլ‚Ǫ%͹lL­ ÖTÁv»Ø´Å6š¨d¯Y è¶He‹`¬ÑâJí¼èjé.œìÚ¯¬‚¹†±ô+pµÊÞ™o»ºÊ˜f¨Èúûi¿~jŠêw#¬ðÁtŽ«Yª£N‹f©eM:ZÀâJ«jºÛ›0X倦žBð™òEëÎç½sm“+çlóƒ;ÿl1]uA‰ó…B']%ÌJÈÜÓ@8­ôÔµõüdG7MõÖ9B½â `ƒ­ /a—möÙh§­öÚl·í6c½ÉqóÈõÝ#&#÷ÜPÖ}5Þ€g¨·ÜR¯ãµ…®¸B‡‘x:óðøâ”7”õ‰þG^\ùæÜENÄääx®蜗ùå—m5™¦·>ãê†b {ê®×^êP¬9˜õâ9RŒ†íì¹ ¯’ñ.ßeƺ/¯òCÕ m¯+hð» E¤ó×kÉ=l_Jïü–¾%~ò>ù…»¶iö‹,¿Úûþ}èm÷üaÊß>þÈ矒@çëŸõJq˜ ôîy1I_ýà§=Q PÓƒ`ü¸½àìí\Z™´<ÅìE \àËžL8X±I­OJ'c¨L>rËSK×ÃBõÁE¥_ìX '5C²ÔT¬ê°T8*/EjSxxx,‘eoUkbð6±æÐc”Mþ_óB)ž,„Y\•ªD³}쌳"–P<­~n_ôRÍ8Gý‘¬Žÿš; «aud Ñ®=þш ÖñéF&PÇ…b0¤ÉÔ¸¿DZeêrÙ#…24:‘Z\±¤¬JvœOö&”t$dg49Ày9ñNyT¥ %IJUf’~«´eÁ"1_5iD—%A Fë (¿ 1uFfÆò˜ÁœŒ(%Y°Tzƈgä §)Mjz3|Šüf8qØFâ튋L¼ ÷Bà >¬˜)ì%˜LhN'`Câ¢ô©‡yˆX$U½rÐþsd<´á)ù¹O„vI-èŒçVþµÄ…º•#³('_ØOvúÐI4eµ¼(Ì'îpŒÉLÂ5ŸÀ2&¥?é:÷¬[D/S ¬àLu† ˜þH6.‘)V|Úƒ)í´@|"]ÐN±Ôˆ ˆŒÊ|›TËà·áØîªF*P À`õ*ÆJÖ²šõ¬hM+¢¡Ö±†U¬mk[ßúULh«xíQ‹0ீ ¬`KØÂ6@¬aËØÆ2¶,Ë«d3¢Õ½Áá –EÜd7K³½fV›ígGÇÙÒFȳ£ HhÚÕ´°S=[+ÖŠÖ¶´¥ÁkcË[Wåv¶ îouÛÛ⺣²„ƒƒr‡þ㹬œŸIÈG'^Ž+‚Ì©vgiÜС6³¸µ@x™Ëçr—Ò­ióø>Ž/cìn7K—ñŠƒ¼/P”µ¾(D~t hÅøÄ%F±¡x¡b€K•`,2g„1¬¨ud¸ÛÒÒ÷!‡Ào 8 MI¬Ã§ˆÅ9ÏøAS›òÆ…ç“a ¯„#×G)kɑƉqlr:L­4Å6ýnrAKd£`Þ$°ŽÓKb/ó{'Ö#ƒ<[#kÀ¾VNA )vO G2Q2–ç–ÚIŒ*Y˜ïäè§Jè`ÃR…¦ð§ìŠ9ËåÝ_õjš¢íF‡Î(±3ѰŒþg¬¤ÀñÍGSÿ 蓺¾…Îs£'MŒG„БA…)Ý[Kg:Ó›ætl=ýéB‡ZÔ¦%u©³|jTsVÕ«6r«]=YXó"Ö†¦µ®ß!äK«ö¾¸&Á¬wU[#®È 4–Ç‹éU›÷¼ôqóœ&Ègbgn¸˜½¬¶7^0üšµbH·Çlqxã¼üƒoKµ{Sk“ÇØ£Cöm½\ájÛÞËÍw°õëQþ‚ùƒ'5Ë’U”t¾ò7p–°Óéî@÷ºiäþ¶·ÅmoÜ‚›ÛÙæ¶8š j0‚xˆ½£ä{½…Ë='9Ä ïl•gÁìo¹âô­¾e^î¢A’–%7èƒý—Åþ6K~ˆô1zSθ‡SÁâÙƒËÃñšwÉN åmv³ê8¶:Ñõºr§{ýÊøœØ˜Ee•€—Ý õ ¬É„cOÎCßz…ŒþuVëÙÏÙÍÆ°åž"º[–ãu‡ÃÝÓwkìï–ëú§xŒOõñ¼ä'OùÊÿ¡ª—wæåq ¸¢5¬d½\?ÖÑ›þôq=êWÏúÖ»þõ°½ìgOûÚÛþö³7€]7Ï Þ‹ ~u¬ð‡OüâÿøÈO¾ò—Ïüæ;ÿùоô§¿|ÈúØ×Ï8ã¯Ïýî{ßµÙoù÷ÇOþò›¿¼Ë>¿ú×Ïþö‹;Ûw¿üçOSþ§?æõÏ¿þ÷¿xüóÿÿ¸oÝgqX€Xjñ'€þw€ Ø€¿•€±Öm8ØZXsX¸GG~È ‚ègyk`}'‚(˜‚6pxB±{,¦‚0ƒÄ•"˜G 2xƒ8¸aýo*ð9øƒ@È‚Ãó‚@X„Føt;èwºu„L؄̄Šç„R8…*…Tx…X¸+Ô¥/ ±hî#+J˜…b8† ÐD8Å@ë…'aH†l؆âµè†|(bGMvrL<(l}XˆHP/8GƒX[†øˆ h†—Hþ²G{‰šè}lFQ"•ˆþc§uŸq‰‰›xоgTØ‘`yˆŠ®(ƒ2u&È…£E‚¶x‹¸˜‹º¸‹Àçä%„*ÑŠO·€;Œˆ‡)±€_Ɔ´˜lš×b½'o¦ø†ÇHiƒÃ\Ëx%+q×·tJçâ˜qZVÖ(Œ1ËdPƒz(.lø¦qñHsô˜kæØh¤x\åy¸×¡ç‚ÀÅÁ5qM7oïçxÛv=xøˆŽAÐWÔ‘‚e‚Køs·E€ØGŒöÈS–ˆt™tªÅt9ƒ d ùеU\Äs¨¶’,Y†µ†]ˆfrð…w›#“3™ly‡\E ·p慔Ó78þ'HErYWMWlI…J¹”?iv5æ—KD)YHƒUÙ‘xõL!gMîe:_©‚a)–°åd2¶…6•N¸–l™’Æ•–= x©’t¹—VÙ—ò¥—€I‚™—Y„vyd‡Ù]„©‹É˜é’‰ùƒ‘˜“É[I—‰™™Ù–•™”Uø™£š…‰‰¤YšÍxšÊ”š ¹š¬SŠC!r™]Á&8‰7›ÉšLÉ„÷,Iµg½Ù»y€YŽ€ÃaEy.[¤PJÖC7´BTSSœxœÈy7SG;§ˆ×•MÜD5Ö€Í&~eøŒ‡œâòf>.[ cò‚K·þ4œ·›†ˆiä¨}7ן¥˜œZ(t˜sÁ$f%µÑ¥¦)‚øéŽ«e‘Y|©~±œ?t`f6EÅFoö[)ž j™)q‡tþÉ‘E㚯¢Aør1wqºlø©¢siŸ±¹qà¦}ä˜lËF£+j£lˆ†f˜>ú“,ZBjhÝV¤µv¤‡hO#©ŽR:¥TZ¥VìÈ›¹c”Lº8×XŒW¦kƒ£'9dšŸLW¢hŽôÙ¥ûñ¥¤UléH\ê¦ÉéwmšpªRÁe§R ¤>ù§tjn~j;–§ðÁƒö…¨…únx:–¹£)Ú¨hù¨‚ê83J©­s¨þ ¨%ÀqÏf<àÄdÀc…MÈ“ÛÕn‡É©@Þs“¸Q›6]náNªÂY?±^i¸Hí%«#§ª9Ù—®Ê%?w–»sª”›ÛB0â©0ÀoVäo§â_¨`kÆFd•·jp7¤`ÛzEÐ O\Ô•Òi‡ŒŠŒ–Ь &pþepS”a÷D!tÕš¯¹$1·cߢ¯´:‹˜£F÷a$ö’I¶d•˜?QM»v¬ÌC¿ÂJZ™`ËQ·âacDH’8±V–awr!­ù•Aߤœ +—7ÖcŸGÒtÑ‚¯ëh;"uH͹OïäCo—sÚº¬Z+æ²Jþdþ†_v3$«‡÷zrºdþã´ ‹n†$ŠÖV³ÆÔO½tG §±ŵ!dK?5bÎú¹Z¯hûœÍù¯k6dö¡¡(/iVEm{®oÛ³v« ÇDsFkV+HæÂœüÊB; Eñ¤_2:‡Acû‰øZf•’´:X¬À‘§3{†š*í:3ì±’‡V¶ÄŠuÊT™¹š•2›+˜Sºœó·•*¹’ƺ•㺥㹲»“›[;¶{»G‰§bú»‚¥£É»³éwûxVlåÊ;zÉ»¼Î˼n5§øB¼sa)X~"‘ÚkXÙ»½Þ˽RñW9½Ô«›é'÷¤E%5R¾Õþ‹ŽXaUê§ì{tçmLÕ³Å*Aƒç¾Ø¿O!¿,Àö[gèÖ¹Áº¿Ê*¬þË,°‹„°@ÐY@QÀ[$vqxv@ ¯eà­:7Š  n—O•º ,°{"+ÎÁSÁû‚ØL£ÚG¶©N°db„r'¬†œž*ü.?;,œ:7u•/ «מ<æ²üt¹ÔûhÔ¾*!ÄL;C¶^¦GÖÅÅ ÃPùd;¬­YÅ>ƒ'V<ÄF"³ åee÷­±1pj¢v0Äv·œ=—PL¼‚Ö«l +lÆì“•ë&c|:=L 5ñÇ‚LÅ€\<”K=/sȈ5kp"þ—\#™lO”¬4°6¿8Ê’Äü3Ÿ|kæÈ¥Ì¹S)Ê+èkª¼ÊsÊJËg,˳ÜʨL„ŒŒËùBË6˜Ê·ìËì̆a˽LÌËbÌ̬CmÊz¹-µÇ8)ÍxGÍ7-Kòi–RÖQ0Iý×`M}K°(wÖ'WÔuMØ©J–YGÕ¬×çáÌ«ÛBz‡=OdMRûêÙׄˆûÁrP2–Qœø4QÛ|O®Ížˆ 6ÇXÉÙ]‹µÊÑN³1”öêIι°ÑUÚ”M–ÅúRÌ ¤S÷»®ÚìÍÃ}ŠɸA¡á £ëÎÝ¿Ý%1ݼâ=Þä]Þf#¼EµËþqÇëzª÷¼ðߦ׼¹WzËûÞòýUøm{oEßùßûzº' R¢Þ,w×û½ ¾à‰XŠÅàáÍçà^áÉ7¾ÊdàΛ’J'É™ÎÓ7zq®Œg$¾%^‘=}š'®-ޤ!~Õ#þŽNãOºÐë}£™â.†‘ Žã>ãôÆã¿˜oD®€"äZJ ~?žä1Î’ ê~S’Q^ÙKîäìª7å@¾—\¾åЉWNÜ,.^h®~‹šædþånžåüwäN'çùÞ…I粂x¾av˜{®ae.Ý:>s.®çƒþÝ…Ž¢MÎÞƒ}®‰óXãþê艎 YhžÎXŠè‰Î䜡ù÷èZé9ˆ¦Û¶¦à8q¨ž¿(üyY0g’Ü(ŽõGêGfꢣ6¾ãªé•žZÀîãï(9s¸.ì—^#WØê©£>Nâéì¯~¢Q*ë4.í:z¢£¾ì’é.J9ëjeâ7ã¾tå¾É>¤zM†"Y¢«žtŽØŽóFëíÞãÞÞ‹ìó·ï&ÞïÚñïßè(Nð'bð¯ì–þæ2nðo ¿ñïåñŸãŸ×òïNè+çìŽèò…Þðµˆòå‹ÎòŸ%óüžò0¿òäéò¯ä8þ€4©æý.ëå=ôg ¼Fω·˜ô[ôgÀôä›ÒK¨ROàšS?~ÖŒÌ\ËN%¼ÛýèÍ7‰QöÙ9hõ²öZCY12ö( vNå¤V5_vÿ„Α÷T¯rtŸ;2öã9ÈÜð˜roº¤ì÷W_÷=#ø|ßõÛ`øa¡—‡?÷zøù[^É_"?©š¿øõ‘ùŒ¿ù„ÂÎ%»÷¨ŸgÉšÏÞlÂaòɪ±\XªyrItû’Ýýòù‰¿cñŒ›ó,ùÍ´A…çÁ<æû’ˆÝþŒCq±_½ÜÓVÈ—Ñü<ÕϽ¿ú¹ucÃZpÉÏÃÜúÞ£ÄêþŒ†áOùò©Ûn`¨MÑ,—ýY|´X[ük×± G¯ítýpøÚ rVK+½wgpÓ,Ñ“äV¶u_8–gº¶o<³‰ë¼^(8ŽŠš^0¥c6'¢Ñ(òJ¤¤I‹©FE\¤É r–Í1è›\·Õo_ÚTêXá§¥LîŽß³ü´6 »¾Â¼9"7ÃF¶:¶Á??D²³LÍMNÂ˵CÀŸ¿ÄÎÔ›“IHG8RµÖÒBSÚÆ1U]š=X°[QYÛ /’ß:ÔPàX­Xã/¯â¹7L½JÆ;hÀîaçâèË]òrs´¬ÃæÖZÑãtësy€^p>âwmÊõÊþzÁè¹æ‘óŒßA;¡ÔµÓ›Bf#eë‹aµd0 6›¨obB} !XÒd™O-¹ iÊ¥’k';myÙÈR¡T.$)“´ïnÒáò ()I‹flA§D¤HÚ»R´j<15:;‚å¨P¥Âae…¦>Õ®M)Mš!bq¥|B«u­™²dçÊ%dŒÑ,aS_VW÷®&ºé/fÜØñãÇÑA¦\Ùòe6i›bæÜÙ³äáO&ö\Z1hÑOL¯¶L3êÔ9\³¦ýY3½Ú¹YÃV¦Û÷ëÛ±…ÿü]›÷p³‹sVÞ:8òÞË¥C>¾¢ùôâÕY\Çž[;þtðM¸w‡÷<üfòé©›??^=míîß—þŽ{þôúçõóº_9ÿ~ùúÓí¿ð8»¶;Pºú \Ð1÷“½‹°À 绹A:ôðCCqDISTqE=šrê*cgG_b´ŠWá­ Æ©(n¸˜' £vª÷Üv\®ú*ž¯ˆŠ°²þ »ì³$f"åmöÔ!EJ*ûA®hëÁŽà>¹mŸú]¶¯I…!oèêQà5¸f䬭Úja·ä¹eUûÑ l¬"&¡‚óZØ`¼{ @ àðÃG,qĦLlñÅðRÒ–ëٹ벃߮սëéYËëí½øv¬ï•ê~ìÞ¿òB›²²´>›³Íöy0€-ôÐDM4TF'­4Ñ›amFmnJc…X-Ô`qEžÔ:uíbp?qÈÝŸÓÕ{(ËÑî sgõë.Š÷l°i;+÷Ü ¬Ibj¹vTw­}å©/‡Ù‘¸¹=³^ÊQäš•Q kéál÷Íþ)_~·æj´rÌyHi•à€+®Ô– ζ×&Ól§¬…Ö¹šƒÚÛó„ ñÎç~÷Û¦¹ûbiPቸच‚­±»^ÇžgUX†QÅÖ¶äÓS[­VZ¾SêÅö`íþšJ©Q*ÿü Iì±S0ˆëƒµç.‚ͯ¯HÒ‡ëÿÿœBòdÇžŒI}ú[>xÀ:ðcS=jÁJ0$·¼ó>ø]P °›“¸0(yl0Æêà0FH ÆÉ‰…$t.ê¡BW!°# J!-nø¼-ì­†›âa¥Ã9/†¡òHÀŽ8æ…MDbÍ>·DFqE\…þIxBU1b‚⥘.ë‹bTbú®(E3¦ÈcWƒ£©P3<| /!å*Ù[ظ<ôt/k¥Ð#‘øC7rp2óU~(§È¬-¤Ž*JÒÑÈ‘µËtäÚ" IÉíùf]Àù¤µ¶ìE®&×âÞø6ĵk‰†/¡ÍNyìmoj·ùÞh`Y5걎–› /CC:Mæx½ÃÒÈ’™%àõªwÀ,ÁA´¢º¿òМ$Ña‰È3tV³%2íN<4¢KdB²Ù͉Í{ï” /×jþž/C¢;/¯„Nô%ë¼â+ïÖ™p_Ðeøö%§,Ãk’œ¿;éÖ>1|£.¼qŽ¡œÕÍŒõ¬{˜é#̆¼†QÈi8KèJÆ^ö`Z™é¯âËP^w.܆?a@:Þ÷õùüL?záÑpxÅ$¾>·täcpäLü͋ϳ‡ËíÀzc§ÚhVÝ'‹°Jùô«êWOåìfôz½Þ’NúNdyÌ[î¹|n¢Lg›Ûž›îÚü­qû3é&+ã/ºøˆµ\ðå¼²•;ó >Ù®ßhîó×û™7NøÇ|òüà7?ß~õ·yñí×mü/…~xþÏ?÷§¶¸ó¯ªúCßýá¶€ßÆˆt˜€÷d€ Hh™Ç€ ¨þÈ7(j˜øl¿×­†lÄWeì‡mÍ—0óS0¸S‚yãw#È<“3,bh5#|š“Èr»–|õC;rC7²‚kvƒø'lÒ‡>؃™C}(„âWmÌ·|(ø ¹Ã„†G…eƒØg…Û„…Ù§…[¸×Æ… ÷€Óf)fXj`xl¦†i-èlkè…%†vw9r‡V†6S‡vkNhv{x…‚Z—†ÊV}òFˆ…nlH†h„¿Ö†Ý6…‹Å„öÆyÔ{’‚‰œØ‰žø‰þ\ ‰RDñF¦uŠKTЦxpž^¨øŠôU£ÈpŠ÷-°x‹ywyºòx«ˆ‹¾˜FgD‹Áø‹Ä¸Fµh‹¤xy•WŒÌˆ-Ç8D©¨ŒÍ8%Âo¢TI°2ÖÐ)ÏøDÔX_Ôu:ߘ)ÝØe*‹dN–ÅÃȌԤŽàè.áHŒÖJ7]Ø%Je-#e]¡ÔŠ}ÔŒö^¬$]ÕQA‘ÅXâEuBvÿ$‹“%ô^§J!s‹ _¨SN¤8ñ’û"‘¥%#Õ‘”uØõ4÷ŠIuNÇO‘%¶ŒÕø3)“N÷õØvæ\p3ú8=žD¯Q“ãˆþG$%’B”””?¡‹6™/í Py•à!•^âH‰•^‰,^”ŒåXF_Y–¡•bÙŽf¹–Z„–ÂØ‹l—Å • .) r™—s9–dIŠwYKz˜—Г¬È—ì#˜ˆ)TnÉ‹‡”˜Ž™`†y˜ŒÙIY™Ã™.4™e™œy*‹‹VI-™ £9b‰Š„©™„B–$T­)ŽÅEŸù>]ù‹ q’0—&.W”¨D>²‰™Ñ’BìV›¶™Q0é6Dgš•Փ™À™Ôèÿ…N*^é4•Ä‚–jwjçæ|Bœ¸h%Y<Ç #gZÌyžÊT‘5@Ï©@¢þ žN uàór4Sö›ay^›3 ŸjÙ™Úñ©@bïØž¬r ØY rµž, akwMQ0¡áš ¡©™£ƒ é ™º¡–É 8˜J¢iu . -£2:£Wõ¢ÀŠ6ºP*Z $Y’…9¢;š˜=Ú[i —Aú˜J›)z¤Ž™¤ð³¤LŠ˜Nš‹¥%:›OZ¥VФXJ¥@º¥q)¡òØ‘Nʙ⠎hªœŸá1' é8¦%wšÄ…“rê[µE• u »È.ÅeB/£6R¥Z£Ov*2ˆê[}¢AlÚ¨tZŒú¨ó Ø§"§r—H[§’þôõPUŸh+¦xQwA)1/åN³URPãRæ¦:¨zJÛyª’£=(«“Óo—v¬J¡»äH17K˜:’ü"#Ú=‰¦Ò8LûÄžvžvÔª©Ðš“0y:ËÚPå)kQ£jL]ñRú´¦ùŸf•Þ$u½Ã”ß´©âJÕJ­êNÑZ¡1Hîút÷zKušq·%Ú)®äuRåeaÕDLQ©¥þÔ¦:¹­ÅT`ÇT­ìÙ­«­Ùz­I`+¡.µJrG_{¬¸º¢ÊA÷ù”úˆ^þ*>Ý©KÝÙ°®ú±Ô$53›aªº’ú©›K$6‹K8û²?ëQ5þSÃÊ!]º’Z§æc¤€¦ŠŠ¢ÅZ ß±išwPË´ú4z#9úSY+˜üfz«‡1h•V¬÷deë0­×˜a›—üv{»7·t[4¢8‘o«—×}y«·ºHiÚ·Vħ€+¸r¹·Úf¸aú·Ñ¦¸l‰¸‡6§»´m\µy§&÷¸ŒË·¾b¨Š¹Zû§yDºcš¨‡Û¹‰»5C©«>ÉJ·ºªTS]=;tÖj«)•ªµ*«±ªÓ¹ƒÆO›¯Òz°ø5¼¥“©º‘˯ìjðªLûЬÆ>ÐÛ¯Ó«° ɼÁ›¼Æ­«%É*¬k±Ë“Üh%{ä´7j‹N9Û”9³æ©æ ³@ ¿Bë²ø™”À«¾DŽê¸òA¸û46¸š¾¹ÖµüÀl#_«l¦w¶k{Á.ª92f¦'·lÚò祥ŸVššñÅÖ1aSÎLš6HÙ,q7н“·mÔµA.¼8ñ㬇'7¾¹ÔçУKŸN½ºõëØ³kß.ssÈÄ—Uþ÷¾ülò•Å—Go~¼g÷¢×¿—?½ëð÷ÏÏ·¿¿þúíÑg| ¨ÿˆ ¸ ù1!„þIX!…Ât›r4ýÖ\wù¶áˆ!rx’‡I馢‰¯¡ˆÔŠ$~Ø!t"–È\Š,U#ˆ2¾˜#g?µãŒÎùx#wH&©ä’L6éä“PFùÜQR•X^©ånYr¹¥•^† æ˜]’ùe™hž©¦˜i²¹¦™nÆ çœmÒùfxÞ©§œyò¹§~ è }úg¡ˆª¨ ‰2º¨¡ŽF é¤Rúh¥˜^ª©¤™†ÉSŒDöØ"¨FÚhª¨ŸžŠ#©£Ù*þ«ªz⑯†+¬P 9««:9”®µ–Š*´öZ,±¼";¬”Ì6ëì³ÐF+í´ÔÚÚ {Øîçà¶ÙØ­‚Üjûíµâ–ë­¹àŽ;áƒì†{î»é¢K.¼óÆKïºÖ«¯±²î«l¾©.ûŒÉŽÆ*¿¸ú+¤‹ ÿÊpÀ·üÑQŒÅ Y|‘ÆS„qK@n¾ ,ÄÂFœòÊG¼šÊ-—”ËÇDqȃ<±Îݼ#W+ôÐDmôÑÔÖD1ÐL7íôÓ#/ õÔNëLõÕ@[õÔ d­î…í~`½dã+¶…c›-¯Ú÷‚í®½p—íöÙ¢mwÝx‡½öþÜ{§Íw|ùÜ3Ï ^8át¿(Ç|ðË,7.ù¿»&Œ°Ä5 ¬!ã”7¼¹ænÜ5âq|¸@8?dúE‹/޹ÃÇ.¼ÓêD;H§~qÅ;^0ì¿›,3P4œ“ëB»Ž<ÒÌd¸IÏ=î¤7oýõØ›jÑö-O-òpïžøò‘o¾~çþúê·_>ûﻟ~üôÏo?üI½õþZï¿uÿþ»(@ùáï€L`ý¸@ÞÏ |`'(Á Fð‚Ì 1¸A ZÐ}‰3Úò¼÷¹× ïq™ƒïtw8îÎ…¢ƒ!ëBG¼‡õîr•3áÌl˜ÂÈÝp$þ$”–÷‚8Ÿo‡³ UÇ;è5QzO4 SR¼úPvG¬a쀓)>‹„^ÌÞ´Â(Æ‚±ŒhLc’jrF)Ñuzk›ßæx·8Æmj#§hG¹Ñ1ooóc‰GA’n},¤"/„=Bi„Mûa}g9Irñ Ž#‡WDN…‡ÆÛ¢=‡DÎ$“Nj@2YEOö†“A%öd9IRR…³¥.s D®RqjD-­7Ì`ó˜¾*f’F–5`.ò‰üÛ¥iÈ)S˜„¤æ3‰ÈlBÓ›Üì[8å8Îi~“<œ ø¼¶N¦¥óxÌ<'WK^Öóž—þ4È5¶IQº²v¥¬$>(ÐPf±“ÙçèT¹Êy6´! %ˆ3iI‚Bu èL–V=drt‰µèóyË‘Š´¤PŒÚG”'Ïš“O[èòþŸkaí^×Í5ö2ßåã1/¢þ•˜­ÌcÌÖö©jö3}‡|`$Ù¡aγ¢]gÑÞÙÅ&#=Ÿ=·9Íñ¥joÝIäånšÀ°†¼éOÚÁ(^±ŠSÍjH£ÚÕVµ©ùÉä*“lµM¶'›¡‚çòùµÖÕ!”‡[ëaã¸Ø©…ó”SÒkíÌ–Þnκ»T,[ûÚV œ±KgbW—Ûq>i—cùhF7K²ÆD·¹×Ín6;;‹û`ç-ïzsÐÞ¼·¾ÝÓÓ4j ßôÞwÀóMðàx ¾ðƒ+üá -÷–s=ga';ÚÚî·K mõP\άµ¸²þc{qoO©ØÄ5lǽràn;¬ÓÅx¸[^q*Ûæàv"µ…óv7éÝßó¹Ð‡> u?‹ã§Žu«“ÎbGû·Ÿ”~5ÓW ë¦G]éU§º±5Î,®OèãâömÉíôþB½Û_·5‘ 윓¼í#§çà¼þ$£}Éߎû—ó t¼…½æ(eùͯëÝí¼Z=':’ú.DÅ;^èlÄ0¶'?y§f]›˜/±Ô¯®ÆGëìXŸzæSôœ×zêKßÏSçÙ*¼ÜÁNó]ïô8‡ûdÝ>{µ›DÊo—ù²¥(ñÖþï §Þáwšx¼K›ìÏw>Ú¥?óˆ§üñH²;µþýî—R®ŸNø6e)N‘¿SåO?ú׿%ºcïßì7¿üÕþúÏ?þô¿¿ýóÏüûQ!t}ÆglÔ7|b§w<Õ_H}D{²w€»‡€!g€€×{ÖGk±Ç{…w|;³|õrÂGx¸8‚&˜|('_¢–[œ&Q㵂´•_jf_­Ó‚eç}ÎÆw8¸ƒü•cgÆ^B&a‡&SˆfhDhyf{úeu›×„¨ç„§ƒ¢wzLø„VX…X¨zP¨…Wøí´fˆfƒH˜„@†_›5Z5`^Èv‚xw/áƒfç{lèqt˜ºg‡%8Ágrèk‚„—Vm„_G8„þšÖgd{ xk¸†OÇ{ˆ|”(‰x‚•xÆPA(^„Öf•T5ØgJè^ bvY–D±ŠydÙEQYXA™˜é_r(ŠaiX€hĸߨŒÐؙҸ…é@³A´ í˜y#sÉ™ŸÙ…ɸz¬)ŒÑ(›žI›­ç‚4hd–™‹*x‘šY• è—Á‰;¡G(ÑYY)h²äÈi•Ĺvx˜œ¡ R©–Õ)ÙÍþ…'Ç—Ö }މ2@ÙlñDž.H8sI•y'˜(œŽ8}Ù©NÅ™3$‹3¨†§)2YœGh ‘ô IókE³™³©Œµ‰ ¤I˜6jxN9~_ŠJç=“jê ›ª¡ Ê¡­ Œ±‰ 0æKÚy—à)rØiaø©‚>ù«ùdûÅ\0j;:|]™¢åè8z”^9œS œð¨‰ ¤ÐùˆTéa‡è‰z„˜dXÁõ«È£8š¡ðùžhÉž+5Ÿê… F–HŠ\Ť&¦/šbº¥)TVB%j:TÙOÊDt‰‰Ikz§mÊ%yʦzÚ§|ú§xê§ ¨þ{:¨†Z¨ˆ*¨‰J¨ŠÚ¨Œú¨ 5ŠÈÅi»IT:šŽz¨™º¨—ª©ê© Ú¦£É©{©òuŸ;™i¤º©¬ú©«êª­ª±úª² «¶Z«¸J«º:«¼z«»ê«½z§²…”ÄÚB V¢ÎÙ—Ïéá”6:gY9eÊgègh†¤3º£g¢ÉúÝ:¥D ,P@D@åJ®ãj®ÈŸUºvž×˜R*a=2­"¶¢;Ù¢7Š—ùz¢¹‡¥ùuê<kYî hgJ QÑF_bev°»K¹ã;k ¢ š!ê¡3S¦ñŠ`‹!˜úÕjy¸ˆ­ʱëþš˲+ë²-kH=¤?º®6[³EJ”àŠBô²™I2­¤9†¤†›£öXậßzú*´M˯}¨—ÊZµÞÊ®W ­a´¾¹Óš°DJ¥Y+µû:í±hK¯Fai×ñ¢`‹¶pkIŠŒ/+³1;²s+MÈó Äwƒv[{[{y[·xk›†« ‡;vÏš­O˸܊µ[©ŽÚ¥¶Ñ ¼ù^4(y~¹ÂÕ[\›³ÚºžNû¸VʹÏ)¶¦›—ÿÚ¸T{µ¥û3¨tœ в ¦ò:¶É³¬»ºd;®»³¸·§H¹h¯Aö #co+¼Ì{8i“4ù¼59½Ò[½Ñþ»>%;½h*ú\o× ½ã“5Ö+¾Ô¾çk¾å›¾ì»¾Òû†:û¹9j”Lë£:›¥ó{'{‹µ«„Ñ:µŽ!¦‹Ë•¾º8À¼µ ¹ªëžÀÛ¯¹Ë8–K»5x­D¶5B¼ ÌÀeËÁ¼»ŒºÍ+‘¬eA±¼Œ9Â*ü;ƒ;³të¯ ³ƒ;±ÞMŒ÷¦-¬j^“Ã<œ¸2ìà Ä4kÀºÛ»Ž»Á¯ ¿=‹ XÄ/a°l%ìÄö»ÄT º£k¶|ÄÌÅ: Â_lÄ­‹¥éyºe¤ KºÜÀa¬Å œÄ¼Âæf°ÕAÇÖ1ÅrœÇr+Ä/|·}ÜÃþˆ«TûÇÞ„Ã|<7« ÈÈ‹ÜÈ?ÌÈçÅfŒ³ùkÅ(šÅUüYJKɺñ¿J\x¬v’lµD¼X¬Æ"üÉc ƤÌÊ¿›¡¡¶&lʱ¾¢+Æo¼Æ Çg«Çü…ÂHÌŠéËÄìÿ§ÈÜûwÌÊœÌÌÌÌäûÌË<Í]#ÍÎLÍT2ªØlÍÍÜÍÜüÍÛÎ×<ÎÞœºñ[¿§ŒÄº µ™|žœL¤žÌÎé¼]®x¥çü XÊ.XmÅà᎒XåàæºìhEíÎU‘Êßξ5ÖÞìÐn®ÝÞàÒ~UØîßßžîÌ®îìXÈngp%¤®®Ø)^ïÆºë€¹uÁžëûì±Ûâs9ëì3®èQ~å*>ïò ë4®s¾žêpêâÞÝ·6‚›~:Ÿ.ñK.éñƒ3êH>—NÍèÏþä]TìLæ™=+/ÑùîÞ0ÕN>V`"»ðŽ70?̪I¶ók»æ9ïá'´êeóAžc§P`ØŸ¥Øw®v@o–J6õüù:V?QŸÝŒÎôcŠiñ}õ½^ȽÉYóÕôô˜äòû¶ù)”b¯Ýòš åEÆúÝdÿ•ˆxahŸ_joxoÞ{Ç\_˜†˜Ùœ)æM-Ý•óf:÷qo¦Ž/÷­hÇ8fSµaH¨øÃ*wç­²`o[†h»¯Ñy¾°Iô=oùûùø*ÌÈq.ô¨¯mJo»¯¯¢‹ÕèL,\˜o’εû¤ßûÅÅ:Îk[õ¿)ùXþ¥¤½õ6݈Á¼¶^µÈRÇ?ø¼³÷Ûi„Äïi>æðʽC®õÐqþÓÆýÌê¯÷ìáPñþÞÊcOð©²Øßù7/:Þ/ïÑ@à@‚8Xa 6tÑa‡¼hPãFŠ=~2ä‚$EžDÙ1åÊ•$M²äèæÌŠiÞ$(gA;ofô‰³gP¢Eîºr!Ð¥%Z”ˆcD…>“r<00«À­ º^=j¬R­e¹šõжëZµmϾM ÷eØcé¢|ɮ޸}KÞ­ ¸%A¾…Ýþìñ¢ÝÄó6¼òdÉ•ûF¾L9³eÌ_‹þµª%cOMŸFZuTš¤?v… {ðÜÏS!t-x¨AÙ"w×fXxNÄ){§=ü6îá£<ýfôÏÔEææ¸Zûöí?bož¼Fë€I"L^½ãàégž/¾^þ_ôDở/ÿ¾úò‚û/¿¢ LÀð408ùV›ÁÒÔcðÀ° *Âõ(L0ÃÑ4ŽÀò0ä0%ÆÊ#ñ5 ÑÀO4Äa«D_lÅdÄÊFòtäÇ‚pÜÈE?Z‘¬!ïÂð?”ÌîÈ },ÐIñb#RJ ibòÆéäËR#!­n@0AÃrÁ1;œðL$ÓT³±/©\¯K2ÛÄþéM©è¬Oט²éªå¼³J@mRÁí$´E…úô’QæT¥ )ÂQI'ÅÍÑE sƤH[êRHñ¤ÓR+=”Ô™ŠÌqI(ÑÂEN)U”V#?UÔTµtÕË&g5´Ö`o¶ÐDgì±Wc 4Ô0ñRP;½îU¸xm5[l·ÝQYn“]VU#µ=ÉT)“ܲµ¡}4Q‹röÏÛæ*¸å¢¢—^]ýFf#•”){ãí3"ª¸)ƒßÕà}­u¸*vÝ•^J †ê]„3® ^†Ž˜_éÊ$™?ïÄõ×¾öPÆke8z)½ýþõ“Z¨ÒØ^©â­hgŸ‡þÖ ™}𹉖8Ôœ—ºgœæùÒ¢…ryÒ£#Ø)Ÿæš`N¿¶5hžªN΢Ìöm ™Éfù£©oz®í˜âË0î¿ð4çv‘û)¬mõ¸a¡ÕÛ9ºwzìbÿî_á÷[qÂ#¶û½ÃÛ-i£}ŽüñŽLË»i®çÆ[nàì®ÜtäD:`«Ö¹r}«ÒUÏ”;Ûo׎>Õˆt|ñ¬9·p›>}kòŠvå½Jžyµƒì=øÍŸøQÈŸ->óç›Ýyï»_vÞÞ›qàËÚb̳Ù6Ü߇?~ùçgð<Ô.§ÝðåÃO)õüý÷K¬ƒ:ü™pÍB˜Îþ·5¯ýŒ*!MåÌö›ßxêc˜w±npPc ¸ ‡Ÿ k}4Ó¢&¯Ð¥¯} á·Œ“.“‘Άù;^Yò6Âm#ƒÙó„öCÍÉ‹5ÛY2ªÜ+‰†Û딩UψW|"㔥}lrÓÔØ¦H4"þ ‰5Ùâ×”xF&z‘x`Œ¢u´¥Ž ‰™áÆØCâì)£_ y;õµÉ\¹jΞØT›CFÉWß™ÉÇ -l—Ääi ÄXQrq"ì¹@9Jjm*“§$²dH˜Nº•¯Œß#IÉJU¶–·„_-g «P®’—»¼V/…þ L¿ÈÒ“¥ì׸ŽY¾•ܱ˜Ê\fµX®hƬæ$gX²—…Ç™’¥ÀI#t=)›ÒœÓ9‘‰u:²9ÎÄ dè\‹´¶õ±“=lf/«ÙÄbv³z½˜WÅuÌlhz‚…)O•˜~Ž…Æ+è5›©®ÊVS‚;t+%ÕÊÑçÕ¶¬¹Ý(Hœ)O¢BsrÁZ,>Åd½ÐiU–\ÝÏ”Öâé2¦Ê1j[•J¨ê6»ƒÙn>»KâÊԜԓëèôT”¡­ñ^{uZ`qjBÁú«nû.‡®ÆPS%7œ‹|«:³‚ñu°c/FGxÎÛNS¥V0ßú0Þ~ô…ÑŒÄ|*ˆYÔ¡Žð‡3âÕ-U‡´ |‡ä[²Ž%qä/Ä&JÒþnb¥%­ñlã·£e·âúqB­šZ–˜Ÿý0…ý#Uõ™TN–"p¡)²Ú$8?Õ›0’c É$o˜ŸVV²z£5eö„wÄ£îk7¼÷â Xt¥‹HE¼QØàªË~([\á0ëùÌB&q -<8”¡l)(ßjG8¿“  Š‰k¹¾Ù#ó}ÜŒ{µR!ÉJëBþ:‘3/+|Js˜·|»YÑUÉe>rš›Üæ%ÇùÌo®sïÅ|çY±ßüt'ô ËoèôÓyÎk®t›=—EŸÓ£uø1ÝêI×9Õ§îèX’ëòÃúÒÃþs²_]ìg/ûØÍžv´¯éVü+gÝ8G±Æ¾ôÆà¼â­µËéãrkµ¨‰#îˆËt·°!ëqrÜ’¤ŽNVx¶ íâr÷rýñ›dq»÷Æ w¦ï¬é¸Éln¢üþ½m'#Þ/ygƒ»+y´á/-mÙã·öszì%_Þe°?°¿ŽS°ÆZÛ`£¦éŽÏkSd3?DŸxôIZ`DÝ]ú*2µl ŽC9CØÐÑñŸ‡½?yDãÄß7ÿ©Å/hò¯ýçoú1•aøÇ\åä_2ü˯÷ÇÕžì>m:&ÔÓ>à Ï;¶êø<Á½¤¼rõSƒ/[@U+›Ððæ«&T@åƒÀ ôÀä<;´Q¡@äkÀHJ5Ä™¶Þ8< 4­9Áë³A5™5åJ®¤0k=ܺ=ýa½}¿ 3Â!t²|?rŠþÛ?õ“¿=sÂ)ŒÂ9“þÂ*¿¬Àc3,d%±á=yc¿'¤3/\Bk<Ë!¸$”1=Š%­ã©³9$$d<*#¯-´+&CAÁ>´@XCáÚ’ŒA—["-¢4|@ܶ7üºî€CIŒÄ8d/$ÄÄ5Â(/T ÁtDPÅ+{1Oœ7‡ƒžÑɸ‘0ôÃ*ËD5”E@´¼ tA ”¼C¼Á^(Ѽ©¯6^d,gû6\|AdÌÃÏê,Îò¬gtÆh¤Fh4 Ÿ›FkÌÆm”Æn¬FnüFoÔFqÇqD¬U ¶ Z˜ÃZˆptÇÞJ¬j®fɈw,Ç{$Ç|´G}4Ç~ÄGíþÈ=üÄW”/C@Zì@„lÄQ D j7D”ÇJaÄ;<üIG‹y3–‹'=ì<ޤÈP$H>IAÄÀ€ìÈ$ÉLÉyû«4b¢ÑÅ„+£ñ4½q"Fs5•¬ WlÈ„ôÅ1ÆŸJca±Y 4t,Ê¥äD3ô?(ä?§$ᨴJ¨ÄÊ2¼J­ÌÊ+ÜJ¯Ì»A £ì ÍûJ+L–LŒªìJ´ÌB¶äʸK¹\H™üH†4É*áɼ$D;Ì?…¼Ë?̱˜BGغI^câL¾ÄCHǬ˞-ÖaUŽd¥Õ£èÅ‚Ö[5ŠjÝÒZ-ÔÑÜÖnÕ;%ToµÁPµNH5ÕEmGQ½Ôr%ÕsUNu×u=Usý¨ÝdWx¥×vM×{þ%×ym×|Åר€ÍÖXÖk­@ìÀÖ^ÍBeeVa-X„ÍUƒ+;²Õˆ])km؃=›‹eXõØnËÅ´XF[›ÜIjÝÓ:eÙú\ÖP[XŠeU"³X:uÙ‡}ÙYLCƒÓYRן½=¡ZA¬I̤­ŸJ\ZúñG¯ØW~ÄÇ}¤Ú§­Ú©µÚ¬ÅÚ­G„¸Z©Û¯í ‡[­ [³-[®MÛ³íŸXäÙ·M™Q3Å>ÕXT5V8 ֜ҼÝ>XõUŽ}±½º­YÜBÙ¶=ÜdŒÄEÓ–á6jY“­H‚+)‹Ù¿uV`½Ù–­W•U½¥Y¿íØ&sÛþ5]¼Mç;Å¢e]ŠCP¢íA¦Ý¥]ÙM :œÃV ×àÔTu-U€í×E^ß×ß%Õ‰ÞwM^PjBâ^~Í!M”Þž½Áí[ÚI ¹Ü%\ü»[ˆ\Ÿ€R?TÙ‰Å\nõÞî­Ò™M›ÇeÉýÁÁ€ßÐ[Õ­ßfe_Îý\œå_íµÛÌåÕÆÍ_7ÙÝÕÍÀhkݵ@…]0yàÍ˲óóZçØå5^‚Õàâõàç…JúóWÆ`|ÝÑî`€¥`×ÅØTÓ_Ð\ëÕVÑ àÞ[ÖWþNŒE_bUßLÝ ÔÀ7¦ai]ÙÍeâpÃþD’“˜A˜|Uù}bÖ»×c6èëáÀ"6¨Àe`¡Œ¼„Û¤Ùˆ]ˆcC5ÞÄ3qá8c¼K 9¦c"T ®ã<†Z=æã9öã>ä?ä@&äA6äBFäCVäDfäEväF†äGÆÝ8¤Ýݤ§³]‰äMöãJ®]¡»ä­ó:N&eI–ã7N“@®Þû=L4²´ÐÀÌõ ߦ4_îÅa‡åÛ°(cËccˆ›Hüêe^þ·’äáŒ%âtÊ“ŒTÊW–8±Bâô½åï•ábŽ2Mœß-Ö½ƒûå¹q_È8*¶½Müß©²_ìæNê*43¥|™ÇÍs+Tãç VÁ"ã°þ$STd§£á5{H<«^aáÍ`6hèE讜g&èC[èNaò³“~˜{Óû=ߊdI€Yfׂ ;†Üÿ‹áþÍç®bÔ5idΧmþ¿rÞ_cöe.¸FB”Å[3ŽF&O³·‡‹-h®aºfj>iÎ[MnL$Ùa4éâKê#±é²™#ÒébõJ´”;¿ºdzÜjXž1nèˆ&á„îëƒöj0i•Þà¹þÅõ”à¿a.~#ßy.vÑ+f؇» ‘Ößöi%®åÖëþ1ê´Fi¢ÑfêÍ®¼ŸˆuÆÉ.ì€3ìÑÀ¥îbú•eÏ–Ó—nbÞ–#ÇÆèððAÐþí£æE+Câá†ì£t˜·¾^n¾êç6°k±~¾è¾mÒn46nYëÅ&뙫»Ž43BàlÁŒê–8ÏP[´uïö†o¶•ïµ}ÇížÁ ,>úM¾hݘï÷V,ÔëÒ‚é0~nÍîmÎÎm‰EêÎæD¢+ t²;únÚîhX´oÇÚ¶m>Ïrg›êiêWn¹9ñž§þŸTñ>æñضîë#ëÝ!½D‚×ñ{¦'”Vï–×Àlål"a‹ þrr*ýñ.è–nPŽ]òØœÛÒ–æ¦ÎhÝböðbé½vé,/ð/žmìï$fp þiümsÓžq,—r#.izsËcq”*¯qy®%5«×.;ó”75ë?#ž’êBŸi šs×Äç®p+$?r#/ò&×ôÃÖ‘±È*Z» ágD2=$·´OuG/B—Rgì†æóà&îkf™0Ÿe!nð/Ü.¿õ/…lúLâbL˜ŽÉ——tò:ïé¨^tr¯u¬I6Ò;7‚±äе'W™ —’ _â'ioWmú¸f7oˆL! š¢üuw+n^o÷ŠãjŠILjþì)zgŸwÇeªñ¶Ý<Ï!W~ïó‰KÄéqvòÉžÎ,t—máwƒôÖbøûb¹è.1ƒÇ`, IßöܲQKâð‘Ï^R'=Ò”?y•oR–Gù•‡ù–_R‹l퉪eNŸ_wæ®H™OR÷¨øƒ× Ø2£ëYŸœ’§d¦í1e:—s/ßÝò5ú^ÁÃÑjiÁ*[úR÷†Wˇw÷[n‹?¡yÿúz_{Z!ìÎgÒv'™ôXã\Çu6çr7ßû§›ºv%EGÌI“vä˜KñÇcÀwåøZEÈo·h?Ì›i9ÊqñÒþúùÁçVÞØò}ú È^þý¥X€ Ú· K?¥F—j­È‘Iì=Và„R‡’g3ÉÖaM)¸Ôˆ.‰؆¶•¢S+±¨bX/†ÓMº&!Œþlq…aŽ·…Y‰:™Ó?^V˜f<öèce‘©”ä’1Fg•l§ …TjØù§åE2F™’—_Š9&™¢•IZ•g~Ö#”÷æqH‘Ù&s Ñ©—¿Ýé!H}¾äן~(¡ƒ* ‡ö$(¢Œ.Zh£æ©fCpUu©Ž”¢Å'¤*ÊéBajúP˜Öxe^qŽ:i{'¾$¬yR‘ŽºéJA²zk„©$¯v~U#Žîj«µ:ùª¬Ì:ËW°4ÎjZ´;µØtÕb$ªO¡¥ZÝ”«-¹åzd.µ¯»*›S–TihIM¸gg™ª†×½½ªii¢‘~¢¿{*0þ¨<0Â'|°Â 3ü0y‡®«)¿Ž:¼ºÐBl¢Áw¬/rq†¼¾u} '²ýâ¯ÉXʹï´)ëê²5sM,.Î+g쳯Ò"„*Ž@MWÑ]Âí¬ïÏòÚ|d³£ÍÌaÔÛºÛ‘eÀ’:Ö[ Ôõp¹>y5GYƒÉõØ_[+sš,QÇZÉY"-çÒo Ûô»xë½÷Ö`÷íb¶cû /¶ƒ‡8JÜv‰x·KžflPq¿iƺõeЙ{§yæ˜k^·ãœ‹î9雗޹驣¾ú誷Îúé¯Ë;í®×»í¹ã¾ûìº÷Îûí¿ <ñªC‡òÉ+ßäòÍ#þ¼óÑ3/}ôÃû^<î”Qß<ôÛ'ß½÷Ïkþ÷À_¾ùéî¶Ëp“|´È•#+V¸Î%Ì_© Y»Ò•²meîq û›Æbw²ŠÍ.c9ªÜïzw¼æÅkeÛÞér¶½î}/|ãS×ò¶¾¾ímnñ»ÛûÚ7¿fýݯù+àÀîæ€lNý"¸À V0;ÿûà /¸ºFnyµKÝóW îðrý*X [wÃowC ÝŸøÃ)¬xÑK\ò–Å"ž1‡Ùëâ7wÅ8–±|ƒ,ä!¹Èd ;spring-security-2.0.7.RELEASE/docs/reference/resources/images/i21-banner-rhs.jpg0000644000000000000000000002441011766764657024165 0ustar ÿØÿàJFIFddÿìDuckydÿîAdobedÀÿÛ„ÿÀBÿÄÇ    ! 1AQ"2aÔVR#3$•qC7‘¡ÑñBbUef–w§Y!1AQ"aq‘2ð¡±ÑB’SÁá#3$ñR4r‚¢Òcƒ“³ÓD”´Äu6V8ÿÚ ?ýüQˆ”D¢%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢.m{åkBÄ•|eäÞ«áãacPq%/$è@DÇÅÇ¢êAûG¶ŠJ é V)¦†Þ3,îk#¤Ð"åÎ2fZ›<“l00mÅã3²PÀ?1NÞeqhQ.›’våŠå@kÍÝn»8°¶ŽI°ãL­ã¤W†>Í1ñ¥Á„­uíßžXîX²Ö+À/Ì Ô€›!´Únߘ§'*tŠn¡¿Â© uÚ#^~~¡qWY“æ”pÃüšÎ"¸W–ï"ÀeÉÙëyÚlò=ˆá£qÐ<òÒx{ž7i@@TQ¯—ÄÜbaè&ãNDÊ;Œp.¢²ê–ØšàZj.’Êw(³Ž´is[þ3'¤b…Ž NÚ7Õ­}F6–¶&J³tŸq58Ip dÌbˆå›Aè! õ­‹‘Í–'Dà ‚<#a Å·Uè”D¢%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢%(Š=挲êÕ4u›h"„•ùr™T£Zª¡ÈÚ5¢D½œ•U01ÛDÆ$`2§âD“¬ªIŸåë½®‹fnîˆîkkB÷PÑê$àhÐM0U¦jE†XDLÈÏÞÒŒ×+ë¦tÅI:1TY»"GÖÙ#Ñ(•‹S _S.äNàú²ëQÔ5Pû—¹†û#¹MuDMuPiˆi45ÌEq¨ 3Z‹vï;â^"ã§öêìÝ+ùý·$)3vÑu:£ ÁÙSATĶª§ÐBˆô4Ѿ2tÖßɤï}kc“–ù-¥9¤µåðÈÖ8ž9d{©ZiV`0#òóüÊ[Â^6­û Þá´æÎÃ;ÜrÐÚŠ+C³Æê•7,]£¨oIbå÷†šVû´ÞvilÖ¶åÔWzl€QÌ< +’F>7Š‚æ<5ôpR#ŠŒBÓnˆF2MÕETˆ`@  Óh”ÕZÿ\ºk›ö°ôcÛN=Õ ù”¦Â×–grãyÓÝv[Ñg#¸|ÉUH‹…2mm0ˆ“Ô€D¤ ApŽÒä Ù¯A°z‘©í+†[Ê_>„çxá&¥ ñ|5Á®ràÇð4'8‰=¶\Z¬døœ£l¡2ÃzQ1ÚJƸ¦ö:E©ÌÝãGh”Ç×nå3àS»Š;Lbèaì» ûMRÊ-BÅâK9˜Ç öq âÔªb%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢%(‹Êœ•B"BUÉ€ˆ±j«ƒ‰‡@Ñ2é¯ÄFˆ«{J¸¿®;Ÿ(ɺîé’vÒæAùVñM›ŽƒÛJeâ ÈCATª·)µì“NwÞ•º–ã–(ß[KCËh¯„¸=Ô¯õi=hÇŠÏ u-›H"ÙYU$'yUT0ˆ¢ Š(sj!L¢">À¯»»LÒH $×I$ðÀI W-P=é*Úzñ»fÙ€ƒ9›¢à”gÓoð’ÎÝ7½t ©GMzk_Žû¯QƒXÝ:–¯mýêþâfáO ²½ãÌ¡“RHáR·ì!•%1UîÂI'*þ–pÚ:êŒÞ>äjÊ‚`ôRD™Nò*t6€dÄvÀ>Ÿ¦;÷PØ{Ž;ȤpÒ'peÌuð¾#Qšœ3Ř¾3JƒV×+Þ ñ?–úý’qúýB·Ç†u!€ä7]à:€z”ڈ֯»’úäÜ;Q^=ýÔùc\WÝ ÊÜ¥7›Æª¦b„J:†ºþ5Ö¢Fúb±HÐBäÆèqŒ3HŠŠútôºA»°œãfgq "%ØC<†]²çù…›2‚#»¥ú¹ä2Mµ®_X‹LЃ\#šÁÜ CÀá\狊ø³³+Õ¢÷Òýpý×Úºý쮑XV22q®].żƒ[n,Ñv‚®›L0®ÜŠT¶œÀ¸A+ . ’C ÇJÞ-<âµ P¾Å2IÒ UxÕ7®Js¶f£„ˆéÁC ÜÇU) A€€µs¦‰²\æ‰]Á¤Ššq âQeVDX^c/F4²ó'pXx¤‚m„:çL¦>ÐÐ:éWK<éÞÆ4œ ˆJªóÛ˜à›Çýâ°~c§þjœ} P³k2,WoYÇ¢.»jɸ +»p“d@ÆÔ@¢ªÇ!7èû«²Å sÌæ±î YN ËüSl~cþo÷ŠùŽŸøðýöýj• Õhñ›ôAÃmž· Av‹¤á1~¢‚¨˜ä^¡¯J‘±LÜð¹¯gx XUXN§ Ø®fϦbY¹ ÇnêE›uÊS†â ’Yb(P9GPÔ:…b’òÎòæ–6H; š¨•J…ø¦ØüÇüÞ?ïgæ:ãÃ÷Ûõ¥Bõš»jù9d廯ÊnÜ5Y7Ha!ÀФc¦m§(€è=4©1ËÌDæº3Ú#ÖV§'’1Ü#Õ£foÛ."E¹¶¸a'tÁ°z½»VjíòK¤o°Å ù—ö…g)‚îöÒ)Ûůš6¸yÜTÌD-ýbÜŽü»zZsï3*,¡n8yW`‘S©á˜¼]nÙ@:ŽÝ¯´Ö´kùy6vÓÍJåŽV=Ôï£\J…鹸­ör âÎÃ5•X[°Œs&É Ë‚gXPfÉUÊåÊÀŠf0”…0í(ŽšÔ™/¬¢¶ÒÍn^hÖ´9Æ•£ZMI &€p QÁp>\Ü®­\‘%™(d%oÈŠ í9T#5” ”ÞáâÖy"Ò;ÙkIõ ª¨™ƒ8Ûn.1 H–-X&( “"IAÝ š~Šàyµ‰]#§yþ!Ò=Ä÷—¸¸“ëv8T)ö­Ì1Z/)3§”E;ÅÖàó™v Øõ#ùDC’ã‘È!!.¿l>Ô›ŸR %çN¶ub[M:M—£?øÛ†e¹p5tq8ÊašQA%qøHñÔ_tö³öMöÈÇÈ>¿Ð¢¼—eD`kz펿£ò=ËtºNËØÓ¡cMZÌÄä]X§Çn¹:Ù¸ÅTVïê;Zµ£µ6v™Ñ›-Éo®Á¿oµˆ,º|öŒ{¡”°å9A"C'0‘“—Gˆ4À>_©p6’ï%C ìg¯_6Ž<™hTVvàˆ]ˤŠÜ„0ˆ˜Ç@¢# Ö«²Ò¯ïî"·‚'ÖWµ­qi «ˆ—@*EI4Ui!µ&œUßB]¶dØ*Þ¼­;ëF‰[Aܰ²îÅÉ•!_Âǽp¸"}[t z×è´ÖÅ­·†XÞæ´ ÒM8ä^ˆI°kšO‚³Þ8l’„h«–éqõ÷Ÿ¯õýoùë¹Uü =Pùǧ½’?¤r½®#\}Òþ‡Þk¯÷È”8¤¿Óô­?Õ.Ô½¯ždñ^ÑÆ÷Ú·ìý¦,- „$ŸÃŒTùîÉcƹ HÄÕ> €^êE1‰®ºjò¾"ôÝ[Xê¦ÜÓ4ýÛZšÛ,2gs2Hf~S€¹¸ö€HT¹ÊÐÜ»ïýCn~ð'9Á¦0ÌË¡}Ì¢„U»wß³`{döEE¾“)w7“no(‘”ÈJ ûNžuÆúËT«Ñ?uDàÆÜ<E7cy„xçñl­<‰x‚ÃL×Ç9—6ïZãq(úÔº1D é˜P06m ”C €‡è¨ 5ø²q?+ÿ… Ÿë~Цoôñã_!ržPÉ0×S˲]œS«Åݲ1LÌÞ‚1ÌA6MÀRHÅjÜ a¨Á¨õ­¥»ú°w¾¹&á×â¹~¥+×Læ6ŒhkhÑ€À ÷¬¯‚9™Õª¦LÂìyûÈ^<Ü‘7øÛAÜï­†nGm%¹Š¸,Èö‚òU4ÅÃÔü,Û€›ML%Û\§²úQ³µ¾µk›þ9΃c Ή¢W5à²XÜϸRG|ÝØÄdLtîŒû#õ+Õã— °ÞÝoñdü{›Í¬K9Áš¸^NTaV~»@Ž€¹ˆ¤’»„:˜>Ø›¥{G§2ÜͶ#»k'2WIQqm+ÃÚ>u28™rö¯Íý¨N Ÿ”ªÿÛ¼2ø6`ZA:+y¯õ åó_äE2ݯ ÚÙÜùu×NµÁºhéêäþ³½ëÝ?1¸äry•Ïï2çÍËÆ”¥+‡r¹ŽæÖ•?J²¾=p¯Ó?”1æ$‡Ér‘ö¬“H©u%î¾é<|ÔÎÛ‘¤;fpC Aêö¶·öÇé?@:‡k=æÙ‹P’ iÇ—Ë”rØ[If«å”vT{n µîÉKÚüQ´Ð®¸(‘™ÆÀ6D¤ùRùCûkŸ6FÞønºÚv²ñ‘î7À ÃMÅÃi%MFVŒ£ `0QØÛbÀ\|TïZä|Gì_P>'¶áUÙ)-mIÏÛ¨ÞÊELÜrÈÃÙ÷Ìå˜ ¹”v£'VÀ¼H ¢DDGoZƒ ¯Oô~¶m¨úMs$¶O¸,’WŠºG5íÌð i‡ÛmKrâiЧìÛ;y'Õ3½o¿ÀÜ=ÿ•Ü|(Mü+jü]ÿÚ_üÈÿ™‘f¼örð ó:ÈøaÖç´Òío¥“Y¹1±±‰nAt¯ Ê ˆ4UƘŽÕÄq>uj8#‰}áÚwÝß—·LA µá'sÝ¥#ÙÂÛ&/wÛRbƒ$\,¢ª{× WFìÞ™lž–¶óTÐİE, Îùe/kc‹3óx°hh.$÷),‰‘TµSÝňòW©¼#y;ê~ßÇLKiq^¦;CO=´ßmñ3‹É–$8™DÔ/n^U2wL›!%råöÙ×þ §×º…j顲±g'HÌt.;ÇHÐjAžfŒÅ°¢–ºç4ƒ€à­OÓï”ÁÉÌÍ{‰qO+ã“¶³òtzåž­&Ù§s¨ÜàUNæjÔçP¥?EÊ`P*a¯GtK¨£¨;A޾u7-]´àâð(Ɉì€IáI#@£B“œÆcí*z§Æ’ÿå q-ÆöM[ë–‡a3 Íò¬ŠªwNDˆ·¦ rÈŒŠ‘I•$ÖÉiòûDK|F[k©[SlߺC£\ÊÆÈÆ¸¶¼ë–Fò;œX(CNÎÕ‚çXÓÀýjQôÿÃ?ø.Aéÿ^>û§ZØŸú½Ò¯Â¾ÿhw÷«/ºÃÜ}kÖàG rG®Üà¬åÓ÷_ríÕ°í8‰™ÉwÌbeç)ìÙ¤¢"ãÓ–ZAW;~à¨tþc JJ“ÑŽ”ëÝ3Ôõw]ÜÂýòPmád’=Ìk&GI™ŒhyÍk‹kR1$D苪|'‚«nmS«ˆ9ç¿Ò1µmoĆÂDeüGô­·‘ø`‰>Øž¹³û½ÚôÖ¹Û«chˆ9ÆûçÓí7•›=}Ìré“Åû̵§ek‚.Ox<Ïcõ)€8ÝéSÉ‹¾JÆÅùVNàŠ·Ý\ï••½àÛ%œ„lbê•ãò¦‚‹¹d@×qŠ" =¶ÊØ@Õ$ÑöÛ5)/£€Ìà÷ÜF25Ìa9…jöáÇqY#ŽÚCFV¾•txcXØAâÌpÍë BÞVUhƲ2.e]¦¤Ô³Ù·â«çf2ê‚’ ˜ #¡J Pè]_µ6¶²ô(væ„dzK€¼°9ÅîǺGUÇW8Ÿ'-Œ nVðUabzi`lq—oþj>³n³½¿&®Èü€7íëjG±¶%RAÙšÎd­ôeI“¸>›¨±•)H¡Ä@µÎz7@vfƒg©ë]X}¥É}ãæmϼO [ÀvYç$•ºÂUžÅO#Ò]‘= ¢¯#|‚ „ ª QnºëÖ¿;õëk>k‹rÒn tÊxæa"‡Ò(§Ùº˜vªó‘|öREüœ’Çq!"ñÓ×ˬ;”U㕎³“œXV8ô÷{=Õù©yuq{w-åۋÏ{ç\O”’JŠI$“Ä•-sÒê>㇖n ø4í«ö8ÊDSFM“øv*j%èEŠ(Ÿàmk©º×tozÓ ¨NkØêqšpæE=´oËV=<ŠÐ<4íÃèþU00…™ŠgrÇ/BÜR-ó¥A¿•¸® u‰ ×"+7zVã^;™–sÜ­–U3n8¨]³ö†‘ Öœ7&¸_›4-äÂòAZ‰K˜sà4FÀE[‰;rÝk¦ZǧÔr“$Œ<¸ŒJÑðî%ǹ“ö5ëÅg\ê÷º’6mÈwÇVIÂh¨¢F3Rm(‡Ëñk-µŒ:~ï† ‹ ñMLoŒ‚;m\Gl¼²q$š{O™LŒÛ!㚌Sp›¸íÉQ2¦{vÃ(ð´5ÜCWJÿ²TÌo`×FtºÆKÍë§±‚­ŽS#°­msªqj‚½äqà¤\¾¤«ü"¿ÿùOÐoò~óÛö{~Úíå A.#aµez„òç&Ý–Ã`^É_¥´î¹É'<2"Þ”aåëc_ÕEÉ©Cödt•Ì2Ú;›IëvçÜ•”ðè·bã“3€ “5ÔOnS\s4 8&8Nçá?ZØy]†²•çÏ~d‹ZÆž±,_.ü]t0A5"­þÕ×"ñA‘XËÉvšªUBÊ!¦£Ò§u#jî-W¬û[^Ó¬æ›F³ËΙ GIœã˜× ™VV8ÌÇá [ò“ˆ˜–6‡áüƒ,®Ô£D$‚w=¬éP àåÛ# ²Ú ˆõÄPX>böÕ*M›ÔN˜íž¥i~å­Ç’ú6žMËÂOqûL'ÚÞq]G ²DÉEǽU_¸ÉìΈI\¨Æbó²-«å¶¡rÂ/T”·@–V³®õÁ¤âŽÙ"ƒb±X»šíÓ  ¨npégKº…³zÃÎãd·zE½œ±Gx_–[ jâ^ÊÃÁL­«2¸ÆŠ)5]ˆ§Újj¨.5áµjú–rs,\v ÃŽ.ë~ñkm^Z¤Hi…ÞÜÖ¦i2p C™ËhÕÔ(m¤mt®`Ø[Gsi½~Ü–þÊx´¨'lS¸[Ë¥·- 5Æ¡Ž#¨±±âáÏ#ÂU¾×O©Kó§‰`¹uÆ>Frjü·øqtå¸l£~]ŠD®õrD´J,/›†f>U‚å™ñIIµ~A HŸË ë×Já}³gÔîŸo­Á¬Ùm[N×Q¼›!q hg¼Jö½§+ê;P%î!„‚J—M¹‘ÎFE9Yzo\ q­®åP)Ì  Ê•¦@1€>>êÙ±õS¬ E°çh=Ó‘ôB²ófü5Ý9ÇjäÌÛÁ[¦ÞÇó 仯 Ë8Ç‘ÂGòÑrƺ¬ùË‚§†+“ÛåIÁU>… î¯cÕý;_ݽ¹´±²•ÚýÔ66Ìñ=çA$‘× òèàNÉ4WÌøHÄi‚昇€xƒ!ð×ã¬Á‡á¬œ–âÍA9ë¦>Ü……É: %§›43ÇŽ’ ª‹“¬ƒ„‡b¥žltWkë+±Ð·F—¦àu LØ£Žî9CGs8Œ*×—5à k…OJáœQÇ9ë…¹]Î/¿8Û—±Â.•ÈÌa`[«_q’ʨ˜^A‘¸¤¢5X¬¡ß±Ôýƒ»@Q!¼M´çÒ}Èí½¬hêzu Õ--¢7±äûnJöby‘¸™#Ç!•™A²&¾'e-«{Âë>­¸g*f¼E‹¡1E?}JÄäe夨Àµ+…ÙGÙ•hWnuQ$.W!ýá¯Mñ1µ7íÛu¦Û³šòæ+â÷¶1RÖòžÚš‘…H ë¦9좦ªkcÞ0à U­›pGà|SxÂ1ƒFeŽ?µ˜ÎÅÏ4hÝC¼BE´i]·‘nð¢=Ò)¼€ëֶ·ÓÝ•§Ei{¦ÁªÂÈÜÛh[#$kA̘8;´×µell9E|Ê2z°ä.M³mN;`{ái•åØ5ɹ J…·kÚ“n€EHIwȪD‘uüD†Â˜KÔÉ Nv†¾ë´;ãpiVÛfÙÎøµ)Z.î@¤PÁœ ŽuAâ–•¤L-¡æQcŸ;€ƒ¹¬¤…Ÿlĵ†„ä÷%a6)ŒXû~ë‹„‰MuŽeªÒ1œga©\¹PÊjcjn¦0ê#ð,¾´½>Ù¶¶{‡_†ý˜ædlâHkYASSéēР¶P9ÞµÃí®(çrÂÉ¿0dVIÎøjý‹‡—Ë¥{+Ž ¾á{uÞiϱ 3­kãJÍÏ8Ó¸Ù{¹óU²Žîk´V·¢WWº@U2c¡Ð8WhôOk:Ú w=Û(éG* ° ^ñäs€kH¦ wc‚Äâ\ê•s¾/ÕþãÃû÷é­ü­YD¢%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢%B]q•L¹Êò²Ý %Z&<„ºIýÕ ™È´{äu½Œ‘@ÆEÂùUHâ×h‡ËÖ´k N“KÔ™žÖACÞcš{Óˆ=þDUÏceù8I³YwŒr¶eøÄçEÕ¯ ¡Š”™Ðî=´Ÿ/°“qÇ "‹@¿¼OfÕOǻӧš¾ÖÒHÓ6”O†v ;€W#¼þ}’q,s:3‚•ÙUŠ„!\(8o)ÄCOhõ.¿)º{+\>ÙÇ9—cí-§úø„ý‚?XkñšÖ>C–oye*´é̪Ф:M *(m@ ŸÎ ;uúJ¯öû¾ÊÌËgV¥`’ìRQl÷Má›®¢Ù ŠMI,¿†—»[-‹=#*dVP€™œÅ—lÀ“tû­Û(]ÎLPn®çØ]+¿Öåeþ°ÇÛè ƒGU²L8Ñ€Šµ‡µæ•Åxˆ¼Ô«€ãæÁ¶;+r0‚´‚„òk˜Ê¼‘\EgŽÝ¸PLªîºPêç1Œq®··†Ö[[42ÚÖŒk@ ¬]ê³"Qˆ”D¢%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢(ñšxÇŠ³”r­o yšÏC¡"DJWMÖ!b²Jiˆ¢'˜¢¨kí«$’°Ç a ŠƒçÜ|ÌöÂçc—Ý?ŠM=­a¯V n„‘({ ûnL4 §Âµî©ÒÍ›©HÛnDǶ'»‹?¹N–ù”²‚‚³8ÁªC¢bè–ÔÚ‡(h*J]ÆDGAë©LPpé^xtGl‡n/H¯ ÑŸ•UL{×Tµ};.{…TÕÌùJf~;rgZÙˆðÖü€(“Ö0Fùš?/Òìîté ûëØh½=Úz„¶Ö‘¾äSÇ%dp=íÎ\ý¨rª¬sâKµƒ³ XÄ´j‰(·A2(b&P)@Ç)@DôWµAÁKª¢Qˆ”D¢%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢%(‰DJ"Qˆ”D¢/ÿÙspring-security-2.0.7.RELEASE/docs/reference/resources/images/xdev-spring_logo.jpg0000644000000000000000000011100011766764657025013 0ustar ÿØÿàJFIFHHÿáñExifMM*bj(1r2‡i¤ÐHHAdobe Photoshop CS Windows2006:08:05 08:34:10 ÿÿ   I&(.»HHÿØÿàJFIFHHÿí Adobe_CMÿîAdobed€ÿÛ„            ÿÀ "ÿÝ ÿÄ?   3!1AQa"q2‘¡±B#$RÁb34r‚ÑC%’Sðáñcs5¢²ƒ&D“TdE£t6ÒUâeò³„ÃÓuãóF'”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷5!1AQaq"2‘¡±B#ÁRÑð3$bár‚’CScs4ñ%¢²ƒ&5ÂÒD“T£dEU6teâò³„ÃÓuãóF”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö'7GWgw‡—§·ÇÿÚ ?•6²»ç¸5§ÚâLh}²¯ØÓt#Ss–}wZÏHTç‚Û½]ØÙ,ÇÈfÖÕúKqr¿Uê8ïc2=)»íUÝëøùUŒz,}´œ?ÖÎFvç0–Ug§“‰ŠçŸçw±õÐÿ´}¡žž5?§ý2ÍŽb;ô+i°Çµ­qy4'MYïoùÌõkȪ×Ù]62ïM­.²§o`q×Òõa¬uµþ§¿bͲ÷ÛS«}UÔß°¶ë@¾Ág¬ìWØüm­{jô~Ù³Ìk?Ifû)³}vìVmÏ5 œÑ@ªšqìam’Kí47({Ýé6†2Ì—ú{=jŸêzž—è8%[‹¢©…­Û}¬ì㹿{ÿïÈ6–¹ƒÜ$翇(™¹¹¢j–Ýs>ÐÐòÃUgn7ªç¾›3œß^ì¿Gô^uzáP:…ù;j§Û̓ ¶¿uüÆäcß‹?ÎÙS±Ùê[½õ~‹Òôl®«öjR—¾ÿ÷ª¥«qe€ù­;›êã9úCâ^U­eùæªéôqæÐ=gØû굌È,õ1ÛsYüãêÌÄ£«Y‘•e¿á/Ñß]˜íôIÊʨ\붸ãÔÖ?êË]èz™žædYú½Œ¯ù›SgÊä$c¡®»ÿŠªi¿Vwº¹ðQo¡§e_k»—Õ‹[‰c­7ÙVElõ¯ªÿÐaz9gûUv?Ôõªý ~Š…9XÖRX t[aÉǧԷééº^]¶ÔñöFÖÜŒ<Ë©ý[׫×ÿ¤† ÷ŽºUI,ë¸Ñ —챤éªzòñ­£í ,£ÕäÛesƒêØû2¦Qe›ŸfnÚ/Ûo­ö¯¶}—Ñû"bé³&¢%_³žì‡Õc­°ºÜZ쾆Ðûj¢ïK;{1èõ=_´Uÿm8`•Ñ"Ž–Š{ª™²,ÃyÐþ–¯ú›[ÿRõÑ/;é½BÊ3>ÒÏOeO¦º\_4=GÛaß¿&¯§éÑè3è3Ó^„ǶÆ5ì;šðÒ;ƒ¨SòÒ4qñŸù©nÌ’I%ar’I$”¤’I%?ÿПdôÛö¯KËÕÛòÛê+˜¬¤_Còli$Yöìô jßµz>Ñvýþ—Ó±y*K&¥ól~_û¯ê¬®ŸÙa¤³–zžâvmõ'óçü/õ½è•~ʆ†ú¦+5ìßêOèO§úOµ} žŸé÷¯I/µ/ªdQÓë|Ñ‘ëZn÷6±Xhº-ßö¿±×[>׳í>—Û?Mý/Ñÿ•_dÜÿKÒ˜ý>ͼ÷õ¶ÿßו¤›ÒÿæA}6ßÙþ‹#Ðôw~Ž6lÝüÌÞ‹€zW¿pÅÏ'ÒñüéþRòÔ”SùNê}g'öVÇëᇲ#ó=_í} ꛽oæí<ÄlüîÁ¯2I,_U>Ÿú¿Ú™»ÓõÁnÛ¿þµ»Ýþb¯zvÝ7öÙ·þ•^p’—ªŸWèæFÏ@W½Æ½¿Kù~ŸýùwÿWz]m¹¤5³è¼Çº³«ï{~Šù¥%')üô·ê¨üßGꤗʩ-ïÕI/•RIOÕI/•RIOÿÙÿí ¼Photoshop 3.08BIM8BIM%F ò‰&¸VÚ°œ¡°§w8BIMíHH8BIM&?€8BIM x8BIM8BIMó 8BIM 8BIM' 8BIMõH/fflff/ff¡™š2Z5-8BIMøpÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿè8BIM@@8BIM8BIMUI xdev-spring_logo InullboundsObjcRct1Top longLeftlongBtomlongIRghtlong slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlongIRghtlong urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM( ?ð8BIM8BIM8BIM × à)@»ÿØÿàJFIFHHÿí Adobe_CMÿîAdobed€ÿÛ„            ÿÀ "ÿÝ ÿÄ?   3!1AQa"q2‘¡±B#$RÁb34r‚ÑC%’Sðáñcs5¢²ƒ&D“TdE£t6ÒUâeò³„ÃÓuãóF'”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷5!1AQaq"2‘¡±B#ÁRÑð3$bár‚’CScs4ñ%¢²ƒ&5ÂÒD“T£dEU6teâò³„ÃÓuãóF”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö'7GWgw‡—§·ÇÿÚ ?•6²»ç¸5§ÚâLh}²¯ØÓt#Ss–}wZÏHTç‚Û½]ØÙ,ÇÈfÖÕúKqr¿Uê8ïc2=)»íUÝëøùUŒz,}´œ?ÖÎFvç0–Ug§“‰ŠçŸçw±õÐÿ´}¡žž5?§ý2ÍŽb;ô+i°Çµ­qy4'MYïoùÌõkȪ×Ù]62ïM­.²§o`q×Òõa¬uµþ§¿bͲ÷ÛS«}UÔß°¶ë@¾Ág¬ìWØüm­{jô~Ù³Ìk?Ifû)³}vìVmÏ5 œÑ@ªšqìam’Kí47({Ýé6†2Ì—ú{=jŸêzž—è8%[‹¢©…­Û}¬ì㹿{ÿïÈ6–¹ƒÜ$翇(™¹¹¢j–Ýs>ÐÐòÃUgn7ªç¾›3œß^ì¿Gô^uzáP:…ù;j§Û̓ ¶¿uüÆäcß‹?ÎÙS±Ùê[½õ~‹Òôl®«öjR—¾ÿ÷ª¥«qe€ù­;›êã9úCâ^U­eùæªéôqæÐ=gØû굌È,õ1ÛsYüãêÌÄ£«Y‘•e¿á/Ñß]˜íôIÊʨ\붸ãÔÖ?êË]èz™žædYú½Œ¯ù›SgÊä$c¡®»ÿŠªi¿Vwº¹ðQo¡§e_k»—Õ‹[‰c­7ÙVElõ¯ªÿÐaz9gûUv?Ôõªý ~Š…9XÖRX t[aÉǧԷééº^]¶ÔñöFÖÜŒ<Ë©ý[׫×ÿ¤† ÷ŽºUI,ë¸Ñ —챤éªzòñ­£í ,£ÕäÛesƒêØû2¦Qe›ŸfnÚ/Ûo­ö¯¶}—Ñû"bé³&¢%_³žì‡Õc­°ºÜZ쾆Ðûj¢ïK;{1èõ=_´Uÿm8`•Ñ"Ž–Š{ª™²,ÃyÐþ–¯ú›[ÿRõÑ/;é½BÊ3>ÒÏOeO¦º\_4=GÛaß¿&¯§éÑè3è3Ó^„ǶÆ5ì;šðÒ;ƒ¨SòÒ4qñŸù©nÌ’I%ar’I$”¤’I%?ÿПdôÛö¯KËÕÛòÛê+˜¬¤_Còli$Yöìô jßµz>Ñvýþ—Ó±y*K&¥ól~_û¯ê¬®ŸÙa¤³–zžâvmõ'óçü/õ½è•~ʆ†ú¦+5ìßêOèO§úOµ} žŸé÷¯I/µ/ªdQÓë|Ñ‘ëZn÷6±Xhº-ßö¿±×[>׳í>—Û?Mý/Ñÿ•_dÜÿKÒ˜ý>ͼ÷õ¶ÿßו¤›ÒÿæA}6ßÙþ‹#Ðôw~Ž6lÝüÌÞ‹€zW¿pÅÏ'ÒñüéþRòÔ”SùNê}g'öVÇëᇲ#ó=_í} ꛽oæí<ÄlüîÁ¯2I,_U>Ÿú¿Ú™»ÓõÁnÛ¿þµ»Ýþb¯zvÝ7öÙ·þ•^p’—ªŸWèæFÏ@W½Æ½¿Kù~ŸýùwÿWz]m¹¤5³è¼Çº³«ï{~Šù¥%')üô·ê¨üßGꤗʩ-ïÕI/•RIOÕI/•RIOÿÙ8BIM!SAdobe PhotoshopAdobe Photoshop CS8BIMÿá-http://ns.adobe.com/xap/1.0/ 4294967295 524 73 1 72/1 72/1 2 2006-08-05T08:34:10Z 2006-08-05T08:34:10Z 2006-08-05T08:34:10Z Adobe Photoshop CS Windows uuid:3f50d993-23b7-11db-9576-fa409a7502c7 adobe:docid:photoshop:3f50d992-23b7-11db-9576-fa409a7502c7 adobe:docid:photoshop:86772fa8-2454-11db-8c34-c59e0b1bd60f image/jpeg ÿîAdobed@ÿÛ„ÿÀI ÿÝBÿÄÌ     !1 AQ"aq2#3‘±B²s$4r³t´5u6 ðÁRÂ%v‚¡bĵÅ&¶7 !1A"Qaq2ð‘¡±ÁÑB#3árRb‚4’Cs³$Dñ²ÒSc5u6ÿÚ ?Ö1(@%+¶Ÿ¼ Zw =ß.¾WK¨TוjLæ%®Á{*QN†LGxm:cÓ¡È;ˆ5èÊ%ðÓp¼Õ¤€²šµ˜õS]DÄJ'¹ÉI3)¶ ‘U²žtT â'Ò+%Ò¢@7NšÛ#~¸cx8·íOg9`Ü1¥p;w̾íxªfù¦§žd)q³”Œ©€@=º3AÖ@Ì%ë-T¯l€9va8ºdf©ÍªáB<ª‹"e†¡E#¨  ”¨Ô½zi—Ó‚EH**õxY(Ç*Wë£ÆÊ¦dªIïE`1j)€ˆî …6ô ޤÅ)©#›%‚¢­Ñ¸ÌmÈŠ’‘§‘lC©ûì†R5}Çð2ñëí TB´ë¨Ïâ72m]Ù8j:ŽCF ´ä«¿#Ù¤•ÚÊænËq.øN—r%HÆAôi’h âŠèF€= mH„rÛê:šíTíÕ\¾!1;p$¥lK JYˆ–4SMTU!’%µo §éðˆ&`ñÓwlÕ 5Ȧ u8­´ÂDÍä~.ê‚ mKö`ñ1 ;F€+@÷ë\1è“*’FœÖ²1P#–ˆ8I@0ì&QqDjÒPÝ}š\ÏÓ¦¹!´¡Ç-ÚâFH£âC”D‹q*b4éÔwß>Ò4‚ 5¯žžlB«#";Èa"?µˆ¦=MðuîR¿¦Û<ƒI®£A€Q€¾jOt6òŠhQ XA¡öípßOv­u`Ò×%j*åôC˜ÇnÝG ê¸&í &P;=J'ªÕ ôk8¬º€ -ÌB¥FY_ú@–Ó«^Ú°wT)JQ% ZTGyëÜ’â1<}‰Lè…û˜w¢E”+q+Ú pî–¥8´¨j)88Ë™MHh[CŠR=¢œƒ‚Ä…EÒû—Ð7’§@*P1;eд¥zjâÝÅá¬2b{Öcy'‚ùP©‘är$†.ÅPQNئÜ|ð‰LWClúU?´zuÓ€—±Ît”¡¥qÁ,¸—SN 9#¤Pvóîƒe[9/mØ üÃîÔyjøÌ^¥J´ãRx €îSÅ;1“¢µL!A‡l yHõDˆþގŠ„)€¢aï 5K£v—ú••¶á®²8H;0?N#¸­nKsïO(8w– Ý[oÛ'e#ad =A7"Š¥\© ;þ>Ÿ8ëF¸alÀ¸ù¹OØŒ*âÖÕÁwkÓW0’jÝžÅrK˜]Å”·,ªqûE{ %ÐDNn›ë…­EE@ë¯PÿÛwT9öÛÇH]Ëù‘8Ï'!²´w¡àí<ö­·§nõÇ%³Ž\ÃãŸ×ã™]NשÖÌF„#B¡ЄhB4!F„#B¡ЄhB4!±fÑÊ­VpÝ•b°¹h¢©”çl¹‘Q¸¬ˆ˜STPXäܦÖRKâÒæƒCQÜrYzÂR4!F„#B¡ ÿÐÔµÚš¢P¡ÐåøŒNŸœ0í§¾•×Ê÷ó4Õiìå~­¢„Þ a¨t5B´üÚGéj$g025… ŒÓk Ω2-ˆ±JtVOµÜKqEL. €›h,‡@üñökeÛä×¢n¢À™J¡L1vÔJ P¨SSÂ…ÔûWµÍ2†£†šä‹ÍñÎâX‡Ç ¹´®løÆ Ê4| 4Ú*T‰n)PüšœMün¥ Œ"¾¡&a©¤—*܉dJížç‰™nÚ‚’€P¤ È`í€PÁáÓ¦²C\ÒQ™ê6€ŒátݺŒv©&ÐAÀ c*rCJAÚ™ú~ k7-Ó+Fš|¾Õ*¸EE)߯Ür((„¢{Q)…3PŸR=:×®™x[âŒ0R¢¦ðÉÈmpQí¾`vŠ )†Ú¦ ‡@ ?¹`”êjÉ/î(ùúyüÊ`S¨O*L>¤Â@ÙZ&n… Óâ¨uԨݦ  ¦ÍáSP—+²”+ù-¯S*„E4~ÑN “¶c&@($jQ*€Ð®­¡{KF++$dAœuUê%hC7$ ™PLÂqGã)F¢5Ó„´“†4BÙ6FX²‹&Wɦ° ™Ž°¤P¢& ¤ ¦m§uð bŒ 8#ëN#øu´Zº¥Ä·} XTÖdJªrù ‚6(S&³iz ~%0{½ºŸ£Ð?/”žÕ•nðÑ~ò^\V§g·ñ‹ƒð6Á7ÚTÞ4öiÇh2¹®¦ª}‹£522Å”F¯óiµ÷…4þÈš@GÜ:3chu!)óWæîÕ‰Dî Ú#ƒœÄÙEtÔ)OAúÂ`÷ê.¶ Ù¤pÍ+ÓP¼æÙIyÖCæ’ï,ŠÛOÛ&Ð!B‡/j†0FB”Ò%lnl‡NJ;ÚçD–—+yÒ’v’täîH)õ\C`¨tÌè ‡@¥4í¬Íl‘`j@L‚| ­ ÚÍR<âbá8+C Ý U>°ІÀ Ö½ujÓ2 ®ÏÅHh-šÍ´©Æ}°a®¾X–ÓÁj>R½=™N^”0©zÔ(a÷j :œÔNÓ —nH©qG9HÀPQO,c€J©Šbw‰®@>jêÖÆAÙZé B•É\· hÏ4 ™8ˆ!(­VO½pS‰‘w½"DhˆÓÙ«Ðã¤ùNIzBÌ|Ì{è‘TÂ+À¾B¦ïªÚGrÑ«ŠÅ1Á‹äIR”(5ŸQ\Þz Ö]SCصÒÍÛ»NÙºˆPMÉ—<ÀE*$]'…ò(»N%:‡jä…˜âÜ!¤,e B’‘PÖ+¥×gNLê<âó´B”Š‹¡4MÀÙtTÜ‘Û8Xª‡Cxt®¤W‰8,O6!G`—qdÖÚeÆ9Q¡Ê—ÐMý¶ªj¢ª` a2r& uW¨iñirH¥qÉ4\?F'Ûw˜ Æuˆ4I4ÐIÃE¶?D†17ª‘ŒºcáÓ­4ÌLoï$`rQ ¸dT†õqf¯“,NnîolÅΞ`·T³GŒÑ›R·‹,ŠpF~ª,P–š+t¹7d¼‘1Œb‘5"o÷7Û6͹_íö^µð l- –ë{šÝO æsbf©\ÖâàÍ8HÙºc§§ê=Þ;&ÈÈ­]4¯pdQF3|’ £8—9­hsˆiµ—_3øWìt£³Ìãh»ŒH#pεr^^¹dö¦ƒ³kÛ²OÕ %йL¼”ÛÆíR ˜Çp ]yêÃÛÿp½ÊÝ„±½Ï$›»ÆË ´Lâö‰Ah9G ­04èóì;’A¶ÞÅ%¼x¡Œ*N ;!©๑Ç\‘³ázå<˜Í(ùL¹-;s£ ØP)5‘U[nÝEeª=þ€#Xðvb$w‚ØW2i™A!}/ºtÞÕÑû^ÏÓ;4ºíìíÚÍG7¸ É!5¼¹újCk¤W*ÝnŸ{w5ËÇæ<ðáÀsçÛ°q“Á-Hr¶Ê*w ¹DÍÝ*ŒGpªíKƒÆ8ªÒ ™ŽmrÚYÙ:j ³6û™ÃríPï Rî8®ÜCéPugp÷ÆØfhò<§§ ƒBš¯c²ÚšàA@AÁ@ÜE©²…øÄáU: çÔó¬”籧ÂpÅÄSÄ@l³‚6®ðØ•Þ5èRƒQé×Zîílš»S°;Pv-Tš1è¹h`I`1ÁÇÛŽnÐL—^¥V´«Ù¤°ƒJ§)@¾jv'IÑŠ ˆlÀt(˜€˜Æ¡„(nÑœ9KP8-<ãF*"Ìæ"¦1D€ê½ã „TÄ ˆˆœ< MIa à›pâ–-bËÓ KöÀ¨ƒq0"S‚fß»ãÜPè¿&¦Û½àÓY&”Áh Hß.ÈŠà±—D®L®Ó¦qT 0L% ^ƒ©à¸ز¾Š1&Tšþ[´M„¸Þ ÇqŒ÷‰´ñé](j§b§V“¦-ÊÔDóFXCUÙ´ªž€CnnSÀ+ª=ê$.¦I@àB·V»ÖŠ˜†K»ÚìÓj„Wx©»iD@j¦Ñ/zë”_BÖI pÃâ©€ŸdÉèïÞ"Qø€¥.êà”ÛZüº¬n–´€ k÷,â!F/ÆRÑ®™‹¢©‡¡Š`T©˜@Hs J(4\XÜ6 ¸ekˆM–*TD™5y"‰ÒXŠ ¡‘@´T½±M3·„($Pj;«Ó¯†»”À²" AÅa¹© `dXÔ«@Q0t?Z;‰OŒ@@B£¸½(Õ>âÍ7&Í&\ÁQiT¢{®Œt–2e!\n ìS¸`=j#ׯ³OYºLMSE@ÑÉ¡A5Aqp¸=VØtŒuk°DåLL5 Pk­ºÒWâÂyhœΆs.¦"ænt R’‹ …Aˆî(Š^i©ñÉ!`þeVn_nÑbf;U¾!PLa©|LO²ü==ú—Î]^ëYP·iÅMDźàÕDŠm…+‚˜]‘A8˜TŠBZÓðê4Áæ<)ª¨ <âß|ÅN &¯|Žh‰è¶ÎÀ¬@ÚsÂ@J½­uÒÒâkÈR@¦%M¥‹$¢kƒs *†àTDLp!‰Sר˜@iMt±Ö£W‚@©à”ÓM#E³åÁ%ûäYTÛÐUØDɰü[7j'¨ÓÇQ´>'†áB7ߨ¨Ã þ=¸¤¸6tš©¿(ƒ€}ANÜèŽ&‘a¯Â Q÷jâÞYe„¼š9§ ¾*S|£Áb¤% !œ­¾?¢â%9HqèÃJ,PúUøGO’þV’(áB²pÓ ¥q¡Š1‘T”H€ø£Þ›¾*u8”E%ÀÔÛJ€êŽý“ŒÌ?ŸÚ| Bi툴‚ʵãl¬Y& ³PÜ‹Ù}À®åPU#(ÕÁŠc ¶¨j«½¬îeÌ z37XîpóA …Í™Ä|ªŸ±ë$hø§ãÜ2íΛ†(œDHS θ ¼:ôÕ4Ì4|y57íJn çö¯Ñ·²¹26g éqV^ÃX°Š ƒõªÃªZQ”)Ul§ÂFä¯Ò {oØN©;ïG ¢ê][†Úá9˜]Sÿ ðÆÞÕ¼ì×[Q5tx|8ê+¯®ä­Ñ¡ЄhB4!F„#B¡ЄhB4!F„#B¡ЄhB4!F„/ÿÒÑ¢JOZ…DCâê_ B†—䮾Y:¤­Iâ˜ðO‹ZO°ÆJå{Ê(à¾,âI†µÁ}µ·Ü]÷ï~IyǘÒÐh»SJÜ‚M°,åeÑ‘ÊÑEÑêísúžÚã{ݯM¶Ç ôê’GàtFÚZWr4u'ZÀeg¨M#={’gçïIìís0Ç–Ö{æ/né×e´òÇ'ml17ƒ˜T8ƒÝêc™ù{ Œ„JE»x¼s,pô©&u©Áío@ÞRÖÒöúÞìà/¢öW† ÀÒÚŸï;pR…­³Žç4÷Ñ^îTc‰>d¬uÇÛ§ø¶RùÂ6ÎFkw"Ý!Ö½K=3uÇÀ“°ÝÙb£æb £0P °2~ÜTPÊo)u¾¾öá½(Û7ÛLéaôš\â›ð2¨V¦‡Qq‰€Wëïfh,G )ÔŠ†Ãœ[ƒÆä#¶â‰À¥/›I D@vœ( q‹XY#FËíðPõi5QÓ³Øé†J¤"( ¢s äˆ9W¶ô¥L¢tÙ½HèÝí cÔÔFŽ ²à2Z —i5º­{”Šm¤‰÷À±ÊMÁ·,xI¨™êaÔ¦ú%§´tP }3™XmE pZUÚ¨ÂfI°¬&zÅЬW”þ§§”US@éHC¸Ø˜4‡02V‚qX¡¯½&!›ã¸;žâ^D ñõß…Ø¥¾}ýü(Þ]OW‰EA¡ä€E@ðàP6­¶(n·]½×•ý™•¡ô<Új5S¾•§zz&ê8Š®œÃ½8—È>O@CðrNø¹ð‡ð%¼k©õΖDB1¾ERJh’Ão%“Á½â-Á.Ô§ó ù6ÎŽëîý¨.¨©Þº»gé–fîÝ9‘膊—87·Fº¹º¨ ÿ´@­CE6Îví‘mP=¬°Öæ´úÇKå>i -Q"0] ÷—Lí®ØvôòOUŽ]tÑœErT‘]M®I²•(•R Cå×½êýÂ@ø‹Ü#Ékây+B®È@ÇY %ÑFÂÍG½Eb„SîÙ`Lª C( ”z @=úÑw)ß4Úåyq4úQ15qL‡i€ ×iAMë¹h¨” ÛѤ= ð ×ߨq;œ])Ÿ7ó($ …J±*ç(3IÊñÎwTí* ™"ˆÂpÜ4üzØcdsFæã«I§Á80 ÝLÂd †öÌ&eHÍ2 ¿"±…ÂBjRX´ÚZk1Ým„T¡ñ(oŒ6J…›l8tSK$o,)¨²âàH'ÜQ¨ xiJJõñÔmÁìiä• h¦KêÈÓJFËçdpǨÆÈ˜½´æôMà µ: ï%ÚB¨Ü *T!„@(!Ôu7¢ö£rÝE¾ôéÅèè׫ yùixö)‘5²>®žïâ¬÷8c½>}>‘À®2ÖUç ÜÛ“–,žAǧÅÖf —-ضÖÊÊ}þápX®#Ÿ.Þìjd“HŽƒá8Ä€Ò·þËtFÝKu¸º7¶ ·ÑÀ`q«[ÛÞ§›(]‚Lqÿ;úJr"ÙØµÏ#9„&névV”Æs±pí½hÊNÉ(“h¸§7-™-~G@šAÊ¥I5ä…‹@P@§X»‹X»µ^ß_L ŽÿpcÉ Õè_µÔøÑ YÛ¹ÔÔêü_"³œÅü‘ä¦ÎUåñ5ÿ5j‘Óú¦âbÜ@ÂöÏŸÓ#Ü6›ÖoÄ RyŠMqnºè÷ôžéuhÒ]C\s-­ZOy%Aš œAFÔ„e"VEKï*¯tê –:{á¢a ¦µÈsNy&òA .’g’XÉ•—˜‰”Õ:∓p‰D´¢¢mÞ5é§E8Ö•Y¯í éâQ¬Î"ÌIÉ{fÞ¯xOæ”)„ÄÛôwΦ.â2PAÉ[K:MꎒÝå{¦hN¥î eLU k¼T2ƒ×À)×\¯u·|3jhÅ:Ê´Å8Z¨s6Wì¶Š‚" >ðèZÔD7ÓÇÙ­]õæìªQÉz>Ed··p ju0Ñ>âœ7GÛá§ÛêÂÔ2C <¦ª¤dX‡‘$ˆB7‘H®¸ËƒÙ8Ÿ²¿:î tþž¼ýų«©¦‰°Nª¡MW«µ‰­vèƒsnPO°2«@ o/Qެ·P55íËŠÄ™-l‰$»²f!YÅ$ûå1–ÊPHûE›ª%¢>ÝF²{A婊ÒFiRðÏÈÖ4Jf}:€"eJ¦ñYPTMRv÷k·¯…5¶Ú—:µ­ë—zÁ¼‘ 3ň8¤2 &[´$*€wt0OÅ«6ˆ„b€Ò§çJÕCÞ¤gYÉâR9…¯•:€%8˜ýãÌz€À )P¯QÔÀ1®5X ¨*5,I•*¤謄B‡\È¿@ÿ‹¸&§ÉM4š+§WÒ²I%j™¬ð¬](&j ÎèÀ©JuEBª ¦*`")DÔññ ûµ´G µ¢ÅGÁ4EWë¤ÄÆ3rܪ S`¤¡JPûCh)¦€¬~šå‚*;Ô&Mgg2+NŠ9:ýV‡¸€t¯B¼zé©ÊÆìp L9ƒC€K9Ä¥¼Ä)ÄŠè•r6À6ùBˆ™z]‰…•ë©VŽk ­ â£0¼8Ÿ ¸%å##î 4ÓcC¢¡žÔË V¦*Än"b¯Ä=5kk%š(Nx|êS œjF íd˜¾IzRfNdqÆ?>Î^Ø‘ïÿgõ m‰ù÷’x¹ýĵ³dã+¾zÓRØ”¶2kTJ¤¢ïŸÊJ‰ )~ú}½é;Ž”¼¾Ûà¸}É k”€áBÒhÆ;E4æÔGhVæÎÜÛ0]§î%® ºÝ\pñóê¡~úŽhÆSã8‹ùq351ºŠ w…z¼™{ìï·  Ö±<É…hñóPñ-^þ7khÄà~Ï—‚¸’˨ܱʸ‘ïì¨ÔÆ“c(«P9@L˜›zuê¶à#AÔÃ_𜠄ÒhÑLB8—OŽótl«’! w–Ô©AQȸxªI±t`PÀT¼¼‚H˜êSáD õthz©Ý+×{w­%6Ëïøy;½B48ð%ÑSÁ…ØUu³\: ‘ Œà~8ˆqùª¿Bºú·DhB4!F„#B¡ЄhB4!F„#B¡ЄhB4!F„#B¡ ÿÓЧC´T¥ú}£‚ #³¦ïwˆP}ºùk(trãÚµR ÈàŸ¸6pƒ7ñW)zazƒ_ï¸ýpå‚e¬Ÿ”rœU­ v«plÚḶun[n`¤¹O6fÑRqRk6ó,Ý$‚Çö'´ÛÆÑÒc§o&È\Ç`<ß@ ×<4À«›9#1«G,œ‡þž<ºðòœmȸ?–vÆ‹Œí¯=g\3mÊB™4#Ù9ËÆà»“¹D jÐéÏÛ>§‚øî.íÄ5¨i%ŽøV¬?é‰-f\NP,ƒ—yC5Å~3òkOÙÿ¡/»>߸¯–ó¹ñÆ7„äoÍúI°—·lVÙXÀH3Qt°W¢ŠuPÍõ>á{qµ[lûÕ¡Žò&‘WR )Ü@¦TJçÈÀǶ„.ÞDÁðž[Y«”×%/ëÕÄùÆû2Ög´„³ÔJźeáñþ'±\2W”åÁZÇD ³ã(îMpL²d:¦{nö³¤7-ŽK«yç2ú€z²4Bí1´j 9œqì¢SlíÝ)5®ÁWŒÍÏI¬ù˜-œ ò—xôù=òv Éëöäµc#^)Ñ€Bâµ`“·ìø©é•»l\¹fý$U |d2«"ýŸ·ÞÜÎãµþÎàLì®jÕÔr rå=ë"ÖØ öÕh³Ëx¾$òçã/(¯ø»VÓMµñ’lKMœíÇvc¹¸¹S[S¶í¯/5 ЯŸÎEsÔŽøSfé`C¸*$îó}×Û6ž¤†Ïp¹md×Ô ¸¶‡M\uQ®©åÄŠÓ_jÖ¸5Ç—ìNþk/éïÅK ‡\˜¼óacŒ³æ a“íÜ_ Õ„ÿ&óûÉûz͸­…IíxÜqŠíK~׸€· ŠÊ ]­áÀŠÄé>ÑtlPíwm7ÓÓÔáPe”šÔžHÀÕ¤q ©Å<ë8(ÃCO¤ª›œyèÞ¼¶#y²§(-¬o‘q¥Õ/™¬HlzµÛxÚdl͘ÞÓ·e|ÉCAÆNKÅ»¸NõÌt…ÃA™ÑL\W~Ýt;ç³’ÂKˆ"Òu5¤9ÚªÚbó<Õ¡pÀPgU›hyCjó#àŽ ó=N;áh vÐŒð–>¿œŒÔºóÓR²ró{9Ž–MΆ!Å&é Ý3öÓ 5EîGLA¶> Kñié7Ìââ]R $öá€vÅÔT!­<ÃuÃ{ςٔ–W!.Û/ fxŒY{æn@Æ)jÀÙÍÒ6>™ºYZxÞÃsqË^²Vö@fÒ<\¸w%2±!š—rác·{QÒŸOÉue<Æà¼VP¤ %Úca Õ¦ƒSœkÄf–ËXLEÍ&½§îU«sÇÒã0å qǵ­>b¨Ë*O[ø–‘×½¯n4ºze¬%» îÃ…,ÆÕ—™x‘rí9 Y3;D¥*Ê&å§·>ÜÈöm³Y\¾áܾ³¤ÚŽ  W*‡SžByh|Tþü¸_`.@g^6Ü— gä± øö¨Ìˆ"ÙYhy‹bý³¤5IE‘BEͧr3;”Šc Ê5Âúó ÝÓ;ܶ6Î×pÒêP–+´ ü•tÖú@8‘Î<€==1Ö”ÎVuýž¹Ș‡W½·†m›å|WeØ{°2²wUÉ7rÉ΋ÙT‘"Hp»uÉõ$n :ì»7¶Á´X]o¶ïºÝ'Œ9ÌÖcŽ EhKAsœ+Cˆƒ€¥]5–ñ66Šš(´ !ˬçð͉ ÅnÄOތͲ«HG Oìö»¸÷,þ¹$²]ƒM- hsXÁMOÜ4à9±D~Ö2U!Ëþx+”—Ïy9™³NN–m’oËZj÷Å-eÒãŸcpÊ4·,i«¢5áò–Eº &›9¹–1΢I´Y$Ü»+¶¾Øt&Ûw<[“e—SJ8¶8ÛS¥µ[ˆ+ÀâRE­³ZâM~…áv>ÅÁä'ØZ¹‚æ·¸{Ç<‘–¥²ÌÃͲ¶ ´f– V‘Ò­4gpÌ[ÍÅÊ®Þ4E»DQU[A#Cj^×m›¯PÞEÓ™±@òêP°VŽˆüDPPšVM2ÍŽ•ÚOå¡ÂüîôêÊ9†ÍÅ3œGÏÖV1ÈÔ%›ÚrmÌÞMµÿ‰¦ÙÀE_7ˆ6\|ðˆ¸x^³h™üª&0"/N˜}šÛ¤:IÛ¶Í²ÈÆ¼†‡úäÈ+€qC+Ú)AßÅÆÃlN’Ã~?r´¹ú.+…ļxÇ~ßòó6…ªµ™p!}°‹lîê.5»Ðc+çT·¼ìs×D k‡‹b®Ù®ZÊdXœ'ÜOiìöŽ¥·´}ÓÆÎùYW†‚ñˆÔCjÖ¹í «Cˆ€pjKqµåW—+K/ƒØšOy”1Ö#¿ò=Û#;w[Å’ÍMÅ«#~ÙËãLUŠmå\[³’]åtä$,Ú:5pícÛ ÒböÛ‹ŽœÛ7k›¶Äç—I+ô™dhÔÝ Œ~S*áP㨙9)bÚ-p%Bøq•ø-êQvß|yãý«É¬ ±µÅñÅó”î8+’×¼š@ÈÂÅ(K­Œ3‰ñ<ìûUhŲE}ó¤èTH‰)&ÓÙl:ŽÖçlÚ,nmwFKe3zšˆ çn-ÌŠ††áZR¿m šX*/½yáé+Ž0´nÿó-͉5 ³~Çb¨×ÀäZ˯Šc¤å .kåœ(   æAd£äÊ%Y…%J ¯aöÇÛž˜•¶WL¹½¾p£ä/ôãÿ€‡v¸šç‘ hAoœå%æÎ;±ø‹Èkǰ·f¬Cjç|\úæ:Äö­ÔþaˆBʪF̈ôÌ•ˆÛ¸PZ¹M%@Ë$¢Šj^ë{wi°9³m:e+C›«Ú’ IãLÁ¦F‡I‹ynBܨ¦ÙFÑÜRâ…Ë~QÁæ ­!ž]¹CPâŸ6yn?eìi™í¿üÑ={ÌàWvŽKZe+&߆Ÿ¼R°o¥Ð´cœÎ‹+Noÿ$*-H£–áÝf‚k ˆÁغ3¦n·K›Ëó9Æ:Hy@©Ðp¨?b1HŽÚ¼µÍ4áŽJ½çžCâLeÎlƒˆq›0'peïza»¯¾Î½ìƒ“îÈ‚ì·ànø+ñ–7t•¢Îâ#ÈWíb‘™"©7éÊðFëÑÛ¦÷ QíŽý˜%¦?PêyæÁÚNœÛËCå¥qÀ}¼QÉMOeU†ä9°5ÓΛKÓ‡‚øß(†rBþ´²Eñ2ª7U© sÿ +5‘læÐVò†R?¤g NÍؘŠÂ¼I‡!J±äïÞÝì—ÛvËdæ]º@÷?PCM2neÕ®QbKH‰ÆÞzñ+Ó”¼•àÏ óŒï#ñ&[æž@Åï mg|­ÿšá;f&òn‚&ž´±Í¯kZ—Jª+n®°·r¬£Ç>^EPúò€¨R^‡èýM•Í“îæhç‘ÒÅx†5 Ðïc†)_µ‚1¤°¸ö“O™L9¬ _Œxüi»¯+§‹¢A[^NÜÈn"–É8S( ê]“«.îq DËE}ío=f“°H†!ÒGq×#ÆË)­õo·QXÁ½ì/s¶é0-u £8ñŒ­*(15E»²`g«-?Brñs p[•qºH•6"²àR\t§¶Ý1¹lÓÊù'~䨅KÀc#{®Ò\ðÒ."¢œ ”«k icsêuÓæ'ëT‚'’‡7w¹eGäþX“9Ø6ä¦#Ëí´â :_hƬŒ*‡i8º"-ÛrFåZ:é2‡[½çJ¹¶ÃÿCôe½œíÓ(¾c9d&•w 0r^ÆŸŠ¸§¿in#‘¢ºÇŽešÉ¦§™ÆlG¢¸ñg0iO»8Œ¡†›v…)«½ªÜÅÑûŒ©8™‰è…-^;þäÝôýãÕ·Æ+ï7sžÕ½ñ·퓨µ¥È`Êo-yå${6ñاbDìé)ŒÃp«,ÍÑÖ‘Ž~›F=S^•LNo°{w±n—W;ßQmr±ÇD¢RÊáOLE¤ë¯5]¨ZxCŠÊ)Ù'®Óé“ió}ê ÌÜ'šï«p¼]Ãù‡X¬¥&äÞ\Ȭo û¹üwðûã[qvû(ûÌj-\t““—ð¡½>ÅUÑúÿ¦ºVÎ&³c³tA­v¢é5—‡SNiZð¦4û½´:L--¡Æ¦¾p¢èŒL·“˜™E×lk(Š€`ÚJ!ÝGq(%T¦›®¼û+\Öixô*f Š!kákšô’³ÿ?ÓãÌ‘rùˆs_]ó­X·UÙ¢ãX¡ÅtådÜ$˜»âM´ë©A* ˆeT¤C˜ªéY&¸:2KÛ;¾m1¢Ñu3ª¨ð^¶²6(Æž1‹IæD½åà-{](¤Šyqºž½@`Ü NNÂõ9–܉R1Œb”¢!Áìw-òã¬mì /|Á  ñ?PÌö T:¸ÊÐ+šµ¿¹ÍȾ§ÖÖ=ˆQ›õ1w,ë7">lªk*Êä¸oþ÷ol½*DÞE¡íkš6@ uk$  €˜ýÓÜ»–5öºõ˜ŽdÓåÚ¦\p¦j1êçíë›zÛrˆ å£ G4leQ*§+fö@çD‚4îv¨€‡Mc¬/®m:?gž#ù†Î2|t1!g‚¨™‹Žx­¶‚»š0d.P"ñrPTÎg {­J²¢@Tô –A y×dêÍÖ}á°ºGh.ïíU™î8®‘úÀ¹CÖ–¼™“+Y.âv®wˆr&ºriNN´®äŒ`ññ×s÷îg¢Zúʲºü Ušì¸$} 9¹n D óÔ*§Ñì™b¥ÅÔÊ¡„ÁB¶ ˆZ¦t=̧Û˹K¨ÙÜú1ýë8ö¹W¾<áûü´È´† s>–JA/.eJám¢¹”ôˆ"à5ר÷­Âã®ìa|Ž1¨Å1þØL1ÿ˜Á™Ô˜¾¢œ+ëÏtTPÊ«þ^»d·(²Ê;âæ@‚$)Œ¢†= "au­5¾û±¼Ç¥šžK+S·>qà¥Þ¦¹;ŽØpûzœß?ùÉ…qûóEdÛ'Ýù—Ýø¢pEŠ·rc”Ôt¾JP#rìÖª÷4DÞ×*E“.›y·M¹ì–V[´ŽƒrdMsF¡ÁØŠžÝ$€k%Í/`k°u.äo¨'ã¸3szxð+ï$Fæ»öáä¿%okU¾8gs±k!°[8âÃ;黊>]+R=ªÊI®ŠÙÊ`EÎôê·¨’öÃ¥ö6Ûi^÷¿S#†N Éµ4OÏTÌl0éªÇÀÖë+2ÃgXäHåDS1V€(Ñ–…¢&Ý´B 5g޼Ô7Ü/¤”º¬$üV»#«­:2ô›gÉòàÝ8õŠp1“Ø®ÖâB™MÉL%Ý_oQÖ£¶DcÞ­….éR¡®¦Ó%»ÿQÅ‚\ˆóÒ'º(ïâíæ1NNìVÚ "_£òkÝ}_ºÿIéýº}ü†ÿåj»™úZr¢..L¹uàÎ+ñ~ñapÜÑ\gÉ™fö´² ýÞâyE-<¨ÎÊ1ó8P¥Z&Ö•¶]»EQ’tU>ó2DE"]üow÷×xé¿éï™…ØêàiAJaJ&µÈ(’Ì 8®­úo[°í=Pøg"›PLs);‰WŒù%vl¦¢¤0×ÃUÈ^M'WCq1WýÛÊfÅÄÌpÇê\`SÙwg-yˆ´´k7 ›A8YE ™„àL³wä8 fÝãׯ¿Vþéo»†ß¹ÌÈæ·QúÊÅôl´jè—½?p®J±9yÈìÑeLkÅ®2âi‰\Ãh`y arì#x)KÖjÃ:ÅLìÿ…Uµgˆ;G´íe¢­Ê’®P¼öžÚï{·Üw‹û§¶Ò!¤†žg’5ü ZæH¥(J~Èç¸ä¨Î$çgÿñ}›Ã¯Hì"¡_å N>Òq˜n¼åÉŒ»:&¸˜¥ú6= ªÝ€kz8)|ÂH5Š|Å«Š[®©úwc¶ÚâõËÅ ‹ÞüøsP¥j`xkX*ºë,»3zËevrC¶Wa`”9J#lª"47AgáÖ‡ï”o ·–!W€>ÕôÑÍ#5µæÕ«'è¥ék²(š,¼ÇÍÇHƒ´SVÿäáÎù£ÕSj@¿º·öof¹i"rÙkÛ„“}ÁHÿ—oËŠ¹¾6›ió®×un±jÕÒ¼uÈÈ,fåH7¦ykælɇɮyÿo[½þãÕÛÃ.œK³È¯n¶&m^]+±Â‹óÅÄ|Eä¸ëp;d»¥âÞ”T¤~Ê»7”Dhaùõ§õ×Rnu•¬,{„zÂL¤‡®’zé¼V#=ú}$ÐÀS#éÛ‹HB©¸ˆ\79 Q ¿F¯Hû‚Èîv­§ÔmA·aùÂ~àb³ž²€åìWý(ùÁþBåÜK‚îÜZçå5ñ%Ñ1iC²½ÂÑǧ²ânÃÁ9M©äY;¶n˜°IB¬ÝF*‘LqT ]¯sÞ ‡Lm»•‘?µô9p¥(0Ê”#¸Š%É'§\ܨ¹/eæÏXL§?lcîpòÒæŸ^>Jqhè¬Ér7"1ëËÎÌK½{*Ö6&1²‹ºxíd› ™Ç85̶¿qwmÒâK;Ë,ôq¥r .$Щ$€8¨M»{ΖT¹O½2«óÜ2.‘k‰sŠǼºÝÑÈx5`²Æmm™©r.ÝfEBÜ¿›Æ8]„J7ͦ*%•¬Þ‰êç?}ô.Hå:M{òù>Xµ¹üБN>BcëßÑüêÊyí<)žàøãéý0í’ç8㋽s‘>ý‰TŠ·ZE‹×‚±—x‚€%4õ2K¤»Sv[ûýË] ÜÎàN§˜üJŸ£Ó/sùweX?&8éëkh0Æ‹û†ió -Ƽh›¸¶Ü†ÁP–5«ŠñeÈí>ËÏß™Fø²m(¢‚³…!%ñLœÓm‚æöÏ{ÎÙ¬ŽÍ ø»H>aíÍ–¸UÏŸBKÚ>Õ'å¬Àý#Ý9Ýþ^b{Â\ˆGùC(ÀÎÊ ¢ëŠe$nÙÅUb§AUÔ¨:ÕzsumÇSGÓTñþ">ܼJ •Ÿ‰IKËÉçç;íì±#w¡Ê\ù.õY…{ŽfY]yvê·®P]ár»{ši´’ )õŠ ì†5 a hžæM¸C¹\EÜ®¿M~‘Š|çàx®žæGØ'ý:WÕ»v"X¹nOòÒÝ[D?*)¼U6sÜRRL×9£µµ‡®tÓ@Ià*“’n…±²f{xÑ~¹*[\é¨PãÛ¤Ÿz’ÀfufRcÓê-‘=3½vH-“LÏx™‹JôCo×€Züšˆpo7|u ¥ôÞ¦ÇÊOšD‹B[ý£ø®Bà¬;a>°Ⱥƒdº«1D{¦ìýM[ì8’¨ˆ˜Å®êT¾‡\s~ê Å›¤öâwpøª©n\ד^+·˜6øÁx Ð'šÆcÁ‰òÁ±ùï!†Õ¹žZVÝç|’ÕâÊVñ¼¬AI(­‘t(Ñì«>9&ŒÐÃÛXúîý8Ÿ¥_5àÔ Á¨?ËsdC­Év#WØ:h˜ûýCœ_°rÎ2·Yb/PŽÙ ­Û³†¶üé£ðîRÄ)?MEf°%•/.³{Yqû’/}³JQW)H–í³·Ý¢ñ»SÀÜ£Œ†´ŽÝø; °ú~pSŽð64]°”;(DÜPnNqÚŒÄtÄ*§i3%åº/¿Gaˆª*ER1LPxNöÿxnå·n‚FÉÈ£¤ÓÿeØÊ…¤î±ÊÙã]ãâ>_BºñòEs±Sh@4fÙ&¤)€¸9Jì %LÅú¥6š€+×U[†¹®~OO©½QÌ)RZ}03)˜ÜÓØªQÈÊØ$àC“ɪ©‘L Bãð(!ÔÇEë¸5Þíï©NÙ¿î/s--¯[ª0rF 4þxõTœIcel}7ùï¶s†—Œ;‡ˆ®«·šö2ÝQ¡ЄhB4!F„#B¡ЄhB4!F„#B¡ЄhB4!_ÿÕ„A(.ãÁ3ê¤tÌã@ÜBˆ6~ |Å܆‰uLŠÕê´–Ï9?Ï>5XïñòZ˜®K:Cgçwy^].x‹AÕ”ê×|”ªÒœÎ?¸ãÑi8DZN¼Û¨¶†î2(š½×Ûïs±mÓe”6?S]x×NŸ A‚²·º10ƒ•VÉÏ©†n¸.ÿNoOË»+ɬ¶@[ Þ‘s’ÄK†íÇP"2ÇŸžzàÊ,º¢Õ\Å0£Bí6àzϤof7Ól»kîÁ®·E‰=®hpi=ä'ýHGú-Õà«õñ;ÉÎkæyÓ•·’·¼ Rpv]¼Ê=¥¿dãËe©»­­›ЋI¼=»‘ˆ~Ùw(ª¨õ§uŸ¹&ý¾Œ3j4 ¦À(Ó\¹ôn®UØK=å®8zòÏ+`‘­»-¾sYðŒ”y sBIÅÏCqžê´î;fãa+q[·D$“–O™:nªK·p` †Çí¥ãÛÐó]¼ÐþåÕãø#p!XZšA^ÿ°*™…ýO¹sf$¯¸}Ãl“®8×QçÌ8ûÝ Ì[ÿx¤å7.,{vé¿®KFÐvã¹±DSf¬iĠЩlM:ùz·cÙ·Ûí!½¡F³žœhI W0=‹V éŒ$ž)ÅYÁ¸îNBå+vÙä6O¸æî;ÖéŽÍÉ\·6AŸ»ZÊ6~òí%¹qÚW ç¨ÊI‹´A¼ƒb‘Úˆ’(¤nsu×V÷ÛÔSÏsDÇ[%K]PEHkšp­EÄ Æ )œ±)Ç›=B¹{Êö=Ë|5àãkNÁ„“²q-çhbl· ~a¸IFQ°ÆòOs´¤<M™Â2!­በɉ·|Þz÷iܶ“c$äº=-§”N^l)Ã0(0Re¦3Z)# » à’M¤¾ÃÙÍuâS™Œ±³½½qÞ:/Êö)ˇDž¶®û=Ë÷í–ˆWt³5;XŠ"¦â‰8¿In[vÕ¿É4övó1 €%isAÔsy…4ãQBp5¾¦BKAI~Ló«˜|ÕP·¶iâ—mÛýš16«Ù‹qÎS·óM½nÜ O´·¸.<ÓxE¯³•œé¹\é år¢dES]©ºÓdß,E¼ñÂe sPê5À’~pªžûˆän“Dü¹}K9”¶!›À1\ôþ‘ãÕñ"…ÅzX³—7ÈFOM4”…‘JvEpäcgfãÞ[ÑË5vs™Ãa`ß¶r‚)fíý}²Úí¯±e­¤p kƒIzðŸ.Äz~Úc9R|g@æl‡Ìf¥ìL¿v_VÍ¿w¥· %bJµÆv”<Ñ¢ãÜÉ;”›“ݪáú‰yR#Ó¯:‡þŸ‰–w’d 9ïb@>4Æ€’IâT§Ê"hÕË牷ã÷?¹eq?”Þ•¸2Å»3j’ñÑÙˈ±K㻊וcúq9ÛŽ)ƒ̼„ŽòYÃ÷SnÑe°L£7 œä]ì=\[iu¶±ú²sy\Ü3¨Çé§qH9ù\ÕF­»‚3*fŒSró€Å9s$cxÅ:\-yÌ[Qw"*5/•2sÌctQL‚ Ô¿ 5æ¶Ø#Ø·[«x_ªHí'´T€~!P\D!‘à*›ŽòÎ?l{Ž-ÆY³zØl\»qNÙ¼Òe*nÆÚ÷U*áfg =¯ˆj)Ê"]PôÍõ–Ù½EygìÇ–P\ÜxÑ®a¨á;ANÚJÚêp@╜Žõ7æO1›AXùï‡Y—=ncîØÄùz'!bvHèùñäÃì÷1 ¯—ˆfb"¬{– £D fæ‰Nû¿{³nû4¶²Ånçȧ–¢•o6pÌ`¬å¹c˜ê´ÕÆÑ‚{j5YFÅš¤U b€íÚ@ íÜ"=}¿.¼‹¸ÏKéÿ(¸ª§º‡”à²c9¿Ÿx_q¥yàN;q—$äx÷óŽàr^g²²%ÓxZ¬§áÛò0vÛËK*ؑёkGµ\»ŠÔ^Qû¤ÅqEaH;§µ]U¶ôÜdIglnK‰õ\×@p´@áQËZ¹ØÐÐJµ±fÁ«·ŠªÎóvYä†Rs”/Ž9ñË]SWEÇ|¸ã¥—{ÙŒ²ÓxH7•—¹ïFW†FÈes8£ä”Tjfe:®×QR¨¢‚p›î_Qm;üm–(bl¢µ-LMI­;©™ÍbêfJ&ÅÊ>Uð¢ì¼.ÜK"ñ´òl[yc å‹eKËd¸TÛÈ6E¥ÅÞFD«6i.ñ$Õjñ:.TEpY#Dö˯À&µ.)©§{Ž'íE¥ÈŠ£ðªÝ;ÍþN« sÛ‹hþ“-¥—íšÚ6= ä5÷ž8Ô×4¿]ºi¤hRÞ?óëš|0µÙà®5ñbç¾Æì–QÊM¸2$œ ù`™<©›k1YÌÒ‰EÚHlÑé¡ÞL‰ WBûÓ](fŽÒÎͯ}C¥ÒïUÀ»V—;]4ƒJÑ€­*‘Íh4%-¼á™ÓÈëeÕø]Ä t·ß1ÁöÎ;ÉqxvjBnfqÅß%d/—ßÌ'>uåÁE¬³X¢´j‚@È U;·Ž·é+ޟ¶ØÈæ¶šÇÉ©:Ëu‚^+AB@“GÍ KBÙòߟÁæ©¡-ŽAñ…Œ†‡RذòÍŒ2ÄTÇÐ*ÊEIº‹µ. Låp ÁÈÅ‚^]Ük¶È¤²ÂŠi(¨©®‹¸û¡²uÔèÛs6š¿ËW|k‚Ëîð[…V¿ ò/˜\7°®lqcÅãlÝÇ|„àò—¿ye—#b©)Å<–‹bGÑvÔªâÜŠ±|“U&›…Û¬ªD1un›÷Ns²]zrXF‰¦ãÝòƉ†Ý“ob_dNaòk0Z38s`Ü!Ä [wväh¾>Z“з.HHÀ¨[·¾Bº®[¢ð’³ˆä¢ C6rÊ1Jy„7 ¶ãÖ›½•žÙmmm£œBÍ%ýÏq%ſݨorÃî#cHcCAìâ ’Ø TÇë[î v @ÄSÁMÀNCwÄ8€€‡³\ÆÇ}Ѻ ¨Í©UÜ&mù=›9Uê3”0´Ï'Öµ2Ààq­œ•«pÇ·˜.›8¸ò ÚÓtC"^fd®Ú k•ƒ~ÛDD¦ö}ëÜOßmð´9¢PÚaÇ´š“‰ãõ+I/5Æó-¦LÈÜ¢œâ=«éÖÕ{pœc·3yyÆÍ…øºžjV\¶#™sÜ Û§Çhݳ Ρ"S{÷©H »ƒ².Yõñþ„ld"¢¸ã\q¦t¥qÉd]·ÒÒâ¶U™ÞÛØK‚ FRPÓNœFËÅÊÆ(‹ÈÙ8Ék 프{ÔHª+¤r*Š…)Š`×4´ßæ‡t}ËA­Aú”ÎCõµ6.ïQnD] å9Ä.'r·&Ú‘¶¼.rÈÖnD·2\ì\A„R5Ö1ÉU¿›±2…Äz·»¼Ç2¢rõsÖ{FìØíem5ãž ~4p⺊@=F‚GjLæ+ï–\þÈ6…ñÈé(VVÆ3…<.!ÃöºÚÉÄxªSh‡°ìÆj¬‹8oݸYÓål‚'\È ‰©ên½†X?oš#€4Q­o`!ö&./†Ø¬Œ7©)8ÃŒn|†ø[Á ¼yìè» 0¯}âL»pÍæhhÛmŪº¹-Ëù :´´k÷§rŠm[°Üè‚ç(ÚôÏ]m¶[q€ÛÛ09 :u_AJ¾®5'&€U9 ËY4´ cüqU:Zí¹”º®U1¥ƒˆœ;W qÖ*ޏ!ñõ¬Dc°+Kb6è¹.ùöÌÜ‹Q]@s$íC.ª†Þ Ròþ¥ÜvÛýû÷vñ±­qÄ4Q¢‚™|sÍUÎöK#Î{•м}^¹BßÜ|TŠà§½.¬i+…ó“ÈIÙ²JÆK·¸$ÌNI åÔûy(Fk øçMÌÍMB‚){F×ÖÛl;pµÖÑÇJèc\Žx“^úÕZEvÁn†Ø?ñU¯ˆü±ÎœÉwFyÁœ`â¤æX¸efæmI<‰då9T1,uÀÒuŒÅ£‹[Ú¹’ÌV&Õ>vb„’’Žº.)Ì¥^ßÖö;måÌÚ#!Î̇rƒÁ¼Ùx×Å";Æ1î:*åžJó"ûa{eŽ6ñwÞîfîÌ€ì+þʺ/c%æ8[^NnŒ¥}1šHíÜÆX[‘éÌŠ@eÅ4ÀšäÞêõNnRG8´µeèu]+D®m Hsµ@T«V·(˜¿tW9  gxWþÝ"N‚N†½¿ÙÎ#SFÈZnê!³´¨|¡ø¹ ä\Gª--{ð©͊îù,máæãòÒ­6_oBg¬ÝCJUQÜRÔ´øˆaè!¦,7¯rÛ7») .a‘¯±í ŠöŒ1QÅ=i# š7°ó‡*Q«Tê4!F„#B¡ЄhB4!F„#B¡ЄhB4!F„#BÿÖZÛ ¨ª Óhí( €í÷ôðöëæ~æÃ¥Îjl…¼ä[¤qò8š†.ââî &ÛÖš×És[V¸… H«áÜ,Råî¨Å¹À¡@¢]z€{vˆÁ¤Cs;M=Có¥‰â£w5 íÔȊ⚤Oi@¦¥¡Pñê#óêm¤£÷QºsV׊K8¬Wþ¢Þ .b&pM»Šølß\3HÌÏâe8‹ŠVÇsò?xG=$¼Å–1Ãr’HÈE³\,ÔëÍ‘R»“ ‡®ºÜý½»_í_«O#"c#©þã@oЮã»m(@øeøÏjÍD8•ytÛÖÜSˉãû±¼lCH;n,ÓNÖ|æ2Šm øA6m’¤Ý*e €â_¹E{}pëWQ®qq À šàC°dgí` ‘¼c"”j¬O`HgfQ©]ûÙ0|À[œÝ[¼D@k×pP)á­(=í$‚ió&\Ð)CPUm艈—ŒÆ«' 3l—! VÒLŠ®™”¨í/šDà$(€Tß.3ÊçklŽ?Ø«Áß?Ñã[ná)>+3¦I* ªë“Èͤ$¨ì,{² °¢"PS¥u‰ö¸ÈÒjåŒ|½Ë*Û‡p•ñm/Ø…MDæâÉÙ¡ŒŠû¢fÊ(=ÓT;…8›ßM4é'ôõ]@PA S,k +h¬ã™8Z-:91[”’ ˜Y.B¢C3ñøiæÜLcoæ È-“K~)¼«&­RM7mVˆ~€ óQjÌVP” w ƒÖ¾ñÓ÷ä‰ ÀÔGa=OjÅií^ÎcؽLÆY£u„¡S§0ˆü"iìðÕ“%‘”-y68à´?uÇ¢S‘Ñ›ã! M´ˆšƒJ¿NÏ$Ž¡sÉ .¨È(Üzg(‚ÈåÞ8…j""%á§-¥,s(üÐO5J$Hxä½6Ój%!@@GáÚ"Ô~Nš·7¿Í)ªVªŠ°c¡·™“c‰L;ˆÐ=¢!Ö£^¾ý"I%1¸z¤ %a‚²6 hs¤Ú‘ìÇhêŠ"Q(í À;„jb޹‡P~äI%%v}«-qÈœg ªAº5¡‹°)TˆZ˜@wÃ§Ž´×ÏpÂO¬ê©~Z\¾AE& )G3¤]…©€:õ¯þÍd\Ü~kª™ ‘ޡן'm:Q(¶~n<Àñ•¹@â@îO¥Ó¨të­bÝ'·Ü!kæw¦ì3í¢(iž)%÷{G,ö*Õ3—hЧ‰Jb…xW¡zuñé­‹q•ñ^ëÖAÜj–‚&·+)5²µ4-I.-…ƒ Úº* @ÛL P*”5€AüzºŽWŒjœm(ÕDU ()ÆÚ(ˆPKù¢oÇ«å™ÌÁÔF4«”~e ˜ ZÑ(WqiñT(PÖ¾ß &<ñ8¢¸’FkIÒ5»¶EPR©‰Ž‘N5T !N€SxŽ¢_ºF~do"‹#2>5è R"’I™#‡ÂR‚Q ÛNQ¨âõ÷é³1–-EÄ’³õ¯9Hˆ‡&9ŽÁ¹ûÄ“9“¢`¥ Pj:a˜1Á¯8`›$‘– {7Ì­HÑ N!vö«R›óL$ñ ûôΧÆóÎHwýJðu\qJu¡£éT<«pó %(ì7r€tºu¶ÓßQÕôZjjÓôqO1Ü¡¡ØÑz°lÍ DÀÑ‹5À^Ñ:pí І ³X¸sÜÍD>”š¼ U¨*Øa¿º‘tí·)U 9`pLCíï¢@0†¢A{<5źÞ\k:Á£±áÇïJæ'U±X â=ƒòD¥¬[è %0Ô: a ø@Ô®’Üu`ëid­Ä4·OáøS—ü5T›©ŽoU™?¿â³•YS·•  ÉÝ’FVÀPn¨˜Ô:­„µ÷‰+«Ù4ú“ALÌߟҢz`ŸR«½š¹€.‹_I9HÛ žb‡SqíT’”A2ˆü)³‘Y%GƧxou5êÏûvê‘u¶n]'s'çÛ8Í9úOu$¹²ïJÝ:zçTRZ=ÕsqGÀýk§:ô¢Ù¡ЄhB4!F„#B¡ЄhB4!F„#B¡ЄhB4!¿ÿ×Q@²õ*ˆ‰N;kÐ¥÷P@iZt×ÍKòÛL‚Òâ󦨀…Ø&©ªJSáëAm<5¬¼8)g"­VH•ALÁN‚Q ÔKJP:tñ~¡1Á®ªÀâKT%ª»wP‡¡h""&-MZÐK_hêu5P°‰ÒÕ±ƒòL¥™ºQ>ïie2÷'V'-CÁ% SuñÛ©×2Dö´8Ò½©`ÐÐW@#ݑŭpŠ'å•MšªdÜ)*ÂA2‰¢Tœ§Ü¥>q¾$™ ¤ù›E ã VòV%£\³*ˆïr$jää •@ý¾)`7bøô7Ošˆø\ãÊòHÄU E&Ìœ«äÎDdÁßmC¨$2N]§¸; Qº¨˜S ý„¾ÀÓå¦Iq€íEFb,¤Dôr‹‹5ö]¤SMÄ#Õ…‹ä€¤Ý´ÍÖ1T0ÃOÁ¤H CP›Õ‰9¬è¥g¶…Èèä]6ë)p#ÝSQ#nDZV§© õ8ÓAi «³I uY¶¹ nd9Ûp‰™É5Ü(ÅÁO±?DÉ$Üâ&7j!Ô¡Ô4Û_¤¹œ jÕ3‡ÞRlÖn4v %š‘j¥Û^=c³”25«ý! nöu®a$Tæ–§¦Þâ* á7vI l‚â`0‘ $EÂ@1A>áËÔ}½zë^Þ-ÃecÂÃÉ}0Åx³nõL\·n³Ÿ.dŽª¨Aw1ç0P>  ÐDGKµ¸1´ÝŠFªÀ¥ä¤38ùwglÅ&é¹lš¬D S Ò0}Gü@­MPÖÇe;Þ^òQ‹•6äŒacò[9´How[Qr ½ ÷›3¤0@O±4Ì4ÿŠº"il3DN,}iÜïãTÄàpK˜w=•Ú©_ˆ í Ó·à5ê& ‡Ï§dÓ,n`ÄtnÌSBH½ÄEN¦- `­áˆ{€j4ù5ª;–GaU ’Þò´ŒNR¬¢b!C€˜ÕTz€Ò£òÐk]E•¾WQ$­Ê¢JeÕ„£A5F•©Ä|GÇR¢ysj‚I¥V°ô*¦)JS »­F½z D~MH!Îmk‚%Cç€÷?÷»”ê"j€Ô@½4¨ÜjÜ2I¦“TÁhJˆWhÐ@Ü%Ý´ÀÆöû+«x‰v5Á, * þ´PäPJ1U¨ü^ß j&¿.Ÿ.n%Ç ”'šÅ~P˜§Ú4§^»«P¥ÃÝ­'¨mËØ^°ÜB®ƒsÝE!ÞjÃøºü%ú?¹”íÓ#ÇõI·ˆ;7Rƒ¼Æ5FàSÖ€=šc…Z±^ €¦&:*ä•(¦¡ ùà`íÚ?íÓOµæ9/~e–€IÔpHi˜sÄËÈGˆQ4Ü(ªuüäÜÕí m5[½Ü¿¸²µ¸n&˜Ÿ™šÐ *ÔÛT(h˜HÐÕ÷ @­tå”ߘÒrPèNÉ%.6¢RœLP üh€ÒzW¨ëyÛ¥Ô[*Á¥¢€$¯ib˜w¤p!ê0 *Q¡‡åêÙã 4w ,3NM(—e]„GpãP:íèP£Ô¡©18Ó2–i¨^’©÷Rtå(€ÃQ=h>ÿ“Ji«ôÕ`‚Or† c¢ëÄÄø†•èp¥j.f‰"8bV(á’gÆ«¸„9„ UˆP¥ *S˜z€ôëO—U–bñÌ Q5§Î½:ÚÍ@0u²‚#Q¨, 'ê t¥|5†‡E)k›ƒ¾Ä—4Œj–ÒR`'U‰@HÅ ¦1VÝBAÜQê!AÖÇɦ‚ºJe팆 fõSÊS¦m¢oˆ6‰LP:‡Ñù}š¸·h¨cŽ5Ÿ½{˜{n© “´Ê¨”<*¦¶µÔ ‡QðÒi©Ž©çiùþA=&†–Ð'&;”ì®ÔåÜU™(DÇã1jÙcî)€âMq§MÁ­ ªmL°ÎÁÃêHõO¯½¬Dß°pÄÆ]±@Â;¶º ­P  "z’>]r-ŸpvÛºDçFXÿp?L{*“s®-ÿ¼ÜGܾ¢ŠáÁžE¨z“éÖUˆ˜ä'P\‚bRhë— fˆ§©.m\Ïë90®ñÛOÕ\Í%§˜ñNËÇÁnØÿƒg?¼-ÏëhjŸyÏàýŸ³ØÿjŸûå×å&¡Z~5æTBìûT?Z·ä lÖ>W|R¿Š¦Ü¤ú8Ãõó¬u?þf÷ý“~´ÅÆE!ã|þOû¬Gåw‚Œ|ðø„äÝG?èZ¬ÿ¨TöæTm?Þ¿ÛþÔWþ‘ðX…¼oâÖä?o—˽eÙ­cÞCç/èV ý/‚ÀÌ-×Ñüò†™XvnKEoä›ôÃWpyWÝö¯†_I/Öééä‚fÚÚ¦ü“ZÎóú¥µ[Ëgì‰óÿ‰®Isú’øýŠDy0{öƒþPÔ4ÓüŒø­c¶_Ò.ž“ôJOâwÁ-r/øˆŸÐüšÜì¿úV|ŸæwÅ)å Q[Õ?vWù&ü¤Óãõ‚S³*§ï?^O÷i×þ›>?bBcBþì‡òÔÿ“U¶ÿæ$BþI}›ÿèãüèis~´^)·fRŽOí“þYœ6ž‡7$IæÌ£K}¢ÿ®Sôõ)ž`£,“~ãÿÏ~˜k?þ D¾Aã÷¦‘ý¬¿ôQþ¶ÛZ—R–wØSLóÐë÷x?Õ¡ýg^x¾ýk¿ç*k2zÜ4ÿ6ÿ¸ÿ9®Þßò±ÿ²+P¨>]«{jˆ‘þüÓ[L;ý_ò7ìO³ÎWêÿü«ÿØwÿ¯Gké?Gÿü—KÿùÖßîXºU·ùkäoÔ [}F„#B¡ЄhB4!F„#B¡ЄhB4!F„#BÿÙspring-security-2.0.7.RELEASE/docs/reference/resources/images/SecurityInterception.gif0000644000000000000000000001263411766764657025722 0ustar GIF89a5³ïïïÛÛÛæææÿÿÿÈÈÈ´´´ÑÑѵµµ½½½³³³«««ªªª¢¢¢¬¬¬!ù,5ÿÈI«½8ëÍ»ÿ`(Ždižhª®lë¾p,Ïtmßx®ï|ïÿÀ pH,ȤrÉl:ŸPh`J­Z¯Ø¬vËíz¿`ÁÀ.›Ïè´z]ëØð¸|~vW„¼~Ïïûÿ€‚ƒ„…„d†ŒŽ‘’…ˆŠ9x“™š›œ†•˜¢£¢‹¤ª«¬¤¦¨—­²³«¯ ´¸¹°D¡ºÁµ½oÃÇÈ}¼¾ÀÉÏË©ÐÔÕÒ±ÖÚ­ØÎÛà{ÝCßáæÂã6åçìéëíÔï@ñò÷£ô3öøýâÅwüiÓ烟ÀƒŽÆ0ˆPÞ;†›Ö„L!ŠÈ$ÂxÏâ ŽµÿþLDø0L¯Arr#À_ÖXæI ¨å®“1_Þ°IæM?ülúÌU’Óq¡Pݵt)S*3:eŠ´ªQBx–&5ªR¥z¬x ˵¬Õg]hugvæØ§QÉB…—ìYª¸Šjêö'ʾ†LXΈXƒ¬xx°ßÂ}Fîë¸rÆÄ4Sj ¹ócß[,KïÞ¶¡Ï½úä\¼u3Ë:õd¿­ç–›u²´-4S²í¹Jaº,_OZ:±pÐŽo‹.îyôó°˜\Ï$™:héÇ)‹G›]Æö‡Á“NÍžïúY¦¹Aþ:_jÙó5Ë÷Ào24}ÿö!Å_ÿ)úÁ0 ;ó½™r÷U_CÇÞ#á VÈs^6›b†èI‰(Ѓ&6÷a=)¶‰j¹Ø‡2Âc65ºx¡ æ8 Š>v²c =©Ë(idB4.™Ï:)"’'()%%M^)Û4Z6D¥ VvyM–bJòåBez %†iþFf›L®¨œ'®É#¾‰'–r´'>g’æŸ@þ9fŸûê) ºg|ÆÑ5½WÝFÌ]…èE½¶PœMÉh’Vj©J§*3ž©£åù!Wß­^¨¬~šª™£î“Q«•–`‹Ž€ñLwH©žôi°Ò¥[ÿ[P%e\”{”²oYÚn±Á6S®æíZÜrÏZ;-rËÙ‡­·G‚[°º¹mºrµ.µ×žË ¾M¥ÛÛº™æ÷*tíyÇšÁ³ç¬z ÿ³éŽò]uÄVqwë5|«ŠÆØªñÇ—\ðÅéIš0Ÿ·XÆðnÇ}²ÈÆÂÜq„”­¼Ú_$+˜sSª}L°"P$–ÌO½,`Â<ßôoËB»¼ê¡)‹§ñÄ cü²zHsí0—aÍ5¬$orÄ5ߌÓ&wÍöc=›ý¯WíÕÓ?lmr[WkôÖûìÒØÙŒ#:•åæ·Äí)~·àÈy¨6ªÑõ;·ãTém9ÿÀcN3ƒ1S²pœ¢sçd8 hzœvû¨»¢Î®ƒ´ k{Mºû×E´þ»èQOÌÀÆ×|òå^4ó®è ½é¬CûêlZ/¤sttïý÷¶þøä—ßý)o˜¯þúߣ_€Àüô×oÿýøç¯ÿþü÷ïÿÿü3ÀŒ?ùð€L ùÇ‹:pHÄâ÷À Zð‚T`-Aà ¡GHšð„(L¡ WÈÂZal¡ gHê0À¡ whC;¨c 䡇HÄ"öp Q`Â%@…$:Ñ€ÇÍÅ%NñŠXTBï`Å,ÿ>1ŠLô"ÀF1šñŒû‘"(ȈÆ&l‘mÕÇ:Ú18wœ"÷˜Gt±} ¤ å8H)”qŽƒü£7 ÉÈF.Ò‘Zd‰H2"’˜Œ#/™É71`Ï}úóŸ ¨@JЂ>³ŸM¨BéO„zÑ¡ (D§9Ñ+V4ÿ¢û¼(35šDŽb4ŸfHŸ0ÒšTš%UâIW*Д²ô¥0©LñéÒ™Úô¦ÛÄ©N¥À¾žúÔ‡‚ÚéìéÓ¢µ HöÄ!Á*ų¦dxÞR÷ÒT¥Nuîs*;¡ú Ý]õGYõÆWÓ¶R®’ëc] f„§!êmÕ–‚JkOÖšV·®Ó¬•«ZWÄÖ ¹¯pf_»DÁª {È*:UùNÆúQ¯Ñ «³¢1µ÷\çu@ñ”'vá¼;(Š›¥›ÐzÙƒ¥I­EWiýH$ª2JBÌÄYÄ6ö³õôì#·(I>®ò·õm©œ=T»äÓ_-¬n{»J“ZÓ ©a¯aPg§Õ¼Vriýìh`w¶uªqMiýÓ×þµ³Ÿ ËI[ÅÎu®Tœéh…»ü]dÏ·õ0‹²ºïýî#ÖûÞCï–‹¦z$’¾•gUÃû²ì˜„<­3³x‘$üïrR¤:p‹Wy;©ðíÆ y/¢X&ÿÒóK½Ýa1ú‚Õ£Uàgå_Ä×£Ú¾}9”¼ca‚Ö£ÞHô(`‡OüâÓO€º/säIºkó6¿ÙU¼½ô§/bÄЈØÏ¾öE(Í+4ùÞ•5x— ëò+ш0 ñ×Ïþößoƒô -ø!9åg{´½þõó›qýÿíûÿÿhB@åNsÔzub–äj°{æÇl¤Æ{—FKÞgôÇ|»Åh¿EbE"…LøŽT–æ]Ñ—€§„lØEóZUVcÄI"˜‚]%(,T'µb,ƒ28ƒRƒ‰µƒæ„‚>¸ƒèKB¸PG8N°T„»—„µ„¬´'¨ƒPXNKh…B…ü¤…WxWŠä… ×Lè÷…fˆ~N˜xÍ$…g؆Ð7}pxTn8‡5{'QUtø}ûçG{ˆLvxÕ—‡…‚øG~çwˆiÈD<‚HP¢†fxf½·ˆ…ÓˆEˆ|^h~PD‰de‰Q¸hù÷ˆqå‰ ÿŠÞDn&x:¦x¨¨SAA0R[CY§r]B"h¯H‡ö@r«qF[Ä%‹¯%i‡·‹¥Ö‹pC#g]×"4)÷bÏ-8'aÏ]]&1#W‹•ˆŒsX,Xv_&³ax4Z×4ËHø52XC{Þø"QtW.Aæ+ISÞÁaÒ˜aV#ah/½èŠïS4a.Öc;–8Q¦—‚Žä˜B‘4‰Q6™#8™“Jè‰Pç“B‡DéS(”7ä~Ô@Lé@Nùÿ?ð‡”-A€BD,X¹CZ)CH•ŸE3»`u1H,`™’ã…I1Taq–I(gciv3Á–sé–Cy rÙ–0!vy—"‘—zI'Ñ—@è+€˜,¢ „Y˜,A…5"¹˜FÈ—Zô˜‰ ’)ƒU„˜`£˜~‚—™É{–—Ínsš¡Ép¦¤ƒ`°_šª©|ÄÄ…°Y•E›µ™”I¹›»I†½™Œgd…bœñ6œ¸iœ¯mÉ©œ8UœÎÇ›Îùœ÷$Ó9SÐIHÖyYJÍÉiGÄ žÝ)žßIž:™G㉞7ÈPÛ‰†EŸäó•½™“‡§”ŸàÿœöyŸCU‡”¸]ÁÙŸþU´¤Ÿ.i‰Z Á ‹Ø“¼XHëéKzŒ(¹  ʃÁÕŠ:š¡gu ZŸ4¡ 0ð:|÷p™s;—,üq‘³¡gø¡6œè—C·3+¦‚Y“‚,çd•Åx¡i£7ŠŸÞ•ýå‘ÍEq»-Ô¸0ÔÅe®åbS’"‡a¦]v @”T„i¤ jNü¤¤ÙuysP&¥jz0‰sÑᥠ¦v)¦c:uˆVQ*octmŠtrÃ8G#ކ^Z@§gi§wZõ”{ ¦skêdZ×a•ªoŠa~Ñ :´˜ŒÚ¨Úñ¨Jš7n÷ÿ3„£Yjçƒ5í('Ûâ4ê"§š‡Ÿ ª®‡ðA;Y#¯°«ä–·úrÿ‰(š¢úy ÇÚ—ÃJ¬J¡#¦Lˆ£  ú–Dvžg‡4š‚Íz¤Åúxò9®¸Ç¬¯d¢ºº”O¹®•ì7•‹šwïiý·•öš•öJŸ9ù­x7¯øÆžÑ)¯Ô Müê›T§­Ç °?x°þš° ‹„¼„®NÛ‚H:±Xè°‹±ßT±c8°{Mk±áŠR!s*²ðv²#û±k²!Û².[²)û€|ø„T)³3û¬+ã‡dâlj`©³$˳«€£µ؇ûJQ{ÿi ˜lKÄ€ˆH´oå´ {®¢ØJ¤X§Ö$±Û…%Ølµiµ9¥²¹ƒäi¶;Û u`l{‰Ø¶*èkÓ·m«¡ÿj·Ê‰·y¢+E~ÛRû´i+¸à9¸Eë¶(•ˆÒZ¸Y¶ŠË:äZ”ŠJƒ•›¹U ¯ï¢¹ž{¹©ø;ûI* †‡’k¦K±¢{”“j¬‹Víöº_+ºÕ«ì`W¶ÝH¹[q§+uÕSo[E»Ú»º‹qÆÛ<µ i»c:É» ¸vÃÛ¼µûs¬èxX˜ª×Т²#£³(+'Q½{še‹ÞKŒ+Ù‚¬•µ¢‰Ã½ks¾tÓỼl¦£ÃÅÿ*½3Œßk‹Œ&ð;siÊü‹¾Âø¿UâqùqUš¾t³,q­‰¤§Yæq[Êvó˜/Ÿ“^ ¥¶‘™ƒ_ ÀOã)fÚÒb`¡]ÿ(]&ç-%·3œ5 Œ¥Ùh ’Âg¡e, §.<’"‡7Òå¥À¹»-WƒÂ•ŠÚ5¦ C ‹L:ŠkZ.’j6KŒ¦S @sš$£ÊĪÄZÜÄKL«QL°<.ÐX9kì6ƒ9‚:.„¨g,2la^‡‹Ïµ óÆÒÇ3ljš$L_©Ês~J©êØ9ü80s¨ƒœŠi,2íh,çx2ùØ9 ЩïRÈ÷c„ꦊÌÿŽHsÅ/Š› B2Å Œ¦­|sJ“É0éªÜ±ø«ª"‰Ãq&¢’OšÃy-\ t8”ÆÎ˜Ã#©Ë„ÃûØË…êªÀü+ÂÌÉU’{¤úq«Z](ļ¼v¸ü˧*Í[œCµìM»ú{2»ZÔ}´h!¥±ëÜÎ(pÎ$1Ï×p ÀN(Šz=2¨u¬ǪZàÐ.AÐ)ðÏ®ব(Š…Ä{j¼Ø{NÏKâ+½zö›Ný»]k ½Už+}² Z)¹+]b-=®/-MÂÇ®øã®6@©K5ÓùƒÓ>@ðª=Ó@Ô´ÓÞT¯÷:ÿB:ÔÔ-dÄ ÀÔPMBO]Õ;$Õ"@Õ÷zÕX=DZ½œƒl'‹²ÿ&·e \ú4¹ÙTÖl½dÖr=×t]×v}×x×{€híÖ„Û×,ûס˜Öo½y€³‚íˆr]ؽ4ØzýØ­½Ç´ÙгA¨ÖChÙüDÙ/‰‰‡4µI渶´gŸ-^A{ˆ"EÚIkÚ±ÖÚHÙµÙf·¢O’ˆ¸É†²Œ]Û¼–fÏ—Ûå³…Ú›ˆÚDÜ™¸lQëÚ‚eÜŸ­‰É-´Bymص™-µ‹DÝo‰\ÛÛ°¹Š)&Úa«‰†8ÞwE¶ßíÛ+›6«M¨Þå½èÜ}µ¸ Róÿ¸÷­ÑùýTû}jËß›½Ö—ÍÿM€à#Èž•„xî-ß ŽßšxNßë á|kà…øOGƱoÔP¶=Ö÷§°þo!N☭àà=·)N±+^¶-NMlR/þ1}aM…š{ãJTãH•”$¡ÔR`!@½C‹$1Ó¥išWÀ¢äI.L>åº,VRRÒ“£¼K¦#YNS[žE6¹»—"f.OEžæ ½a~æ&Âæ8æXTæo.sq~稽ñœ‹©ç&-eQ¾ly\ž>ì¾<:¾©"ç`H\±(q=çDàÈ |võûP÷+ÝË’DÊy†ÿ.v¡^•ƒÁÍ¥9PN—Èıúv?œéd®7öâ^ŠãªA¼4QšÌ‘Ü]bü§6§tˆPÐŽI‹~œÁH÷‰¥Ác,3¿Þ9 PÄÂN¡žÈY¨û¨ŽÀÎuÞ£˜Ü§°^çʾÇYœcÉtþÁ8¬¥7í–\ídŒí pè;[jÊ?¦¾ÉÎuœžÅã¾ ©,ïÎ5,¨$§aïÛî*¼èH’ßžì—ãeÙlî Œ^ΘÍSðï¥Ï®ÓÚîäÇ ð7àñh^Ïê.Tì{"°ë_d!€¾+ç4ÑÉHç"ŸÐ1è!âèw…ózó$?ïX>ôô/_åF¯IxEŸ”<^©NšõCõô_@õ+UÔH@CýDZ¿õïwäOðõ`A][\ýÕ3¤ãIöj?Bl¯nÿö`í‘}÷xŸ÷;spring-security-2.0.7.RELEASE/docs/reference/resources/images/s2_box_logo.png0000644000000000000000000001533511766764657023763 0ustar ‰PNG  IHDR¢M%à¿L pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFIDATxÚì]_L[Wžþ &ÐØÄΟ§alE·ŽµZ"Åt’‡EZjÔ}†dÛ¨‚HwêÑšŠH È*l`¤PÈ2³šU »K5K:˜nVÛvM7 Ó±±IÉÔiHí`ÆÞûÞÞë¿çˆa9ß âÞëã{ÎùÎïÿ9ù|>PP$"JD JD JD JD JDŠ IÄXäd)E—n¤ï”¦‹Ô>Ÿog²Xt”»[oæùfœO|¶óﺦ¬ðšmÖ¨Œ v‰øÛÏównKUŠD8)á  .¼+x°´èûè‹ÿõ\ý§æ…ûž›mVïšQOU'¡€œ9E,8Ÿøzÿã×Ko >·X–‚‰ø»»*yR2:D"œ¤ÃK!‹ ¾¯>ýÄów=í ¿àæ’‘„ˆI¼’ÑKIHÒ^½rèhÊÜüä7Hs²”"!ŸqÔqS@‡@!+…|ûHKÙÙö×é¨oQ¸–¦°´üŽgŸÂî‚ge>äÇœïÞ™ŠùŸ¸g¶Y©æªâX‚oJÓrñZFÒRöÑY à{ÐÞy˜í­°;‡Bî,ÿòÚ¥…VV³ÍºB¬š“Å8Ž„ªÌk”„a!NJGîË"kÏ»!÷~ôcq)€¿ !m/)'K)‰ å}Ir:^Ëè€8)Ž8ETdí©<È\“ïý W•ü:€]9YÊ$""Ôs÷âni1•„ÄÈØu<äÚÞ—“^°@2/ÿ:ý@¨Z~•Ž.1$©¹!×^=(Ά?-&"bj_€4LÃë ‡Û ½qVû̦{÷pÚÓë…ÀK F´9}>ˆ( â³¥˜´˜Ó½(™›»C~^1¦™×L‘x0$ÝÄð–ëÿ !¢Õ>½qœýßùì3gÞÁœk”20€Êcå~S"ƒ¶°dËõ_¼žä»¬ë†nb˜µ{ cPgçA¶ýu¤¦ìÃ_×!cWröžÝòDì9s=g®lÙþ¯9õÆq\Öu…¨—ÊcåPgç±ÿç¾ü!––böÉ ,.?DîËÒ¸åÆšÑjŸAU[-OsI¼ÚíÎ!¸–¦só£0.¿Uæµ5'£nbw,&è·y×åÔ9ùx«°„·@ wd¶G"¶)“ì€Fu8äsÁ rìî8fç…¨Zæœ<úS(™ìµ¬½ûY5mµÏ ïÖ¯¢ö/kï~hTEÄÎÕ>ÝÄ0œî§!cÂÅÉ£åì{l"vèºðA+ngÈ=maIXNýé¼k®Å)LýéøQFÖû¸$mêoFU„Ñ–ïs¦}·Â.¨`(™h¯n!šÃíDqC)û?c’|p£½#¼ͤù.nž¿Ž² 'Øw•Kýv¢ÕþMý-DýÕ¨ŠÐ^}1â☴˜Pßý>Q¿üíÞ<ΊÃíDU[-ê»Ï…p¹D†ž÷ø$t-M…ÁÜü(ÌZ±¸üï|Üïí"I/Ò –.eN ¾ûÒͦç NASKHœyGî»Þ±˜â2‰¸! p÷âé㆗ˆ·3bÇÔ•Õ@.‘±ÿ{¼ó¸÷u]ÔvgŸÜ€4õU؃ÈVœ\×ÇÑ;2"•Õ9ù!^è|öv§ ²/•ŠLôœ¹²ò'-&tèºPÕV‹‚SG°óo²QváĪ ô`5ëp…zêo%ˆ“–»¼qÙÈDÄË*™‹>Ž÷*MÍ…X —òܳßõ«LC§•ÇÊ#ª"‡Û ÝÄ0ŠJÃz•k uv~Â':ÜÙ”D´ÚgX '—ȈlÞ‘Þï– ~A®m87O^$ÁHÆï~c¡sŒ <‡“ º‰a|Ðß§Ô1Eµ ®½¼ž í…‘;àUQÇn'o‚Ãm´*!ÚšŒw\§­ÁÍó×1ÝkÀt¯MÇx‹©C ´gÇÅ|—ç4l$(“ì&›žˆÜh¿\JîyuèºØHKÙ…¬TÐ ®¬Ìó6ç,ÅAÄHá—öêæ¨ ¸!›µ ˬµD3o½©¼æxì îd •ŠŽgŸ ¿@Ù}, …7Â-°hé¿úîs<)sZ[³¡&WÇ“ÐMý-!Y'f¼H£!ë…¸2+êœ|AUĽ#h¬8 ¥"“•Šá6f¯‰QîvâÀÉ8ÜN6uwDUÄs&-wqY×Í#“r ‡â†RT+gC5·}#¼1ШŠ6œDô/Žj^.¼ª­—u]ШC.•aÒ|zãxÂmȸˆÈµ‹HQÕV˦ʲö¼‹9×hØ#+‚!t[ë¤ÙÄ+$ÐM -š`5n1…“&Œm¸Q‹Zë´5œæIõI‹)f,õà ξ«æ#ùE<£WhšHog;Ÿ–²;}.-eO=Ç:{G©Ø/({À(R°7V[r‰ £­C:Nwóüõ˜Áìà~¾èþ‘›“´˜xÕ,¤àÆ!3vUŹ$d‚Û±‘é>K®HDRg硽ºÓ}†¨YuNnž¿²ð䚎7`ºÏr;V~O:vH‡ÛWçäñÚ‰^œq8¢“"—ÈpóüuŒ¶ ¡N[ÚU´…%h¯nF]Y ïù¤šµ‡JXõO€”«ÄIéØ--d+I,å‚óÀL¥R±_ðj×–@[XâOá™MDmL÷0i6ñÈ †Î1èã¼¶åq;g¿'pE²cn' Niêý "bcÅYž$—ȹÁq¬ÈÞ"&b<¡ŸH'^©[Œ§Æ1ÜóBÚ‰·Áû¾Q*2Ñ(äÔM ¯:‘/I#¯3\m0œ"¼`(»p‚'\åý Ž#6Vœå­ÿ'½ÇG–?¿vi¡ÀÈ­Ó®„JD Š ¡š)(ˆ‰èzê³_\\ƒ-›[«9T•%âßÿÜ s-ݧ£KAŒpÅ+¦Ï=ßðð€×ëïØ(»shMXN±5®xÅ5ï[° #}žeïtKÏŠÿG¡)(bÁî 9áéw¾…/>÷| À`…X"ÿÇÓî ¾˜­£’‘""l»ÂÖ Üyþ€Yßð´%€œ,eZÛ?§_•ïU?Àäƒ÷Hߤ±E ¸–¦à|öfŸô‡uj=ô>ý‡¿uý+€!£žþÑ:í#%bÒOJ·ýùÛU©ÿžö’è:Üñ`iÑçùÇÆ…Ñ/ïx~ àßXÌ6«Çç‹í¯$€Ùfõ~<ôÜúË–…Ÿ-¸}f:¤ñðrãÂØ—w<ÆÌšmVéç¹íåÉÿöÜ;õöüÛÓX¦CKAŠóÊ\sý³îßñ|à€/<ÒïGs²”"i²þ¥øÍÒŸ¥VfHVmÛ†T:ÜÁøƒi囟ßÿô¿–ï¸ àS_p™mV6lC¢šC~]<@F1€]xõÍ¿ÞVøCeRζTѯbŸ¦·0|÷ žo¦ŒžoO|ߘ0 à·–Ì6+yq‘CÈ$Ûì°ÀŸØ ªˆÎÉÖ#!üêNäsXäJÁ5#b„L /@2h±ÄV'ã €eøc„+Á0."’·íÞmémIB„4B $z“^ R¤Y(J³"éJÁ‚ŠÒ;Ò¤7$$ôƦn¶ß2ï‡]R7aw ï?ç—/\îÎÎÎçxÍÜÙy%{]d}ZÉ—Ié&5\Rrž,þ~Yj^ZX󠨉ú{øüïâïaÆ£“·Î¼zìVÊ]^:Mp«ˆ„m×*¡É•&å.|ª<&¢š¸/t·Ú FŽçœx{Þñ¯5\ˆ¿ºéÈöËñ× 2)„`^ÌŒªoR„CˆçZ’°Ë+Ù—”»ÐÀ>õršŒaD€(/(øªÿxÄÿváÀŽ?œ‰»­ y€Ï‚^»`âG˧|ŒaXO阜[ObX®ëé4¡¥ûâ&þÏŠíúïèÍS+v¯¹XÅ ’>C% ŒaÁ¤VLùÄìÊ?X¾ÇTNñ. ðîbØ?ÇD"€Ü¢¼Beqqy ÃÀÀp©½XæéÒL,Õcéx„°ç,K$ )k{¥g BJPÿ;,ÇbNà¸%ŸåxžG|ý]EH‚¨­#lEY‘Z§.Q•ÕßšHH·òlÑ ü%e§,ùiÅoçöË€€ZR}0´sǽ_øÒ2 ·>C†ctvÉOÐÒãã¿v–ùëÑýWŽÜIŽË(Ê{ZªP—£ „');GG©½«—ŸÜoXäK1݆‰kq¹+_üê1¬^Ž—GÈ^,ñóðܱo·ÖÑ²Š•Y‡\M¸¹ò÷õŠR…½Ô~nÌŒþ½k¬–'yi‡¯¸œpãi‰ãØ®m»-¿@@ àØÍSöo*×i]ìgx«_»ž•]ݳþø•£õw!D„‡£{ÿÐ!QýÃ|‚­Â¢e®&\ßåØƒ'óË ËµªBe†ÕGª´ñ»¶æ¤íöwÇ©_m-(ÈZµ"hÕƒ»Øûñ4%4¾uiН \„Uã}xž×û¹½çã2íïß«ÇÖìÝp5ñ¯U ( À ¨:Ü<<,<Õ®U»­ó6v lWµ±+ÞØ}ð; …õ:5<ÚÇÃwòKãfyÝÍÁÅì»Eå%]ߘh!èõ^-Z_[sÒË¥™ñÏܽðõ-'âÎÔJ`ÀpŒá›…Ûg}=­ 3úÝþùO’€‚NïÜþêš“î®ÆÏŽ[ù毶?¿«ÏE‘´t`û^ï¾2»gxK†ôðõ“«~[såá dÐB@’€á€õ!ª]‹ð;›.Ù¢ÿʵªy›?üîø÷b™9êÅ —û|ýö—fÁ—SòKFáf§±š¤#Ža‚tÅ‘ÀÛÍnP£#O¥UÏÿöã͇·ÇP"I¯âàM'Bq 7Ç­xóâWÇäNî¯)!ˆh Å–Yz”‘—¶tÛâ=¬|céÈþfÖd~ú“¼ ÙA-ÉNO¸ûø—K³ìÂÜ¿[²ûü^V«¡(!Tj2õ…Wg}=1óQ~ΰw ¡èIVrRVJþ¬ë* –cŽ\þõÏ}ó_™]ñæýô‡ëöo¡¨r=´N®ŸÿæÀ‰u…ùG®ŸÌÍO¯ õù¥ê²WW¼‘ô\ðÃtlçnÎTå•üÆòå2ÌF²¼&µà 7»β^YÅ;“ó—!ÄØ6æsÓcÀhÝaØ‚Ñskƒ¯†8Iú¶ë9ºûˆç€ïaö9ERÑÁ‘»?ÜþÓÂ펮ÀèŸÑ_’»®ýtö·z³$< ór¿±WÖ^õÆÒ¯Jš«%8†ÛKì¦ôÿ뢩= ¾ÂÅ4¨cßY£Þ©T¤ 1+årÂúfÍ ûdÒ¢%bÿlW»†D)0©@‚,,Ê+ÇË 7‹‹ò+Ù­zlßWc¢7ðÍã/ãiÖûß~ ¼^ñxN(µŸØwLÿÑ<¼6Ú–™ž–ï$Àñ¢òb3#Éäð6t ÈüÒ}NÒ.ÒŒåÕ Vq¼ÆªFB}ƒ#C¢@Sþ¬QœáØ-û¿é0»w̧¯­?¸õìÝ‹éYÿÀ¼ºÚ;ï<*Š“ÿ$?£.Ë+–96i1Žÿ ¥éÎ2'Z@W⬊é‹ÏHª¤H9ÎõYtHdÿÑLTŸž°ùèëHm‚ŒOK`X†ªžwgy ² ‚2mœ-tD*ÊN8­ÔÄå•üîå<ÙòFÄBѲ‰ ‡?¾¯V•šÖN€HRV^rèü¾Cg£ìœ\훹4 ó îвMtpds7/g;§¿cj#Ûï@<À€ ó‹ Ž­kèÑ3Üïß)έË]Óô¥ªRST<çïá+Šÿüm>ºC[ªx~Ì[ ™É¹Åù>nÞÕ=°fV:ëçxUaù9Wiß§eÇ0 #²K~p³" ­ˆ!ú´íñóÂío~5C¡ÈZbAœ0f¥ƒ>· 377íÖý+ß)ñ ‰ÖiÀШ;µÞ®ž ‘ÏNŽ)‹Ëµ*'©C-ü1ƒ#_‚ÿ˜ðˆg9®ª»ßÌɽQZ®©ä³9¯Ÿ¨ÈÏ[d0\­,:tíDÇA‹ú«!êëF«®(7!厇a”Ö]X~ÚÚv†wxú«cÃûŒ&I4JSyÑÄPB Å¦?’Hx¿}ß71±c»½7ðtÜ…ÆœBž7iÕVA¼ÜÑþ{R=€k¯œFÁßé¸óyY©F’ ˆ0ÿPà8Kz·÷ÊCuZA&j‹c”­&˜Ô³œRF‡ñȾ8†w úvîúï~M„ÉÖ`ðü_ÉqÄW§d^I¸ù <)±‹z±ð×Ú/*BIœ()}z¥¾ŽMøKÌzd0Ö3òÈNbïî読]ÜV¿Ðâs×Oì»RMaxØ üŸÅÖ!E*ž× I¼‘z&—· ÍÊè1á-Ú+íH*»0—a ¢Â:eë‰4e SÇù¸{ן6ýJÏðn$-1…k8Îëu»Îíy¾ãHRAXŠ?^û,ÌAA )¡m}]³³¾JÔ" ]<&ðÖ†sœŠáË…”[E…Gz€¿1{¦ÑiJÕÊʵˆ")ó$AææÄ§'Ößà­”»ÛmR`Òé:Ík½GÓ/Ô)UàãæÝ¶ExÕBžÃ—ýX!@jî“üÂüzL(^ƒÆ«sÛ(BÑ­×_?YõY3‡1R:Äz/Cˆ¹JÙ:¯7»0÷ÀåÃ\-U—=÷e†c—ýòÕãŒD ž%rXÆÇÍ‹4Ë•TQ‰bôg“î<¾_Wƒ²S'¯š^V^b£·wõÝ}¼hB „cºŽ«D†M[7oýÁ­J²öû–ÙwùHÿFeæ§AYÿVØfà­AkKù1†ó<÷åÞƒ#_ªØH‹ã´§ãkI¹ ØÆ?M+#îñý˜¥2Ò€¶ îЧm÷®¡:‡DVlÒ©T{zí·Ïm9ºãÔ“•\RÐ-,ºn#Hzßoþ°ÅãçO~i¼c•ªtŽçö]>²h{ìã¬G@KÁ¸Ïà{}Ф`ï@xeRßW×Úš“ûÄ”Ì$)^=wýœŸÎþ:8r@¨O‡“»‹sæÓ¬¤ì”c×Ož¹uª¿Š þH’ÂC€Ãʵª’òÒæn^9©Ö«@úVüÕïOÿ:sÈÔÊ@XÖ/Gô“J—ˆcÖš–åÊŸm’@$a‡Y–ÓC-û嫌ÇÀÎ ÝMºu7þêZ©ƒ£ÄNî"ó vØ#ž Ë+.¸•—Wœ´êjÛ™ Ú¿°ûÖ«$ÅÊâw¿™¿zÿ7ƒ"Ã|ƒE´(13ùæ£Û é À²&ð€VÓ2°Ýü—gÁ‹)®.ŸŒ{Ú—Ó+ £òöÛ·ã¯H*¤„BJ ÑkY­xÌÖxWg׫ᯅÜ÷Þ“xcGêò"e‰¿‡Ï%Þ:_þöÕ1N2GÓ7vžŽã’r?¶Æ~" £# lÑ7@À )¹…ù¶£*ˆcB/Ç×0ŒD–"फÎÍrJ“'Šx{‘¥ÌŽaK^[ÑhÊc¡zÝGN }dx—?¾<úÎÐ7êG^wà¼ÑsÀ ¶JˆcA­léú{ìÏãzŽ4‹¡j¥ 8nùaVJ&}Àó –Êjl–¨Àâ±úwgVUåÍk£VB‹ü`óŠwV¹;»ƒZ  Œ+¡âe@U&IgzGJ‹7‘*އùÕ‰¿ÐæAmý[ƒ±†€¢.?¼áîè&qrÛ’}u;åÞ¥ת>s‘õ±·E¼…¢Çr}Ë•àÌ7øÆÝKuퟫWÿ|yéá'{µéVÅ&’r‡‘¥ê¿,ó" †+aØÀH£ñ ý%BëöãH„âq=Gë9ªHYœ˜õèZâ­GÙ©ù%…Ê£n¦ÒYæØ¢™DË6ƒ#}ܽ)‹¬±…郧 ë<èØ?Žß:]PT çX‰@èéêÕ5$jhçÍ]½êiÁÓYþõÌ•kölPtRàí3ü,>Ã4@î»qÆ—›nQ1©~ï•9ÍÝ*¿ë­“²Ùçnÿ â²`ôœç6(wòØ0cŦCߪõ©HúÞ˳<ê®óó—ûÆŽŸ?ÿåY%ê²ôüL£Ç#pÜ_î+I$ö0yõ;œFiª%e˜ˆ–mküºšçe)r:Íí—›Ÿtš/¦/×êµËv.Ú¦b ½¶S›îgW¨z¢™-ŠK«e²ñ燆<¯7:|¯ ”Çz:NhWšåXcM%I$a©É›¼úíŽî0ª¢×†¶ßr¹zÐÃë ‘ÐjzY£×Ösî›ÍŸ5Ââ¹'»5bg*$!óQÔì>*M¹Iy©ËÖ¾ûõÜÓª2¸5‰ioWÏÑCL&ñ§ãÎ÷ ï‘t4I¥d”¨J«y-¤³½8²tBˆ1‚+xºÊú7V(G$-Ò¡åà³ÌéÄm4d¾ëù,M ­_;S!î\¦*U˜ÀÇì]½ûGô®‘>0“™3ÃÁÅ8„¢ 7qœèÞM³A(ÊŠj_ …á˜À2&{æ 䣤+4É‹ Ë_wøâÊÓ·ÃK½ƒ¼kVý˜Á_‹f~‹Ç¿Œ0\Sª¸rwBïÑÕ/VðwȬ‚ ü œ¶¼¨„G‘ ¹ÜaLÓ¼þ÷…áØ…;–.úö )SFñ„HòÁËï`µ¸_ó‰áYÃÞì5´*Ò?œÙýRûž^Þ-+KB,žs³w©½QJ@:c`y]>Bˆmîü†€tnšÝÿ²¨´êÃ×Oô[0|åO+Lt Q´ê±½G×8ɳ>ü HÁÆ™+år_`ÙøÔ{÷Ó掘^o´p-胛·ª½£Üò2Ž×¸ÈúÉ^nšàÿ¬”ªÊíø´Û»†<æÂís U‚Ï kîôÅdóç+×YÒ¼Õö÷6I¥ .ßrüûI}Çøú‡YA„ SP‡Ú„*Ë—#°ˆS䑞¦¼[z|dó)X+565Ý^ %ªÒaK',ß±änÒ- ˆj‡R² Ž«ßúÜÛÕÓ:üÀ Ž}øp»ØE~òâÁ”Ü'Ÿ¾¶x,qž“9{¼Òm¸E­Kåyö¼ÓWyÄâ8(_BSžÿ‘±–ФUGà?¸Wퟗ?ï]¾tã$HíW+ác'ÖÏ^ór×:/zFFþyÑw¤@8kÓ }F÷Œêz‹ÁÐkc¢×y@¥{È!]ý&!!&Àm³´Çg¬‡Fõ‚µÔe`ÐŽìׄ?–c+·V™&u¹„–l·±þ¦Eçß¹ùÇÔU3>›Û§]÷ði]´šrx.¥dÐ9:¹ßÜp¶…ܯV|T—>NcHÃë®DˆEÀ¸Í÷vžò_î½—üva¿A§éÚiÞÈ/\%s£K–"§÷Âá©I·A$À1@R]Ûöø|òâîaëÿ¬¥÷/ÜOKøä§åkÞZvôÆ©9kgƒH\ŸöB ºu³×ÎaæJ…¼Ò=I¹‹ê9!¸Ï÷všÜ¤]^y˜‘´b÷êøŒGB°­ذNûµïeÉ%Ç©¤¢–±âŽþS“s'g¥«•4%ðoæìÕRBÛx‚Ó£ìÔø'´ŒÁÝÁ¹M@w[ŽUÕô ™‚¼[V$»4zmRVŠŸGskOWy’—®Ök[û@bV2Ã2ÁÞ”õw€1“”™’ù4›¦>>-šùÙÊ ÄÌG XŽ õ õ ª³¨ Ù$wRï7½hàTí¯ÙjjDFA¶ÙO”¿z>!ìBbx¿s -Ï'„$æ~¨còPcKaYÑÔ5³ðN Р#@'xùó)ÇYÛ”ž1,ܹL:Lnl¢ ÅÄð_.쳡W[}‘°jïÆŠ'?žÙ ‘°vÿfk›j3³;1ØõjÂÍáKÆC/t#/Ü¿bm#·Rîõù`(ô  @ÐCÜ'}õ¶¢¬ÐÚvr sG.›½D  ÐCóéÄüâ³/Ûxë_»€Öß}°iÌg“•ÊâÊ &:MDx—çomîf†.),ÿ39 B| &!–CZ©0ÄÏõmW»‡’ݵrÇî!í}ÃN,MÍK¿Ÿøánõîªå¿­]±õc°sˆúš·›ç¤;7n™ðùT±ýÀ}¬j*»0pÈRäT<)./tÖç™Xžãtš‘K'äg&·ŠnèÕÂZã0jɸŒ”‡Ám;z¶à)þê¿~óÖÀ×\B¬H;1,óúÚ9'Oïñ Þy0øã7O8ò£Ö ;»ËŒJnˆ^9zó”}Œ7ôÃ'è-îøN¯"e‰y ¤.Ó(Âñïsrƒ¼[Ÿý²jý¡­§ãÎ+ÊŠ\ìœlàM.?¼^ž: Û°É}ÇŸˆ„ôÊ©±.^-î>‰¯ªÉþqAÀñŸLXðÞÈ·íDR«Ý>–9vó”ÔÃ+vüüŠýbAÞ-tècí§ã΃VÓu¨“ÌQQV¤(+r”9 é<xîüý+µßoè­»ƒ#û_~`òªé)îüzvOLçÁ‚:TãYErÞ–+#pB,‡t.’ÑanöCÜí†Zu˜©Í²rj¬Z«:~ýäÜO§ƒƒXîêÙ¾eÛÅtjaU;%ªRP±íZW}è,s õ ¾M¥Óü[èã‘xJ¿±¶}üiYa©ZéfïR©¶%’_üH|Ç©ŸwÛc<2Çp¥V<¤å§7>þ :¸ã‰Ï÷½¹nöŸ—Ž Z4òçvŒ¨ô„ÊSJí·@´ÀÓIÚÃIÒÙIÒ³i#ºmâé"?»ëFÒí¿Râî¦Þ?yûܱs{®&þuiõ‰Pkîu¡HP¬ªyŽB¡²!·r¯¾qÛQãœ3Ž0Ljë‚R€cËs ËRdƒ A ¾¹«——K³g‡‘"’ ±®]@øß‚?ûýô·v.[·kù ùÃ/m<ÛõÙ6Gi—PÏu€áaK‘À—Äeÿ–’ˆ Šˆ Š0š›±+ÞØ·÷Ç;©÷¬Â_°w áêtö¯3y%òg÷(¸u6ññOwïr_«ú#I€‡ª ÙÀ˜Ô´ â,s û%§%^N¸Þ+¼kCúî €züºðÛª‡–p¼ùõÙh·Þ‹…¢µÓ¿èÚº³¢0ÏûÙõÉ øŠ¾ð¯Ê·Ïíüãçûv í$¡Å—^¿zh°–ÿëØ®O‡^§Ní‹ùôµÅcßoí|ìæ©¥?­à•Ê÷f¼-Xç*u Z¸çâˆmä~8Ž?ÌH ðz|pcÀkﮜùÖº9ŸOù¸KH”F¯Ýyê焌Gß¼³Êx׫…òJ·á+~[¿÷]8ŽÏ1ÝßÃ’‰eu5úéß…ö}$Ø@g|  ô‘B4ô[4RQj5¹•’ó$lZè‚A?;l 3ôA7bâW3µzõT¢~êºÙЀÞbèïý ¿#t§VíÙhmS¡oEC_ÙÓR…ÍC¤ÑkǯœúJñ.0Ðz  ~;õžµM¹þ‡Ã°fЃ—ð.xoñø/§Õõ2±dÉ’ÿ÷IžÎÁ‘-‚Y©€öppiߪýÇ“/™°Ð¡ê%¶–‰“ÌqLg¹Ú uI;†E/{cÙ‚WfٰLJÀ‰}|Zñ!ŠäNr'w¹½sŸ}Ûø[wÀð½'eÙľc”^5EC¢^ò÷ Rêµ´DnïÒ¥m÷¯çmˆj[yƒA WÀð®ÃDR;=˸;8{عtëÔ³³nKþ­Iš¤ÑLÓ4É¿(ÿ7€•.cK\òIEND®B`‚spring-security-2.0.7.RELEASE/docs/reference/resources/images/BasicAclProvider.gif0000644000000000000000000002330111766764657024674 0ustar GIF89avóïïïÛÛÛæææÿÿÿÈÈÈ´´´ÑÑѵµµ!ù,vþÈI«½8ëÍ»ÿ`(Ždižhª®lë¾p,Ïtmßx®ï|ïÿÀ pH,ȤrÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL–Îè´zÍn»ßð¸|N¯Û‚AyÏï ƒty~‡6‹ŒŽ‘’“”•–—˜™™ˆŸ ¡*Šš¥¦§¨šœž¢­)¤©±²³´µŒ®»¼½f¶ÀÁ´¸º¾Æ°ÂÊË̦ÅÇÒÓbÉÍרÏÑÔÝÖÙáâÁÛÞæçUàãë²åèÓêìòó–îï÷øGñôü•öù¼öõHïÀƒs$Èp‘Á„ 6œxí!Ä‹WH¤ÈÏbF>þÙÅ“’c#½©\ÇÐÇ.%QôGåË11…Y#5sRÎ[Ž~³¹K¨IH«nr1Š4¨ÃH î´ETé¦í’ªmkWž°Ô8ôÚõ¤Ö³óª¶ÂzôV.«ZØŽ5ËÍX°·ÒÜÍK—¯ßvÐàö‘{jêɧÚóTì4±ãŇ#¯S+ŠðQÊ‚•È5\—ñcÏ?;æJ:æÌW,;Cë²^Ñ_ç%K¶¬¼ÓŸTsĺáÚ´[ßu=[öð¿¶së F·³ÆÄa  ¹ôèÛ»9ŸÈ›ùŸZ†£WŸ.¾±õXݽ?Ù>¬5Xñvçß{†éÕû¸Ùõ{÷´þÅßIõéS[6“H šV L Ø`) Bˆ„„Ò·Ü1LõäS6Zx†^¢ˆDX"~rHSPQ"•y’œˆâ *®èS‹7R‘£Žñè‹@À…µWlɉ…drL¹ã†=¦dABF ÅSbå5ÒHyÆ})Ýud¸¥•@`™å-U¢Ù„škŠcc5>±&æ{Ñ!¹S|MÙ¦›<À¹æœ€*ç¡5þé IÐ ãar–è™…î h–„Vš¢œ¥èZ2¹w¤šÕá§šÖpé”™¦Šc§°jƒj(«V4««1Ôªc«¸Â k¬àÝš°föº±Ìðjl ¿þ"‹ž°ˆ4«Œ²Ër í„ÔVûÊ0¯c™]†kªP?f—³²Rª­¯5òù¡¸M}U›dPÍûî&Ю»é,àŒw¯‰à†9ÚOåæëǵä¬/ ûjÃ?Bäyßâ«î–¶7®WNƦˆÃÀ]œÇ¤ˆ×S ‡õ›Â :k.Æ@,[|v©|˜þ깟#Uê‘òAÅ2Ì.X¦dy&†4¤‚,²pK?{1¨.M42íº«ô£Õ!}4˜9‡æõ¤WǯĊÑÜèÖòçïÉ]Ó<6ž;c5uwÙÈ<0Çyº©ÀsG¬6×ZË÷F£=fád:-]Ï Ý õàþüîMgÕS/>‚ßSžçØk×µ£ ݹçìòûZÜ6Ïåð^áyøßÿ<°©uS¨yySõ;ë¿Ôkrîqc>ò×Q.òñÁN6ñ£‹éðW¡û2ÑÁo2ÎöÔ[нõõ`ïEL·í=½…™ïùøõLæ~øÀOþ“Þ”ä¼ã³?'5ýÖ €µî'¼Õp[\ø¬ ¿ç…¦yò±Ý|’’V* °_Mæw@ñ%PÍ(P…ÊTÈÔ RxêM*Ue.µ©X…iUµcЭVñªY +FÀÊU¨zµƒd«Z-ŠÎtæc¥PõeZ×úS¢ 4ƒ;Mê5ŸzÖ²±®€ '5)X¢“Ž…Ýh_ѺÅ.쯀 ¬]ÛŠÔlV•†-j\¯â؃.9 Ah#KÚÏq4¦f€ì_+KO ¦V± éli/Xʦ¶µ°iç:Û°†ö²Á¤j[iWÙÚÆ}Çhmþ ×åê•·½ímL »ÚêÁ™ÉMfv‘{Z˾»ÓÍmtÇK^lªç·ÃÅìdƒ Ýòº7¤ÛÞ4y©Ú¥BÖGë̯~[rË÷¢5¾çóoc•8-5 X…^ Ûë„n&ˆŽj„Qtß8aÅœð~4,Ý c˜Ã Fƒ\áÍy8X±œ«µÄx;qU¡±â-½8æ°ƒ$Í î÷Ç@ò:'ºçZ«oyuq@Fœ=9U ^L±1eLe‰¸ÈÝýna…‹Ø,w¬LÞ´rè%ÇQ¨ÌÃøæ«Ìf‡´“YJ.s…[ÔËŠ¸FŽìv:Ö¼ÿPPn± ZŸ>lþÕ6³Ù\a¾©—[;ØÌ¢¼áÕí[]ä¡x‰t©“"æPlÍzÛ£4³ˆŠgÛWÒ8ŽsDÝ2ªàŒ‡ÛãÛxf'NúÓ26Hž»Þ$L—Ñ\v-ŒïÁê&’£tÓ›£¬sŸÊÓ¸&4q‰KUêŠwÚ)-vD¾'*=¥MwK‘šŸí»c·­ózq‹QmӪܾ“òûêä?x¥¯‚†ë ÉlG(«Oÿû2µ) lT¿ÓÝÜSõ¶ám±N‡‹`ýf[¼r¢Ž~õ‘}4ñ[ÉÎì å ×§=ÕlŽ7›å*üÝ Ç„³塾zTŠÓjÆçý{òœËmž2þËEv%SÙÉ$>t{9dV,¬ïÉßt„s3å*7Ë¿ÕÃ'&Íê˜ÞaÎQ¶d—§iÑŠ S§8KÃéöº‰¤î¦–KïN‡ÃSÖ±î-R½-ŠÇÙzä"(k¸½êeOÓÒqÄ¡Á§Díå“÷âd&9M‹‰îtÏY¦»¾÷eÝpLÛ´_4ÃßÔ­GE¼9ïWz×%îäcíð’¼n =Ö¸‹žób^;™Ã>ö´Þø|ÆvxJ˜VžO»èñwkí åÔCûA mäOÓz̧é­|sD?Ê>ùœŒêçÏûÄÖþô´+~è÷~…àçfúïŠé͇?FoþNŸ{å'æzÖÏVù.«âô7ûÖo’ò/ƒsÊ‘}ùG,ÜKÁ"Ö¯ö4Kh¶Q3ÄG$ó~lpSqç%×·€2‚ –ÊçÇuÊys9Ô3b÷xlr03‚$8~´eC<Ø$Çk"Ç@ƒCBB·‡„/Øg<×°×-5¨€9Ø) h)È0;øƒ¢µhÇnw…#bfšæxK¨C_r:2Ø•ã)6ˆ188…›çƒB6‡DdTCXO͵n©qiAóz˜6#t»—6ô8»£>‚ȆR‡‡R…'ð†“qeQÅ…ìu[‘&p2` ÒâˆƈþTh‚(~v\ÞrIµkúðR¢+$â‰àŠœ‹ CŠ¢¨hwökq1R8´!tŒÂ8Œrðfe‹mN‡¿h øÔOÐÒ8ÔXh$‰>‚ŒïÃQŒØŒú±PŽâ8ŽäXŽæˆHDvŒÚçËGOÝx‹4–|Ú˜|FW~ìWCq‰Ó~üÈ?ûh€ª1JsäZ–¸e÷EGyוÙ§Eö ‘Yé1óŽÉˆ{pgGŒ7E“fÙ#ÿ8©g{$#hû³<§ÇwZW˜xÄCX™’¤¥Zó’^k§us×p‹ÇÌ:YþzëÃ’OFø@-(:2€TäW.EŒXIƘ”YEq-(” áx™wu‡ù8RÏhj¹–úôO\IW<釷“„…XwÈ1;´F•H”ÄöRàxŽ€˜ •ŽoÙT½('|‰\…¹˜Ð$z÷ȘiS‡™–IR“)n%y™œ]™‰ •Ù™¢Ù‘똘£yšãô™¶²™¨ÙšX¥š bš®9›”›É"›´™›†’ºÙ›!U¼é›ÂÉSZ¶ j¸9œÊy%Åi6Ç—œËšÑ˜ˆÇ+ªˆdC(Úi)Í)%¥Ù†µujØõ…^¶æ©*ÝéÁùˆz¨^§X\矹þ’žFpœÓ2<áYm–hpô)Ÿ–•ŠE‘ i‘:‘Š‘ y‘ z õÈpÖIjérð)gþ>ö9†"ôœ¬I[ôÕhqÆ¡ªJoA¢DøƒQ¢‹ç¡¨–:£m°•ÕП.Š\0š®–lù£@ÚE¢T 9 ¦˜£úr¢¶vm®ð—‚ù¤PzH„iQ j Œƒ£H ;êR´Y‘E:왥բ¤$é{%š  ª¢b SñdnʉÐéš4:§tZ§vºSªÉo"Y–ýqzšô%‹„ÚIÁ¿1/÷g€c|Æ$ö·L<*„AƒU¨˜Z6ª§þíÀ‡.ˆl†ˆqñFùÙ…äɤ4vp™ºªšjŠ:•aI—úVk‘j^J¡âY¡©Ê‹¬ú«Ò§‚ઓy̶¤ó)^ú ^üi©¬¬Ð*?zx›H~fwwù ÈŠ«¦¶RèÖ«š­âºšÂê˜!˜t"*§ãº®·9­±¥ðp§u𧕬-÷¦ìº—î œæº¯+jØxd š|zq3"ª$èª(¯g·€¥¸pSXs0Wt¯nª­,Ѝ K{0Ìè©e•šWk›€¸” Û:«ÖÚ”£â”{²íZ®Õ¨Ç¢²8˲k†Å:”#±;»‡ý:þL:ë¯x¥Wûò«ð³L˜­4«%6«v+(;4×ÙƒwU©+”¯^;c[´)KË;*·’™#eùé…ãyj žØ&Z_;·(ÛQ{«ÂG¶GHug»”i‹…whj§˜‡©Øk]K·ˆk7H[Y±}toPˆ°u«¥–6±}qˆ4yzµÚ?“»…ʺŸ·%¸¿v‰q;©™¸¨u‹‹r¦Ñ§÷p/"m”«·!,Hv¦ƒ+¡â W¼ZR}“ºÂ;zS[A÷Žê@k¨3ÈãºÄ;¶ÃjuºçmŸJ²ªà>ºÈ¬n+l¬Tw;¼»2´ÿ*‘ë“ç5Føu˱¡R½§þã¾Ë›» ±Œà[¿R*k2¹'U'y”'¿yÛ¸fë.˜wIkÎK”±µQöÛÀG·ºÛ¾4(•°!–À³Ë€5+°îèÀö[µã[yÙ¼£<)ƒzeÁ¹íÁe|ÈÉÂÆé¸ìµ œ´20¼ë¥¤þgÄO˜\Fn¹Äf¼WÅÇÇ–ljÇÒ5B›Ç{à¤QúH±ÔÊ‘D¯üŠÇ8®Ì8ÂÔ{w¤¹ã‚G©Êÿ‰¥ÌÄÆVÄ©KÆÑSÂܰŠÌºÆŒºÈ Sî HZ̸Ï|ÌtlvÀe,¢ŒÁÑrÍØ ÌÀh¸¸ÒÍx[Ìà<·Ñ¼|Z;¦ÕìÌéüµëüVØù†<§ˆ¼jñŒ¸óŒ¬¨-—¼É^¤ÉýIÁûœ¯ý¬\íi,¬ ˆô1޲c -ÏÙ,b -™Ú¤Ñâü›Ï•W(ÔüÑ ÑžeºIÛο;P& D(Ò!}v‹Æ¶Õ…Y×·jzÒ·D÷þÔB=ÔX™Ï"Øž¥¶«:jäL~AáÎ3½®ë*¥ª½mËZ Ù¬òTqPÕâ:ÕåÌ»GgLÍÒ¿Ô0ÿçÕT¬Ò‹¦Ú‹‡Ü»ÌmW#i­ÖѺÐk†>ÁÍv}×l̆)#|Ý×öú×Ò,TtÐ+æLرYÓãübÅØLkØ !׊ÙN$Åýè~%Å{;ȸ‹¯Ç˹øVy/â¿2Å} ¹ÿH$ª…¶V–Í%N„€çQÚ3x°eøÆñ;B»í¦x/XaÛ¿ÅzùÀ*HÔÄXÑGíÑ@Ó¨3yÀÿ–¹•3ÅŽŠ¼rl¹È#ANá²ßt;7{ºórÝ •œ‘ˆþè’p,yÒ]BÉ.Å[{A˜=”êK8–W†üÍu2†·àŸªÂóÝ>+²zƒ~Š×šaFýÜ'­Lxw)<Àd†¾´ ”>‘<9^y¸„>½r³†Ì•þ}ÜŠ¶Äœ*³M­?‹à}È‚4.à‚œßb¸ß–W½¾#>3×}uLyñÍà¾FË— Ý49Å„ˆ26gÀ#ssQž{²ˆMëwÆQ{}÷‡ÑˆV.*Xžå2+—·—áÔÍ<¬§{DÙ‚äa Ýñ¶Ñ[”ɉ_Ìc(®ƒø»žö­äN\oCç bç~Šç³±æŽÝnNÕ˜-Ù™jäò/»þ‘+Úu㇛­ç2ÊÜÍÝ_èìèÌæK1?Ž>ypÃM²ú#êóä°õ= þè¬~ä1âãÈ»3k@;Oþ´ÔKÀ}¶¼zAst)ßÌìà‰®×±>ÇÇ~>|[áŸqw!>ixˆ,w)n–ì[Éì¿<ß ä¼ÞàÎë4¸u3â’ ‚ËÎ8ï¼íÜžƒ®í—;Î^ícçs¦ó“>®ß\•O×ÌîþîíŽ+¸Cª':TŽë€&ˆ±“Ûv÷äi>EñîTßÄœ~ñŸñ+ñàco¼·î9»èˆÐ]ò&ÿE}ò*¿òÑxÐ_n:ñ£hf*®wògéáÝ·:Û ðþÐýó@HôD_ôæèÜÏç³Ì>Tr.í;ŸÙÊa“פô‹2ïÒýsyTâ@cÝNË’g®$ˆíþÓVŸA"ÆwjÓß§L¬~¿î…öiO¿ŸlÍrªæA7'„ÂŽ ÷’7ëTýÔw÷„üï6ìåN†? ¿uGø..1‡ßBkŸÈ_¿¨}ì¶ç´‰¸ä™Oå¯Â2?u”_ù§Ûâloh$!ùä¨/CyÏmÖú ?o°û‹}½·oµO^Q¡û—¿ôªßa{ú»¯ÀŠõz6È?ü‹¢ñtÈñ¥õâ½*ý@Fýë°Ú¯g±o$ÏòZ”òâ¿E.þOÛÆ®aÖ¯b>oôCoô’äéèÏüãµþ‡_õNÿžùýoòÓJ®ÿä¤Õ^œõæÝ0GÒ J4UW¶u_8–ç, î“Öwž´o`P8$GdR¹L‡^T:¥îrUlV»åvu?àÕ;&[ÀLtZ½fÐr\>‰éw|^Ÿ?ãö«6ÁAÂBœ'ÀDÅ)»EÇGÈHŒ>?IËJCÍMN‚·KÐÐFÑRÓSžÌJTQÕÎWX´OVZHÒZÜ\ÝI·]Iר`á¡Y_c¹Ûcåå_¤dæ9àáéàbèkªgìmn2iín.ijrNëpôðtöö˜øxùywïù{ü|ý}þþ~ÿ€ù À©WpÄ:ƒ \XF@$N¤XÑâEŒ5näØÑ£F4$Y£äI”&Rn àÀK˜1eΤYÓæMœ9uîÌ)ŠW†:Ô¨»¢G•ª8ñ@Ò¢v’.Gժ©Wµjp*¡«Ó®OÁzÏ«˜°a·ÆÉºÖ-«¶o×J`ö)Y AñâÕ›·B\¹2&ipá¥i¯ü”WwìÝ½Ïæ=Œ˜EeË™ùhæì×sSºû¢ý[º³̧UwI½úèb°võÒ+ëÚ›mÜ‹ZçæÝËnßÁ]ŽR­ÉâU“/WÎüôñ Äw>Ý:ò뜡{ÎÞ£zþwðßÁ?²yô+ʧo·}}÷÷ì…Ç—î8}ëøëçÖ¿Ÿ›Úþ– Ð?Õ$оS00ÁÌd{‹ðÁÀ&¤Ð—Ç.ÄDC -äPÆ>¤NÄ=$—íNÜKņrñEc”ñ`mFsÔqGk¼ƒG ƒrH"‹4òH$“TrÉ!},cœr¢$€FGJ,³t¦Êf´ôòK0ÃsL2ËÄË'ÍT“˜X[óMMhÓ08ë´óN<óÔ3 9 Ê=§9ç·@ %bPE5tQFuôÑCIÒr͆Ò=-DQL;õôSPÉÑ4 NCUcÔ(J55JTõþPuUXc•uVO$õ†Ö8mE ×1[åƒW`ƒÖS_¶b¿8VËdéxuYh£•V˜f½›ž0ø<˜æ)âÙmu%ULUÆ×Ëj‘™v]O¾m‚]x—H76ÀxÖðÅá]sÄ%´R!ºuwÛzfÕßDãŵu¦à ÎU8Ðy•…8b¼ÍØÞ0ÎÈ7bŽÛ [O°'Ûz¾”’3Fùä’»µWž;ùf›YVyÓ‰cm¹ä—I†¹ea:g—‘î9ÔŠi8×膣ÞWd©§®ºh«³~zg)$f‚aƒ©ÎZl‘_lŒåz¯—†m³É¾:ì¹ÓFÙíOþ›ž¡íºûšæ²ÇN{î­ý¬Ë4Bã…eC¾zè©cŽ|ã™qVÛpÝðfºñ¸£†¼ìÏ;&šsÍó^» p?{õÀAg’¾[çS\Å-6ÊrŽUº_ï]nÁ'—ÚÓ-T´cÜ÷Öá>¾S½»Vu¹‰½ù¤©Üs×§ÔUq¾Î ñë"÷l™ä¶ ‰ÞÍçg}¼æê׿>~Y߇¡}yÏ÷ÞðÚ…O,gùÊlnÁ¿ãéo Ä_˜©âKTaò¢BÓ²€o€‹{ห†P„È‹`×âW-³Ø¥65 5÷ÁqP†3l /s¶ .Ä› þQGC 1O>d 1— ´Ñ9Œ†øÄ^1‰L¢¢‘愺 @1RGLµøE0~KŠôJàó30Q‚adc7¡F œð”‘ UX–;ÎÑ1n„cªÜøG@"kŒKà uˆÆ/öÑZdd#—ÈE’VÈb™ GfR“a0äÞŒˆÅ¼ð±“^ðâ&M)I¶|’fx·D²»= {J¨Z,.IÆSÊÂhs/5¶¯Ér—¹|ã(ß¡Jï´°˜Ç„ÌYò+–­4效)‹ijK_ó[ÿ|ùÌkâ–u@æ’áBff¯aV³^öŽv²™UŽ~ðŒ, þ1N§…š šÉ”–Σ‘ínÛ‹'ûþ)´ÚOŸ´¬¦:ʹ·Q˜£sÁS^E™;t64’ Ýà²åLà]t{!µ(I§YKŽºA£:|è¿â4ÒåMT{©çhŠÑe®Ô¥)?e¼z®¨‘K_E?·Î‚ ”§[Låóðɉ^´¦@-iò|—ÑI²m©½dݾêfRÙ1S¨`µª@¿ºÕ€éT=-ýaœèKBí~õ'ý$W=í“O•Z‰5xÒôo =½š>Á6©»Œk)ÙÈWê°ueor¬7û•UWùU³’Ýè Õz·É‹ÝßfMëYÌf£Š«’cøþØÏ®ñ´³i7ðˆ|D·»åmo}{ i¢L-*K[äʶh Oœû\èFWº7qÒp-[&W»ÑZn‰Xû]ðÞõ™Ûny‡ÕÝáö·ëeooÐ^øJ$¸V²…yí ,ô¨¹Óåo¡ÿ&Õ}Äqï{à(—EHßküàUåwÁ¶°R a KIÂvÄb¨rá ‡ør.‰Wb§&ñ¦è`ǘbØm±)<\¾” XÆ;'kLî4Ø8<&rXüãÙD.r“Õtd$#ƒ|B.±“­œà(38ÈT&‰Ž¯üebø8ËщÁ|fþ,AyÌ" o›Ýüf8ÇYÎs®âx×|g‡¢YÏ,³3žý\Ä=º}þ3„®âeA;YÍ…&å¡ýèË2:K¶¢!ÍãEKz޾t§ÿ§éc`°Â‰ñt©=(fPïoÊ8§V]K›ZÄ™NutЛÉ8f4x Ê­u—‰éKQ®äê/IËaöÔaÅöè±}ªgËZ ®5j¦¼ëϬÛ£æò¤ÅÙL÷qS©Ê–æÓÄ=Öe“ûÛÒvª«Í_óE…²‰Œ®q혅ÈóËW?‰ú³¿¥àk'ìúÙoŽÁm±u h»H7î»–z“s\ÉîSSûÝÖÎvƒ±-j þRÚ¸RªÃãöÑ’SϦ7]]¹šmr™ªœGmy61VRŒzãd& Ã7Ç;šy–]y÷NU˜ž<æ^íéÑǵ˜¦œézºòr>í3CätëÒÚU˜×Òê^¨ÝP*ÖÄ2Oê0wØÕ~õŒg}[¯¯:ïGК%µžÏYò*Ns Áud£3™`Ëβ<ð±i7ÛyW¸Ç]î¡æô2‡XC›G^Ãîžü“*oy;Åúž™×üÁ4ÞùJ¾ôÒ¦5ê§#úÕk·õ®gìcÜÙÓ>9¶¿ýls¯ûùôžõœ>Ç?,|Yÿ¾ø R=ò!­üå—€îLv¾§¡}†Xþ…÷ÕGëõ±_‡æs?ÐÞÍo$óLüÏ'¾†¶^áv1ÚÜܦ,÷.<@5ÿCåjÓåÚÍoÀb{¦`›?0#¿Ýc¤>é°ù+u7¥Ã¦h²?ª3˜m©{Á?Ë'z¿…BÀâðÀ`A½{¼ƒK~C¡B¬ÃÂ<ÂË»ûc;”SAг+}Û7S¨€s¸ÿk<£³8 ' ¾@"A’éß9»$lB²Òš¦{»ªrÂ)´'bx¶»²" Ž!ä$¬Ÿ¢›)€ Šz2$+À#œoIº2$©3ôÅSà D»®¿ö».\˜;¼¡ŠÀ$»¬C,Ô?©r@þ’;D*\š›ÃA|´-ô<¤•/„AÃó7ɉ'}ÃĹ*ÁÊáÄùù©îÑ@ºz¥MÜÄN4ÅODAÇ»B´+;<=?«¿ö)*CD7Ê9)oržÌ¿=\«VúÅ/1Û³Âê{D q[ô  ÅcKF~ÑÅþ[FN‚EøF· Æ ÂFiŒ=cä |Aªƒc¬ «D¸„$¬»ó§¸#j´¦õK´nä^*»)Ã* Ä|ìÇ«R©x´®y´zÄ \,ô‰CVTB LHBtC…|éE@ÈWt½ƒtB™Z;ùCAÌG@¤Á´ ÈβÈ3+HÛÅ[ìCÅ¢œTþ,RÄAS´ODŸ¼j»I4I4CI׈Äh¤%Ñ ’|-1?%Œó;ÔÖZÑET;½ÒñP¯øŠTITJE€ùjJFÅ4Gý0OýTP Õ—H¿?ÔLuÏMý>o`N`æB` ÔJ` ž` ®` ¾` Î` Þ`ùŠ?þNUa.a>aNa^a0ù`Žaža†á;spring-security-2.0.7.RELEASE/docs/reference/resources/images/logo.gif0000644000000000000000000002132711766764657022466 0ustar GIF89aØ÷ÿÿÿ33™³³Ù‹–ª*-::œÆÇ¶™ ‘IdKVLFF£ÆÇÂojshvv»æçó¸ÇÊØØì««ÕåæÌ3QˆŽ¤«¤åæäššÌkkµäæÖ,0-x…7LQ÷øèGZnnUKO8‚‚Ávn(¿Á¯ÄÄâRkkº½·UUªøøÙWlr–š…ľª°§hyÖÕºUXkjíæ¼ÅĪ‹”—:H1––ÊØÛØ£ªfjóóù5IËËåt•¤(Cµ¸™ÞáÍ”››òëÃZcW›¢£y„…i~äÚ²ÄÉÐUpƒxLŠŠÄu‚Yh%ux6W[tâàă¥¦­±¬³¸OdÌÎÈ%iz©­œ[[­quÊÓÖ±´¡!(#óóðF]jùùü¥¦‡»½ª:=7ÜÝÂG{‚ 3PiZlÓÉšÓÔÁöñ˺½¤‚‹fz§šv66›ùúñ6{xmz~ƒŽ”˜¶·+57-(ÒǨ\x’‡]x‡–‡ª±`„”pÛÝȤª² ¹¾Â oZcpi?ðïÒüüý ^r^ríîç¦ÀÁ™»ÃìíõYY´¹ª'D©­” \lüüüÚѪ@>¸°“Ìμ1o|×ÙÃHD›´ª°µ¯gu;=Ÿ¦š dsýýù¶±ˆ%B\º´¢;feìîÝ_Z0 k|Ž®¬dzOcw¢ Ø×ͧ±Ì¨”Ng•ŽÚÖ¿ÿÿþaa°ÖÚÉ ^^@^rš{œ‰þþý mq=??ŸOO§þþÿ\^DÏÐÄúþÿþþþ.OþÿÿNmÈ Rc Tjýþü!/1÷øöĵwôùþúü÷OQýýþVu`ƒúûúÌÌ®þÿþ;Q+ п„—Ÿ€!SK‘´¼Õàñ ^~»Éêa‘ÑÑçÁºª!ù,ØÿH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»<­ùºó¡ï˜Sc>¬óõ /Ts|‡Z̘B•*6 ûÏðR_FQ¨QCI¬J•~½PR¤F%Jª 6æ›å¢˜W©ô¢NKMšã KT!ϱœ)I³Ýë Ö2©²HÈ,3.ÂÐ 4ä­{"Øû uâ§Âÿ﹎çX6þ™i ÃÜA ””¸ôµgÎ8¿óΨ"±¼`€ˆÐÄoJüRH!¿ËÙ9@öUá ÑìÇßMþÕPÉ?´s"L"Ë$(CŒ(¹5q‰(²8QÏoœ1·'clXSfƒ:ˆÀ1Ü„p‰m þ2K à& MÄRCpbÃ"CT¦cLw˜÷áè¡‹u(2K%Îl0ÄjÊPnÌØ3å(Cðné’qTñ ÛœBoG*²9´Î/4Є=¤QÉ@#6 ËPœðC 2Âþ(U^5üƒ„*c8@L¡/ä©Ð:Î4ÿÀ i¦)£@i$ Ô +À õ°@$e qıˆ `à@e΢Œ– =ã }E,§Œ8(ñcP'øÀ•ñÃ@")ç  Ê@ª.$ê¶ã?ï"õA²i(€D pS¦ùRG:¥Q È ƒP# AÙ䫊âfAÛÀ¡J Mvd€í ²@6Å5jHx€Žˆ\¢H0®BôÂE°@b8ÜPªdS€^0@C#?@òD0Ä<@Ô‡°B;=dcGËEË Áœ£Â l4qó·UbOi"U(3ôOWkÿ@X«À »õklr¨?x ¶Ødµ/ £ˆG.õpcæ½ðF¶œˆ€è TâÚ˜l$eˆ­®@aoýÀ#äPtÐø×amTy,|È9‘ˆÁA³t#Eð¼0% . €@¥%vh ýTM÷ÛüƇ4ȃ|ÿÀó¹Qg³À zQÏ%³˜`\EÃØG£Pœ`†!((Só›@§vœÀc^XÁê~à±LL8É`2÷ùNrq`ÁŒà9 @uøÜ("ƒXÄa¨° [¬'xB¨ dà]x4ÿ4A ˆ€Æ€HœÀWC)|˜»¡´ãlwƒnÀ6àï€G%²5 »p´È×U~@Ä p¯júŠ"Œ€ˆBú»È\`A†€ -\ƒŒ,Úȧ\Â; 7À‚,0‹‡Y¤6x7¤'†4,Â’z*É(âðÐ!A€¢¨ƒ–W‘!¼!Y~”! (`ƒœ…$èÙùp„^ ¶ŒH;^@FûÍp2+o sŒ’g¨Ç<ж0#Êx% :`‹Ð3q™¬8ˆÀ?3PöW1–fhÒ@PŽó#ë(§ ÄÀÿ1”  °'E”¡„@z  ”!Î{v„Eè"Ž€'°è Ãã01ü‘†U¨C7r‡ÿ± høD=Dp @Üp"p¨Aëȇé¢ 5H;~OÃ]a× †JÔ¼N ˜ÀFð@€ N$*$vJTôQµ¨þ€D ZTH¨¢¨`}bT‡ºÕóµŠ$PFN‹³E£CÒ Ò‚@@kâòÕ–€ØÖWä@ÆQ€Ãf£|É@`ŸÐ:q€uö²ñ„­@²âúéa ¶Xay2 %˜†¼Ä®p†0ÿlAÊÐÁ)ÐAȇlc=«ú€Œì<ˆ*;Ú_6³MìÔš€D6º•õÕe³ÛÜ\7´¦¥îÉ À=_Y·kÚ=*Nž±ŽS8†Ñè'lÁ NÀ¡Ý´ä4!C¨ëL0\, aiZˆë«l@Ãc¾ò®aK®ëY æàSAë+Êfv»Ð…°¯ì*@´â])˜ëÝé{» :N±N¬‰C À{ç ‡-tƒ[òU ‚@³ ¤ˆGD‡1P7]dB\ܽCžì¹š"4ʇ^Äfí´Ÿ,wAlÙDLµa×ب^‰kÿÚ#×Õ|å…2|ϼ8¹Ã0†P_;&Çi°…-à0è@lˆr@ä-üw ÙŒ( <Ñ‚z(€‹àÜBÎì«b¹‘¤˜ðe Båªq:å3±‡-‹YËB µ¾ªš‰ €ðúJ‘ƒ@^qŽ&ÏÃ06àç½>& ÎHáÀì@B[ E7|ŒhDù¥ƒóа,8 N … ©•S“ë ÚÓÀ¶!jõžÚÔ•µ˜?ÜjíBÀñN³—bk¬5iœÀµaÄ™¬CM:þ²eÀlüÒBÚø…ƒD`@\Agø1«Í€\láRƒ”ªà1DÒ,ÿ0¶ Òe_£à…£7AÞ š«zÌõ@¾ØTGw ýƵ@Æ¡Ý@˜Ö1Ãn\[ÐÂx¸Ôia‚§ËÁѤ0^HûЋFt.\ d²&àà À†ï0€ 1äaWðkØeÖOÈ@rGs›Ï›ÕÜÅ;À}E¸Y=°BÏàˆ39—Àcφ²£ñtXž¸ \@¸à h7.a€@ÙÏ^ô¡‰œ °Ó¤© ZÐ ,4€&XùAæX;äîXíÒh>V£ê;«N/wû„mŸÖA/ˆá[1˜›ØÄôÃá`@Á$ÀÇÿ-æ€?A»è¸4à `t‘§}hF¢õÆÙÀ+G dAˆ0 ¶À½Õaâòp7a`Fsqsô¶|šõùbxü†xÁ\°0 ~f_ù%.`€ä@ ÆÐ 1Ð` (à€NÀ€0¹ÝøU p×”IT¢- @£ Báƒ'.UÀâR,hxw÷V¶ïbµ†Á{¾²Z, ÄV%ƒf.àF€Žjнеð ‰Ð¡`¨ÀnðV@ž€Ü`[ 0ÀÊ«w0ÿ@ RRû”}€Ã@ ×4‹uXÚjw7?pOEs'>4…÷wÊ÷aÐoÅâ…ÑWa£Öðp†Úw p ÂЉjP \R½P ¥ ZP (àqHjOˆ@‡v `h«— Yp5ÂypN`ðjÔfö)#ðýFfé5sùæwj†scöjù‹`H¼".+s*a†!nåÂð‹_’ÀŽð 1¥ð ý`ÈP äàn€(¨A4¶ÅPdõw70 q0ç|À )·8Pãk¤ðahÿUsñxª¨s9Wö8“ø(.‰§XŸ¶R–9÷u}p 1  P •   ‘ZP ¦™`™ ÏȦð YQ”À G°†fmGBpDpõC žõ&o6)sAt3yj>§f7‰…®kÝ3”·fep”I‰ ´°sà«`•›0•’`•)P )P  Qj{ Z€LÀnÀ+h>pB ð ŽÖ–D hX£€z!"f]è‰9by—KÓrãðeSh5Ñ5aÙЃÀŠŒ)oâ}ù8‘É“ÿiî5Ò†»0‡)0•ìÉž›)Ç0 àÓ @ðQPšùš1` P\myŸ[°·yyð s@CΠäæ?P^ˆ4¬˜Í…Aø&.Ú€¡¬¦;¥ # b<Ù‡G”)™*ŽA Ê0»€ð™9•›ðžñIÅÀPàP‘åPšâК¯É¯ð k€mIDV KÐ HpbУÀ }Ń@e‡å7Rè+*æ=âEk5Ù\K#jAkÏ·¢Yቦã9°0 U`Ê `‰ •8š£: ï™t@Çÿ APóÓ  â ®ùš¦ Î8 NpK@QŸ [`¥YðmhPÝ 1= â Ou¦ˆdDHÓ\#Зpg‡ÁG2qÚ˜?'bX”ƒ`e—ÃP:˜žP•PÒZ¨ð飊jZ~€ A0LP©–Š—úš €µð} [ zpVº`ð d0@¬ { á@# +à W‡`Š>äCÎ |=0AJÄDå" Û¯Kž«wÐ=tŠ„óã`°+›¤0¦x°(U ÓÖ«R­Å@ÓJ­ñÿy­  0 A€ “ ®åP À\@ ©ùÐXÀ @¯K°àyˆ™8Rñ à —Ùy°x­„Z³† ŸIà ;ëØà³•  @µÀ©¤Ikà çRÐF@¥øŠµ1i`ÍpÐ ŠJ¶Ò Ÿt`<+S€ =Ó0š  ^ ˜ÊT‚p!õà 7 µŸð |`G K`¸ a €!G°«@R³Ðš¨”+­t` –à àжœ;ÓÀ1 ùà" X€-ÿµŸbÀ µK爻1ðÅ à¨` ak•ˆº 5;­‹j (àj+=;¤Ï ® àT@È«‘A€* :Kð ‘@ p7  ¾ ¡&‹‹ òû=Â=Z ”Kn` Ÿk âÀ¶ØÀS`©â`½Œ¼µ È *PS}ûÀ˜°Fp7p¾,èc0 @Lü×Âf›$|¿Tð È0T°à:¤D®Ö‹¼–¨€ š 65%G0¾-°Ð A¬ŸPÄq LiX€ Æ À+ º@¼Šz 7k¼1€ Ë+ <ËÅÿL¤ãê×+Æ¥àÓ ¬p3$Ç‘0kŽ70z0}YÄÏð j”ÐVÐ LÜ< †°¨—‹¼º°¨ÇP R> ’\ì¼m[SPº,Æû@(ˆß{š0dP0@z ˜%±S=5?•/ƒÐU¹VUp§Í>T`/aUTªélU¡ÎÛà`µC!±(Cà° <ÀÄ4àÄ¡àǺ@énÐ  ðh›ËÇ@ì°¹-̹à³1<ÌÈË‚©ÐhpƒØd0-ÜDplÍY@5ZƒÇš€$ûi~³\*½4wÿJ]'ÐrŠ9Y,m¡h:JG ”àÍ@ _ÀÏ×`ÿÌ× ÐÔðäà ðšZàÚú¿Ø0_<Ñl TP `óà/k  í0@ÒŒr !Ó6­“¾Ò@·#§°XÀòiÍuÓÍåŽ, è5#aǬP|€ ªÌÄû|Ôn0ÒÐÏE- 3 n` t>àààl ÌÍ[©—*ŽLÀL@©Óà ÐÒCm€ ž0-pl=H ¡ì –1æÒ¶V=kv ‚ÍÛ"6íÀ×£%8½Šœþ b=-Ã` .À»ÀûÌØÚ­ÝÇÿàÊ nP  Z ¡ž­ÞA ³0©\`Ž`¯àÈý€ ž€m€”F­PÀ°¥G@¥zàÉO¥Væp׸ck+ x3ieÐ0¦Ú]^ =þÐrp¦XÀÝoÓ` $€øÐRp 4ÀŒ@ÒÙRð™Ž3à3àØà=kÕY½ j  1L´@`ÆÔ Ð š€ ÀÐ dÀ lMÍÖ¦qjžæ¡œÒ¦ “ÈGÓùiÉj”z=^ø«â"bxâ!)ŽÏ/ÎŽ€ ¬€]ãÒpË<0è@ÿî@Þ¹j˹’ð­š°Æ`V ŒZ`© P"T ˜0m@—CÛwYÍHæan€nqw]6Ì,ývné6ÀWÓÎõ]ûfwËæü(ºK $€Âp ÆNV Õ`3Ðììàì~ Ñ®è?îì€ à¶Ø ïÃZÀ›º©`€šTÚ0.·Ð˜ ¹@ÒwéÉH€Í!Ó/g&1‡´[Ř'æàÉ׫ja“ZS:á!¡»àN xàÄx`Õ` ÀÏÎÏ.íÏí›íAŠÞ³ °™Ê®©‘(À@¨° õÿ@ÐÀ° ‘€ ì 0°l¶Mï !wEw±aÞUXV†¦uðo®ë'£wošY+`24öë!AÊH€ _`<@ Ýp;`ÏñÍþãAî"Ï "¯³î°¤xÿšî@©¦ k Ð‡° ' ð 7À @ÛŽHBuN2¿GjÂ7“ï{À'¸>ðê‰ È=ÚÐX À\ ¤l% R°‡ý€¬` |>k/ Œ ñ~ÀÈ  ÀО ¤÷y_ \°¿0ó=  üЊ7p;ÈøÔlÛ¨®8Z H§ïˆùƒÿ½5›ßùpÞ\'ÚaM¯D\à ¼ >ðV°x°‚4€ÔHÍö3ÀÄŒ0ñ¸ïŽxÜ `RÐàA1Àü1åÉoüø©àïÓV¹`\8rä$zT YÒäI”)Uðç%ÀK˜JªÊ3´v'[Ú|)“d™6O”ÌÀóåŠv=j¾Ì¡Áæƒ0W¬¤ZõäB0΃JŠ¡k®"ëÆ-¡h¬eÄÈ‘”Pz¡µ`ŠàÁ‚QpùÃGÌ'ª&BÒ7æŒ09zy£ŒUÈËŒã©mPI§1SN®|P¡DmjøqÂ¥1£ÂÌñDjdØ(‡¹ cDLÿ?<¾è2Ä»ìYrZ^ÅHT¼CŒR(YÁc¬_¼;Ø•¤ÞœËê ¨Óç- ‘\Š/\ B䑨éIžÑ~Ä6 @*™#4I îßLJ9ÿgP˜†"©(˜F0)µ—±¦ (;J½ôN‘ƒ"œðã T,ÐeC² (0, ‡œJ-ÈÙ£T¬HE „˜ç0:˜#F"IoÂÑá0‚ï"n˜  ŒmÁžÈì% Ê’N°I¦'´E+ðÀ¥8d¡\{PÉÈÖ±\Ä +Èâ°¬Z"F=jI--ö4%?,°bD`tƒ SÈAÿ…?Z@@PRå†ñ`Ј—ñˆÐ¤HÑ„lÊdZÊïÀJÍFÕò?SA}L˜ù&;$03€©<…l.p 5 ‘‚ÞÈ¢‚‰(öØC TBY…>÷܃+úq$&ÒbP-¨ðJ¶@iŒNŽØ(H:"ò£ÆÐÕ*ì` €lúÁKR@^¦èµ—Õ.K…É‹ 2ÈA‚2Â<~³éáÖ\ߥêŽ{`E Oh#7 ¡Â,7¨ÁE‡\šIÚhÑ2%+Ñ7¸XÔþÜÔ!€pHêáÎR]M‘èDâª~X&mÆ ³ð]Õç¥_jÿúé¨?0_Pmš€03HØjFi•ààf‡9h!“PBéÅ,&´¨ÅŠfpqåhQ! ('5Ъ%p?Y“e²›xÙ݈,ï£NÑNi[ÒÀ$P£ sž>˜k£^`›°Ðæ¥ÏÍÖ|¥1P€#ðÃLA«î(úÁ.hQ.ñÙ¨A¥OA"(G lP =<ð€ =ü‰$r¹`‡ÆÛ—ò.?â±ÙSê¡^£ ÉZà|QcŸ'÷Käõ€¥L=€¯[ÏÌÀQi#}*±…BÐ 4 @`x jA"jì{â[‰^V<šéI ¨Pƒ'êáÿ€xÀXú@#" ]Ü$Ç‹# #š×SÒö@c^x€^ðB†0 n{+ûÄÃ&°Áqmü"wñxÁ/Ìð_3¸B6°ÁÂðÝņᗿl,>>à™so…Ë:Œx,Âg0Ž{ÜYÌâ–C‰ékƒ—ø ¬xÄbÌàF¤—«ø‘I.VQ%ñGð„ O`ÌÁ!$ ’Œ*ÿ Ï –dÍÉ9(ò‘‰'lÇN>½ˆŸC<àøAfJ{Økfó#8ü9|·»Þ•óè¬à0(x±1æ!Â> ß8“ªº I€¿d#†æÉ îu’ Tí%âÏKì ¨Uú([ ø£œÅ'?p Lpˆ™®# ¶ ì¼f:»ÚÎsönœ»Ûâ+Ð6Ï îÂm%¾Sø’QQtÁvìyàªã³€ LàuÐØ{Ÿ|îÙÈ@M^µmiß„ˆt0”JMÔúª 4°ìl< ¬wˆ‡nç»"×Ý…õâ ç\ñ¼ø°ƒ è¥ µ› TA5“˜ 8 —s³C‰¼@ x ‰¸ûŒR“ Ti½A û;«a°3¸Æû?}ëµ£;ÀT:L:¥ãØX˜©zYô)  032QBp”c4ùøš(\BŒ[¹Çp˜'2©=0‡ =˜x•à:-´xÃ<À7|C À@À0è†Sø³Z¶ ð<’ø'€œÐ— øÃÏPÕ±.j °2 HD@œDE,FIJ‚É-Ë€(2óº ¿2«0t‚6,­9\E8̵n؀ɲ0YœEØX‡aØÐr5£…n‚1@>¤EaÆôx†g FdLFe\FflFg|FhŒFiœFj¬Fk¼FlÌFmÜFnìFoüFp GqÇK ;spring-security-2.0.7.RELEASE/docs/reference/resources/images/ACLSecurity.gif0000644000000000000000000000771111766764657023656 0ustar GIF89aòòóïïïÛÛÛæææÿÿÿÈÈÈ´´´ÑÑѵµµ³³³!ù,òòþÈI«½8ëÍ»ÿ`(Ždižhª®lë¾p,Ïtmßx®ï|ïÿÀ pH,ȤrÉl:w¨tJ­Z¯Ø¬v› lܰxL.›Ïè´zÍn»ßpª× Øïø¼~Ïïûÿ€|`‡ˆ‰Š‹ŒŽ‘’“”•–wƒ…u—‘†ž¤¥¦§¨©ª«¦ ¢›¬±˜¯4œ²¸¹º»¼½§´t¾¿Á5·ÃÈÉÊËÌĵÇÍ’ÀÏ2ÑÒØÙÚÛËÔÂÜÞÆàäåæç—â×èê3ìíòóôæïñˆñù˜«÷1üê $°PÀý;h'§‚~îqxè ‰ ±Q$(È]£þÛ-4x,J?‚&Q>¼E¥aJ”x^ÂÄtÐâ Œ!•É|¹²§KšR\²,I4&ΜÈFF̳ñaç£6…ê4&SwÅl!-’ªW©_OV­z²ìÖmJ#ý:6(X¡P5j0+¼³äv²d+t,и}iÒÅË-­G«oý"V¬ØlÔºÕÎ{5qX¾–Ö<9›aFŒ}&v;n8»Ö:Ï mº-O¢GUëD ö9›.lËÞÍû6mÝ\i_ìM¼xÂÏ9q·n¼¹s^ÈC*gÁü¹õë©¢gœ¾¢:öïà+i?.üføóècGÈ]…÷ôðã÷Y?°}Š÷òóç§/Ð> üúþˆõøw€&ˆô(@w F(¡ ´”J2!–NyQP7a)üµÙ‡ý6 g‹YØÉB.GâŠ(Š5׋ÚT¸ÔZoåiÕÝÓbn4ZRŽ+ Öš^CÍXZØØf=¥ÄØSÞ©ÓápLž%•MÅÙ”9fyZdUN±™ˆ[vùI0WJ&f“f~Éååè–kh¾¹ˆ“‰…YŠ–U‰@›©ééÈ^™ÑIg¢ive¨"|V&£ŒwRµhŒ{PKëPÑ韒öh"M!š”–¾–䈣*d¢FÓ úc¡­ÂŠi­{¾Ú ~Þj®!Øj¤öd嫇À&{±ÁþU3+²ÊF»®[±¤´ØÖG-R6kBà†+î¸ä–kî¹è’Ê7Ë–‡„ÙÆ»Úº°àeà·ò拎+ìV뮋ú ³yóì³¼ŽÀ ׸mr´Úf‹_)ñ¬7¬ñ®K7è& ×&24﮲°§¼&™„Qs1É#[,4S¬òͽ<°Á!Sl²Â&Cƒóй°˜îÑTЫÁÌ3ããm¿²ê`=>u:yRx!ßþ3€4îøãG.ùäIùåþ˜g>Ç8¦ÍT)‘ÕYZ:¦J©\R¦ŽãèZ‹ö˜^­ùÍ¥‘a9$OµË{ïp?‘p£qM‰(£™ùIü¥r/uIÀßu£q‚¹háÙî~-A¾‡p*žhijó*5_äë¨Ö§áÆãyæÔ:–o< ~5¦¯õcŸý`¾Ÿ?ëÊ÷¿ÿôâ; øþô¼þÁÏ+òÛ¿8‡‰ûy`U¶« î‚Úm/€wº]ù”>/k{ Õd7>©DÏR¯{ßü¨¦8 œâ¸©]|O`ôsÏD^¸þ­8G™aEÚǰþg><Ì€‰ÆÄ‰°ÐM;Lâ–ØÄ*6䉿B¢þëeÅ.®‹×ĹèÅ2ÊŒÔ Ã…fÆ6®L½[#>ÜHÇC¡ÑrÄë¸1#R'Sä£ õqG€jó‘ÖÌRµ> k¸S¤Þ"8Gr­’D_1y™DRÒ“-q$ؤTÈ‹’ŒQCÞ"“—¼ý°“ú¨á­&éÊÜŠzžŒ%©,D8L>ï!¥¼É)BÑ /’çëàèB;eºŽtìÖwºà­%l•ê’I¤ A Ò.|ÞüI ÷= N3šÛü¦9/¥*¿]ã˜7,8'H•`æf˜l”^ðø2<}šƒ$  (ý÷' ÔŸ^ò'úÊÐî t–7äðþcÏåàsŽ£Ùà ÷f¡dùè™ÂÆH(esj"MTJc¸Ò‚¶¡¡Sh`*¸Pzé€`¡hdxG9îÏNEæAš7š„yÄKŸAªÔ†¦i¡F]jT X@™N”-ýãE!ˆÎR .¢ª 7¸¥ b(,HÑ#é̹Di¦l¦÷,hV%ɯTs%kìZW ¥YaÒÏzî ­ ,µdœMŠÍ†éËjwëCñ4Ö‹{¼Zô$ëÊ"í³  ­hGKZÑ*í=]#ÙÌf€Öšmn°U›kcK[·Á­¶¸ÍíÙf«ÛÞúö·À ®pÛÆÛáâ–·­M@\þk· ¤vŒ‹Ëœt§KÝêJNSš²®v·ËÝîz÷»à ¯xÇK^ÊmÏMì ”^õº÷½Ùk/|›ÀÞ‘Í÷¾øu‚|ó‹„úî—¿°1ß’ý—ÀNðL_3øÁžl„ð£ OøÂ~`†‡€± møÃ>0ˆ…©Ç›øÂ">qg—¦â'8Å.þVcLcþ¸ÆÚKŽwìÞó˜>þ±}ä!ãÏÈHf‘“™§jS³N©ùΆr™ì嘕ŒÏ{î3ž½þ`#·9fM£sœ-ì´‰Õ™Ðþ“g˜-úϾ t¤7-‚1¸Â2³Ø»8•hN›ú>§nrªW-iVOÙÕ°§¯<ëXºÖTƵ­ï¬ë]ûϽþµ°Áìa»ÊÅ>¶²'-ìd/›Ù¿vö³ÙÜìiW;ÚÖÆ¶¶³mki²´àÖÂyîpû~ÞÎcfEÒܯ»Fív`º}š~ øÝž9-º[Œïbv¾ý–†QËïzsVŠçØ¿·|â„ïláïux7ÎÓ‚ˆâ<”øl ¾„y¯Qãã¸zAžŒëÀãP¦%G3TË£®D&—w+ªrÄ(ß";T 8þæµ²09eµÔ…Ö¼åvz-~Ð¥Ðs!Õ+]— × ó›WT:>msNc¦uWWçê©u13½,Òaü†ª(©º½x1¹¹¦a²,êroCÅ©C%‰•²!ç§ÐFUXV“’µíriª 7ðM<ÚÏŠ~³äélw}8ý‚vr_è–ÄrWù€Oâ;›š'á=EÍ»£²®Õ/;¸Ã}žûˆ®÷NNï¹ù BŸñE–°ôêD{;·R ç&?ô¢+æh;wº‡3oKâÏ*ÎÎQ¢ñ=àýz;ƒK'~žîA«´œëþgY÷”äÃÀ~ÅUŒ~Ut>"ºWb‡]êåþô®ý9‹ÿ€Ùoðïg‘Ä¡~ˆÅç‡1Ö!€'wvà¡€O1Ïá€8ÇoåVS o÷ER¨kF€ça¡r1 g¥Æ)$(‚%8g–‚#ˆÐÁðÀ€ßao6ö~¼!»'ƒ ƒýe3ȃyÖpý‡_“€@hJ8˜ã‚6t„$&„_Þò¿¤W3KM…÷”„ È…ù|h&hø“D©cäW~DXþ”J < GKù”à—‘P9•%Æ`MI•‘v•ˆ•D)’dÆ•Ã&{JÄ”GIY` “'3Ÿòz-øx”×cgÙmGyiáW~tézByHZ—(––+g|†hôç–[Å—Ù3HI—•–ieY˜†Ù€©h—FjO3”¹”{é™y™´ö`›É™¹æ™ 9š8§ãb‘¤©”áx†ñ–šO¹š+®ù“°¹!Ð8›¶™µ)$ʈ›TÈ„ªáŽ¾Ù’ÀÉ}½9œ#Wœ“!œÈy“6†4ÎМgšHƒš@vw‹¥…º±zðw›Ô -@Ôš³Gƒ1VGvmužœÇ5ÇžÔ4þxHW{I5@¬ôðÙ_íˆq Ñu†×‰H}íY﹟ÄÔXþ©èTEv*fýy‹UÂÆ´xbg…¡Š%Ÿ jœàÉ¡:9¡âi/¡„ƒ…/Ç>‚%K,Úw%Ú.!*¢²–K>G†Og†ò¡Ëù/Ÿ š½DŠpÁAð¤?âä>ì$BÕG!<Ú2ò£@:É”7O•vbå·ç}1ê/d¥£¤R'‡_2x¢(ZSMj¢ÎB£Óx|“;gŽ}½ç÷nƒK/A}·úöì·ëyQçuþõŸ%¦5 ~Îi7›vÎ)6`óUPß&—\h Zg…¯@¨Â„yè‡$ #b„€XâŠûœx‚ŠþéV7.º#‹+Ö(Ý8öhŽŽ$ vߌVñ–ÚOòÁ£Ø’LF©T’8\UbËei\c^YƒQÉŠ”d†ÉŠØ”©æCN¦ à‘ûU˜Ÿ{±Õ‰‘˜>@¹&am¥çž€RvfVFæ—µ)xJ—_Þ9(JTŸ)E*é¥H>:Žx¤ÉùÞ¡ùÙ ž–a*)¥"YjêªG‘jàYí!ë–pÁˆªP¬îy«Dªæê«Vš¢Wâ®AþZ&±«ìA®þÎÐ+?Ⱥ¹¬ÑÞóì´«V‹Áµúhû·Ø‚Ô,š€n Þ ”㸄BWdŒï®ÄŸ}ì’«îo Í;–ŒbÁK œ˜¦+áºÁ–ꔿú¾û‰¹èl Ã/!̯ž Ek®Oq:¿ó×i¢ÕÅ`ƒ ¾õÝr"?—å¤õÚKÁÆJ–Èr—ØÉ4Gò£ài©á];ÃÜLÇ)ÜÖ¤¶y jœŸ*­ZÁ.ok_ÒL/M§ÓqêÜßmT_ÔÎ}“SˆVíÖµb-ô/D¯²öAeª¨Ù‹Z=šÖ@c§%†Vײbñ¶-XÚÝ4݆'\RÛ >Láh«-yÖ %Ž ¨þÐý- ‰Œß›“zê·wv -WéT¯¥¹ËŽúéÊÍ »Ê\jݳղŸíàÜé­¾BëÞÀÀŸëïä­âô‚-ƒ¼MQT\¼Olž˜h(c<‹¢üòß;C4IÌ÷kj•ÿ¯£ oðöœ#føð?(/G&«Ï§Ûêµðp³ y‚€B„ÿaË=B(º…ˆÚë„þut· Ý™Œ4¡‹]û6–6¼l gTCÓ°F'²ÁŠá‘â§Ç:ö‹Äã“›xÀ'Ú±w$Üaÿø¹âÊ]{„aÇDȯͱƒl$KÆ8'Q’ª $#‰ÉPrXòYd;É2MF“¤¼È'ؾ¦3†ÜÑ+8>!ÚÒ xËMî^z»˜âŒ¨2]9Ž:3¨ÂTVOÕÙII¶EÌQµrVm*VU–Ò£æÍ ¦d0Ù&< aí€&,§DþØ 1;­ë‡ä5 ê‰ÿü_]šªwÒui~½ç_kXOY“±Mìåø¹× î•°Tô¨.5v@÷yvƒnì£%– ÙÅ­B¹cZڲÞ:†…UK-ׄÊʼn¶K\ãgâ0Ë+Ú"N¶zó-^®”8àŠN¸Ž­lþcÜy5Woù:ml—Üš6­¿Ó¬ÉÝí¦èeÞ¯xé™!-¶±çm–›^ÉF¶ºîõÚ\‹´[ì&¯²€m¯Ìô›^º>Ö²ý­ eù Ùúº’˜Ømgà Z6nWÁíƒø&127ªµó"USö©0&j¹fåNÿ$¼µ’ÞN¨©ÅÍT %TÞ&d…(lCÌűê.©Ž†K†áྮ¾pÐ<|âý*Œ³+¯šd’…ÆÅqÕîx^ïvwÊRû\¶e€Ðo­&síÛж3£ÇmT=pX`){NÑh¿…´Kݨ{f¡˜O’ÉÛ³Ÿ Mg5ÝYþ˜.w4˜a6´;nÉèF;úÑ6Ìe»¼XS—†•«`½Ø‘ás3Ûì§d.!¢ê  @€ªWÍêV»úհ޵¬]m€ZÏúָε®wý]ûú×±®uªMìbÛ©ˆ ál6¹–qŒJS4GíIi‹c8€¶·Íín{ûÛà·¸ÇMîr›ûÜèw°ît»ûÝðŽ·¼ç½m›d1…ø.0~œ ÏÃZ’Ô®v©Iðw̹àKo¢ðK~›¯Àÿ¦cÀOq„Ïgx·øÎÊ?$¹Ç¤;n^ý·˜¹&§â›¸*Q®q„~÷˜-?¡]'΢o#¿|ä3Ï¿Ùâ¨óÜ/ÃñãÿùÑþÏßm‹C3áO1Ü¿ÿÆ·|ÿç=a¶gO€A7€ø¢…eÉ`€Ç Ø 8\ЀËw HmhZPˆÞ7vݧtKw}!˜‚*ø!p•h‚;‡‚+8ƒ4ø-v0èXƒ<؃ø—ƒ ±ƒ>8„D8jBX„I‚J$Ø[@hIØ„–1vLH…¿Ó‚T´-Ƥ…ò×uW×Më´!æ=Õ´z ¥?dXSˆ…o倲ׅÛç‚nHö`xÈY?÷rj$g›•‡_HQŠUsgØP†¨OvQ|GˆœA|u(w臒ø`{ˆq}Zøˆoè‚•W{ˆ‡þŸh…yFr›÷U·2˜vŠægyÎTŠ®¸Z¥w7—F+‡Wúm¨‰ïà…(^¡g¢‡º8‘øY1ä`Ÿ˜q}8‰Ì8þuz ²^hHF }–ã~RèˆÃ(ÅH‰ZU¦Œq†‰Û8WŠö÷t?7‚£G€ûaZÏÕ_<6r•cÓ•{ºÇXØÈ†ÚXŽ<ä‰ÁØ‹ȉþ¸zèT†Frv…Fx9ÐUªuS‡è_“‘"µ{ü(ƒÉ ¹¨q¶‘3Èq:åq%÷a]cVªÈвS¸·?(c’ãG;²pÅ1ý(’:¹“e&|Dw„v“ ““z¤ç@›V`¤Rúžû™Y.¹ à™oÑ‹Pš¥qj§Ñ@¥U`¥„šHjêIy‡VB—¨s vˆ ©c¶¨|Ö¨t1¨”Ê,þtú0—j==¿—Oä£ëçAZ.iú˜›*>DZ¥ª4UV7¢¡êMýs§õ4OšÚª&òª‡«CÕiµX’ÔpD“Ã5~!µ’R¥(°£S]êi<ªƒÄ7©Ó«é´”¶Å/ÜÚ”¢’ud¨Tfå÷¤`‘[’#ž`ÚX·7jW¤[ÖšªÛ¢¡=”¤~Æ™ýäšðu$Š¢¾B®Sà”ÒÕ¦d3yžŸÃõ±Sz9jaö°'Hfw»±p7wJi1‰’žé°»CV›7®ÀZ®R>Zõ¦N³^ û|ëêX3;;§Çš~I„—x>û³èÆ¡J"`+þ}zŸøÕA+À4=/Ûi¬õ[•iIF~5)µóÈ¥@ö’Õj]1X›øø *¡ïx´ŠZ牭8i¯» ¶èKlëƒ ·¦Ð—Så™\é@Kn«&ǹ8+;{»­êWaK5µô8¶Ru ÿ ?{ }ë«™·=¸&"°ŠI»q’Û<`Û¸Ä𭘪¹Ë´;BŸ{º¡[º|‹¯®ûº°KCúŠ—‘ G›ëµÛªô´˜¹»¬ ¹ªË'³+—½+B·{ÁëH¦Y¼Jû»œ›¼á¼Ǽ*K¹Ž@½„z¼’ ½®#½È˽¥”ºàËeÖëŽã ·â»O+®öD> þª³˜{,Þ‹•ç[HåKƒi¿b(=å4º}·½JªÚšz·Pùk$ü*À PþŠOb˜L;1¿P·›Àyµ†SŸÖR,ÉS'«yf,Ú›p<À›š¶êPÎ h(lf,<#Š¸Â™¹Q÷;•À‡ÁG@ÌÁ¬·,!¬V›i¨Øµ ‹T<¦b­5‹ä·UD¬Ä$ù/–v£¿²`@C¶Á:ú¦HŒb4F¬;B«—a»{ø‰°ùM[J²¡ÂÃìÃLú¥’µbÌ6ÆÐéS_JŸD«un:·‡’ àÅ0™zü{Nš¸±Y´&Ê*=¼„Z‹ÆÑg]ëÈh»l‹l¹k 6ñ8Uþ챟™ÉµE³¼|¼nt§˜ƒûqùå§ÏªÁ: ®ü¬ ‹Èk¬È;Ç›6ËyœŸ6)É´Œz·,àÐn”i¹„3Â)\G‰Œà‰cA¦c«XZ*™Ä2b]Üd6l¶×§\ºÅ†ÊÒH3:ÍK&VÖÁ¬mÃüÊÅ\1AúGÉü±-âÎ'ô<̱{Ïøi3l|œÌ€{Д™±oDZqgk·VÐÅ&lÝD ýЭ±;Áõ‹¾¦Ù³@›Ñ=oˆ·ÑýÑäöŇ½vúÎüù<wÒjUÑ-aÒ*–OøÒÂÒ½´Ï2íÃtxÓ§IÓ!Ë:­V^øþÓ/ÂÓÿ,Ô•ÔF­šDMq6ÔJ"€N=ÔKÍÔQít˜•U-ª åÀ œÀ-<ªÆ¢ÙäÕ]-Ö_½Õý{ˆ:¡A\ÕõtXÕZ®fí¿h}ÖiÍÀ|ý&U!¢}ØWÌÕ1L DÏ ××Ë‹Š}hÌŠÈš£©ì¬Ò²¸…W‡+Ù—mÙÍÊÙ¦ãUY“¬FÙÍa›Æ‚õxc»Ù¦Ý¬àÅ{X6×I}³t¬Wœ,¯0‹·wuWÒ‹y{ÊûÜ[c´êjDÑhÜTÊÚ Û£<Û ØŒ¢dÛBÛ|³°ø¨ÝveÚ §ÉkžÜ=Ÿà-3ŠSɸþsÞôÉÞ:JÈ"æÝÛ-ß%†}\÷ÝÔÔMÿhƒÂØØÚ-ŸºÌܱÔW³Ï7³Eß¼6+r‰9º ݱýÜè¼ßPQŒŸ•F y‰‘ØŒ³­¬Ô¨Ù >c2ÕÍ Jµ5&ÎÎü*þÉfkâ.^¶XKd(®¬ã?\ÎÞÁ± ¬á‚ÃØéè‹rýtü½ßBJÒ…Š˜ À@Ïõ6ÝD)Ýè‘™Œzø™HÝFêäâ<®~€mˆýÖW¾–HÞŽêøæìˆÝü™Ït^çvûæ8M‰™Ž ™Òzž±=è»ÆÐ„~èˆNè ­k½¦èŽ©çm é€Ñþ ]é–~阞éå¦3 -Ò’îŸêc*ç¢>¥~êª: ¨>E¤¾êN®¾I±îêS1ëöÒê¶~ÓS•ë(‚ë¼~Ò1Ê w>쌠æ(MìȞϞþë§dûj‚/ú*S= Îì—>Ï®t»+jÓ> yní 4—ƒÕ"æ€âÒà>iξK@XîÝî¨éÎêtÀî9èîïŽîñ® †Ùî±tæ®+>ï{9´T©#!IZÝŽïO(ûßU×ìÛÀŒHÖw}Í¿ðŽ?‡‘tÏàð·šÃ‡\À¼0¯¿À ð ?x*« ¶u¢N\ñz×g¯ž34,ñÍ'þó…]Â5™úò‡ºòÃZV;êT×Qµ•ÍTÐ*‹&þÙ­ cS/b¦gìÝï‹R™âƒÅ\Ü\œÚZ;RÿØgSõ7F¶XüÙ®:ôD_°Œw®½ Ùb«àoœÜ¿³ÁmŠ›æR r7Zß’ÛÕñ<÷v½¦y¿D{¨}ú74ÿö ÿD•Œø {´ê}ù šùÞÁàßÈãÞÁ-±Åº¯†cžb¹•°JVÞ$ëùમ ^£Éj÷œ*ù¬£.«ÍÆÞÎÛ¾úzŸàÞðŠDˆôl³û3Ùû›ïÛÃ?_Ý!³'i^ïö¸¿qÂá´\õ²ËŒãÙLöççc«}âÔþ|ãå<[4žíqú-©*Ü_­µäÉãÛœâY+ãF¨!¯‘Ÿýä¤Õ^ BæÝç€G²4O4U‰pu_8–ç9@ŽïkË`Óh`P8$G  —c6OhT:¥V­WlV»eú¸Ïò—ÍFå•Ì¢¬Ïox\>W¥1½o^¿ç÷ýÀÀ/A 7:ÄDE»ª0¼¶EÉIÊJ‘ƶÂBÎNÏOÐPщMÏCKÔÔ"̩ȊSUÙYZÖž‘ÒÑ]Þ^ßß]]ÎØÚbc–µWÃãfgËF\aàjëkììÁÑžnïoðpñqòrósôtõuöoƒ%Çâgúú±déií}þþ~_j‚0€ÀàA„ .dØÐáCˆ!ÚXÑâE„ ðÓÎãG!EŽ$YÒœ|<þ­dÙÒå–€8PÓæMœ9uîäÙÓçO ?5%ZÔ(Nü ,ˆÑ)CŠO¥N¥Z5bT«QÖyÙÕëW°°Â†Õ46ËÌ£iyUÛÖí[¸BYÄ5*àTL³yõî-„—¯µ~ÿþ*;˜OaA)s‰3ÜØñc0÷–Œre,—ûÚºógÐf‡Þ¬4/ͧ¡¤N¬rP8Õ±e÷=û0gÛÈÔž½ÛT.Gžs'Î…wñ,nŽ#§²fùiç¦'‡ÍÜúõ;ØÿÜÕ®Gyþw ß?-ÛÃüyÕÏÑJ¡~ýîÚã›/üý}¾îñÃ_¡ÿüë„®ºý dÉ?Ãë/ÁÕ ÐÁâdpBÚ(”" ÙãêÁ »3/C· 1ž»@Ç: ÿ“°D/l1 AŒº5°¯Fá˱‰-ì1´ÏûpGƒdÐÈ‘¬LÉû†$2É'uˆÒ&!«òȧïÊ&µä€ËÆÀÌÐI/s½3…40Í"³,È7uŒS¬ÙÜ‘Ì9ÿ²S¾<ÛX³ÏŽVÔ«=±+4À?íËMEù9EE%«ÑPð¤´ÂA%ENÓ¯8½F?Õ-RRëõKOõ®T@=þíÊUU_ 5V+5éV\sí&)êtõõ×ux Xb‹5öXp„Õ Yf›UGYÔ¸±Ç™6JnÚZªåhXl»¥G[Ãæñöp’v\ZxçZtQQ°Ämw^:Þ —Þií5Wyñƒ•æüàW6X‚E;˜Údö­táVbDv©_Š3ŽÁb²4ÎVâhùõ¸bŽyç‹}¦h@<íYhFJi"ˆÖæh¦!vz%¨£bê>Œf¡[`÷‘!\ÉecoNèë;.Q¬¶Y¨á¯á~á³7VºàÀþ$)[°Û“{ã¿û ¼Ž½y°Þ½4)Üo·g¼g±ç¼½ÅÇöúîJ¥Íûß±«žÆrÇë¾ñ€7ü®É—jÔGWØôD`·¹óÇß^= ÆçÆœÛÔE¿½uÈm¾k×EËqq%¥|–Dš¼ŸŸæùÈ7çzëÅ@W[îåse÷•ƒúÆWüüé½WùíÕç:0øwã¡úö·þžt¼“?ûë×_¿ìý-~þÛ[õàç?¸YÏ~ Ìß×@*‚,_û ¨>dàOaƒkÝœ7½è%oìàè> Ö‚»¡_ˆ¶òh®-¤!÷ g>âP‡-t[ßþ"8±±¯†0dêú¶C"Q‰š8Ä|Í7NÜ™nÄÆÅ+7Ê4cyÈÃÆÃØqŽ¿ÔcË6Æ4†1y"D#û¸7*Vò›FLäQ%ùKAN±”Aà!$¿øÊ¶yr“oÌä)—ØÊÙ¡²qÀ¼eþCayD¦›kUæj¸ù%rŽs‰èœ¨xÁUmVsˆîlªIé¹Îú³†}$è0çÑ„á3‹ý¼h2+Ò!;RŸe4iC Ó”†’£/½iRhÔüjtš×<êðˆÕã)5¢NêBGfÕ¬&´¥Ç´êXCvÖ´®´§o kUïº/­†Ô«Gk ;ʽ6õ£he ´Öqþmµ“•aY[Ûìp°‰¶ýít@ ÜãÞv·!Knt‹ÄÜY#mhËåÈÔnÌZŠw æ­ zSëÞ­È·Íö-mº¦V_ðîw‚ Ù‚Ï·‘M8XÞ †áá"гÀGËp¾Âã€ÅÄÆ#ކÑþ’âã _m•^ZÜW¹háåñ–«V¯1¿ZÈ›ÓnϦœæœ¤÷Î/2˜ûüp3z`Kþ…;b:§9ÓwÞñ¢Gìè_ŠúЗM‹OOg¹Ð¡^u„Ùüª`ïØ9{òGÖ‘”±PNÜw×¶™“]ßbîD¼´Û•ªk^ÞsÁòº«Nï~¯äÏ÷ÛÁÓ周Üì˜øÁãýk{'dßÙ.öóÁý¢¿»í&øÊsþð§E3ÖßHÐú}ŠûàA/øÅÓ[vz^ß!<´^^ë°çík/úÛC>÷uz8§ÚûÓ>tnÝðÛƒy¹»p¿_¾á›6âïþ>9¤]}Y ºî§ƒ/Ô¤ ÃÀQv¿ƒÞ›8{Ä÷Á7zÿ§æ7!G˜T“†sÍÌ Û¯ã›!°Q ÷až”Â?W*‡ê"ôk©þ‹Ÿ… ÀòS¥RjÀ–¢¨ô¦ïã¨ú«ŸûS¿ñ³žR²¢Çó?íÛºŠ‹"!ƒ"À ¤?²¿AŠò$ô§„ÀTƒ¯º&2Z¤ +wB(fR'3¸ðñ›#Â!,ÂTªYz'$ü+ÙY§}jÂ+ü¤,r'$̼®1tâ'} ª,ä§2,œ!’ÂÿÙ~Z*|bÂ}r“‚Âxʦ)„ª¤À?J(„*¨™BªÉIÃ9 ¢5\«þ÷³ =Ä_r¥|B=•BVâHH¢žBÈí‘)£òþÈŽt©L È¢ò%ZªÂ L!—ÄHòÓÈ—äÀ„|È™ô@JL)žc-ÓÓ,ì+§k¹¦Œ¹¯#»z>¥|=¶"½HKJ$€+¥kš®kº¯äº—“J’‘D‘«®”šz\ œË¬§¹·T¹¨$Ë¡JºŒ=¤<,w K§äK¨,¾»¬K³Ä·Àœ»Ál…¶¬¬¸Œ¸Åü¸¹,LͲKÈü¹Ã<;ÂH·ÜêÅ"ÃLtÓLøàLÐ\8ÐMfñÌ#MÔÓÔ‚;/ózÍâB‰å‚ׄM©(/Ûdô¢M‚0.ÜÌMàœ®}«–¦Nã–Ê;¼S9Adãñ[FuÖ–dD~ŽÞÝ E®:1êá9þße3¾ÛGNäôØd"ÎâMÍãÉhÖV2°Íßoß×PRUædVî’L{å ÖQUâ`ÞbPÙ”\ŽºN.P9ŒÞáa¶’f&f Žc.ºdÞK~‡-П¥‘nŽaÄe>®æŸÙeSùfm†dXe~Øpæ¶AÝÖS`zf½N=€äJ|Æ]s>gEçreçLûä$ ¾Ù>»³=âYhåCƒÂ¼æRýgi~P U­hÖÌȲÁôSHókÈÇ»Áh*¡’¦>\þF‰T¡ñsâ#_7~i˜æÌ#qCî™!ì•ÂÔ£p4œ;²ç¥=3äç–^3r&;p²õA:Çv´ÅšÖ¿I C|ì©6¾ºÉEFîç‚.jN.¤–gb_¦æ¢e’ÅíÝéÕ==Ÿ&^¶Áj£Öê5áj]n¤wÆe ʈÌé”?¨þÇš~ Žb!ÀÞ¿ž~¢¢|h¸®¹FæÄ¾—fçÚ-jˆ6”Å¶æÆ¾ãg€ìà«ì£ØFìÔn±ÕfíËnÒë}fhÑÓlzií9«í‚njî7*îC”Aé1îÛÎáþvîÙãÞçrä^ë–nB‹î|#n\6îæ^%ˆ"aï¹Ý"6âíæîxónOÎí±Æ"rÜíõ~îÄQïùžnyí¦òkaòàÀcLú^·“ç„Æ˜óæIÖ³o£SßVptaoªpÚe>ƒN]ßqðÿR ïîÏ‹ŒÁ§éø»HS"¡µ&éßðièð-QñûNo;²i¶Ch‚íÕ«ç ‡p.sñ¬ƒñ¿Æ"c a¼f;…¢<ÿ;ün³#‡Yï½bIJ6ì?qµ^r¼ôl+Gï™6È–\hæH£,éžö žÌr»bq1óÆÒq†HY¨a5'9sÂbsž±¿tipþõ¶s£sŽCóžòsÉtÊtïMò)6ôAGô-Wt¼"tÑvt˜áóTîªxö< Ÿ›ÿ¶ñ:‡tB‘ôœ¡tè°tê£pëc>çË8O¯'PgQSR×Àù«© dn“äÀœ&lâ%ñ_ºUîVwõ_/îÆîl4iZ¤ÃömÆPö–Ðó`ŸJFßê®EÆjMäÆ —_h—ºôŽö‘yuÕ.ög„ÇkÜötìv½qv•¡½þØtLgÍ»]Ü™rrwÚ&wä*Êòw`”È%L^#×|OL7÷r³BõÈ+øÈ¾wv7p_àˆÿ‡‡^Zo2‡AñÑÂŸÖ¿ÃæþìƒWá‰oöi¿QöíÄatFÁ¤ÂkR\ì’_’“/¬ŠosþÄ´‹ñS E~ôD{ojm—ìœïÏ›Ÿô£wfò¦OGñsòÿBfçêšOô¤·¬¥ßª†Tj ?Þ…2$…¼kF4q¹ãø•–ë«·’˜n{·¯¶?þîz‡wñµ uÏz”‰ûö®wÉû—½{•×ûpç{‰'üƒü0A|Q|Ôb|¹ÚúQ‡|_Oùŧ||q|ÌÆü…Ñü‡áüyñ|è}ƒ}Ê"ý—|XG}1ýß`ýàUýq‡ýÈ·|Ǧý|‘ý|¯ðÄû¼ ohÃû¼Tï¼ÞÏt mhtá/jþÇýzp}7~Sßlù&þ‡OhÜ)õSß~êw÷†GèyNžÂè¿z ®g8×íãÿFé¿ô«qåoäÿ}õç}Ê„€ëÄÎ.ÅÅd* aICµÙ≵´yÕ×]T†rä•~¬Ù¹îû¦!™ã ûµm×bÑDÆM¨¦;¥!èUñ$ˆ «ÍN¶Þ/8,“Ëæ3zkÃ!uíûý^Ëõ6]^ºÏùx¿ŸŒ^ \a`’`bàÜX€€À€ef¦æ&ggæÚNè(!©èb©ê)«©kêÑ+묬míê-›"a+®/p(œnI¤W—g²ò2§Sê©PSÑ þÓ®sÏžô5õÎsõ”¶#c7ö37ùuL6u¯ùî’»:J8‹€‡€GÁ$ü0+hð B-ÚˆqûE§!F+‚•‚(«CXx<ƒÑqѽŒóêpüÈQäÃES˜ð%LOWšü5 ¥<š8ÝÔÙÈgÍY;…ñôÖ„ ðwà@)MÚó*Ö¬GãÙkk¬¡bí öbQ%]î5ÙYÖ¸rÕ < Ô¢Mp8›˜ÄËS¯Ï~] ÖX—£v*m޶@éÀ¨¥xZ¹ÀÜÌš;=¡rOЊï<©Fc!èÃD¬‘ÖÀú/(®¿.^mïóèYAìTþ|¢»öìÒm  îæä/g–»Umó¶ÎMg{ÖfZ³^÷Fõ'j¨–Ç[Unþ<ÝCê×'bïþ=üøòço?~ÈÑóOVNå0¸;­Íià¤&Û(ç8áÛk¦pÕq¡‰â`‚ÁEAo±M4„…ºðØ)U=åAý¹¸Y}÷Ý£Œ5Úx£{4â¸ãFV•Ô"%©!¤BDÉÑH©ä‘$éä’P6‰ÜOªÀ#–…è˜%—]Ú·¥—ø]áQòÔ”4UÞ‹mb¦—qÊ9'uò˜ß~nêIœvÒç' þ$h ú0õ]š–PRÉRMíþùèr„J:)¥•v™yBºiŸ–zú)¨€bº)©šu*ª©ªšå¨A–Jê©«Ê:+­´ô*®0ÅZ+¯½új›@æÚ殿{줭»¬AÅ"û,´*[$³.:-¶Ùâ8mµÝ6£-¸áRÊ-µÞ*w­¸éªk+›æº{ºëÊ;¯·~!ì»qÅK/¿â’›/À’ô;0Á9Úð¹+¼°#ü0?wJW$ÖH¬Ul#œûü/ÄsyÌ0ɳ‚r¾#²òÂh¹^±Ð©W_Ç%Ãw²VÇ|¢óyŠ€¹›p 5ôC7¸ÜÛ• ©õ2żAóž‡$㌲¹6XΆ'þÙÅ =÷†Eà“õÒ£VÐðD±¡8ë¨lìÔº W‹u#CåÜøfæóÌÖ±ü·aÔÝaË=1M]áCmsÜTW+ÑuIü9bÕÑâô9«ny^R;ü&Ï.ñ3ºèøšžð×ÓôÐi´IQ€%™%û„eËtmQ# à6RÃ;¾¬oÒ9µ46øòO®`q‰÷噄% Þ¥»Ù£þÜJˆÌôtæ’¯ 4ó{][ÚÙ¿ðõÃãºåßTçaýÙq‘QÒ¥â?ìñ¬nj èø½\#ºÙFòˆVšò/múk켦9ÑŒdïSØåþ+¯¹MmTðˆƒ¨W!Õhˆz"ŠÞÐHHoÄWºáÒÜV=ϵ«?N’’”Üô>Ö½®©¡ù„9¿mA|#œíPñÁ‚…P„âØaf3¡m‘NU´â·`øR¸Œ/¯[ J˜Šu° ‡2»]î”–FÜônƒ'¼]ð>FâY p‡x¯ÙÅ™éqÍ– ý”H*Ò¯ú$#)ÉIR²’–¼$&3©ÉMr²“žü$(C)IC92&‹ô"")£/–²?(€ ËYÒÒ¶œ¥-cIË]ò²–·ì%0ƒ)Ìa³˜Æ$f.©Ìe2³™Î|&4 P´r9¢¼&6³©zÍmr³›Þ¼&)«¹¬5¡©œæ<':Ó©Îu²³î|'<ã)ÏyÒ³žö¼'>çY q&䕺„&@ºËd ´ %¨AªÐ…SšÔä'D#*щ’œù¼(F3ªÑr´£õè>)*Ò‘’´¤&=)JSªÒ•²´¥.})L5;spring-security-2.0.7.RELEASE/docs/reference/resources/images/AfterInvocation.gif0000644000000000000000000001110011766764657024605 0ustar GIF89a@/óïïïÛÛÛæææÿÿÿÈÈÈ´´´ÑÑѵµµ!ù,@/þÈI«½8ëÍ»ÿ`(Ždižhª®lë¾p,Ïtmßx®ï|ïÿÀ pH,ȤrÉl:ŸÐ¨tê X¯Ø¬vËíz¿à°xL.›Ïè´zÍn»ßð¸|N¯oK€Àïûÿ€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›zœ¢£¤¥¦§¨©ª«¬­­¡®´µ¶·¸¹º»¼¶²{½ÄÅÆÇÈÉÊËŠ¿ÁÃÌÒÓÔÕÖר‚γÙÝÞßàáâ“ÛÂãçèéêëËåÐìððцóñ÷ø€îöùþÊö†õã3ÐOÁzôþ)ŒÛ‡¼¬Œ&P"+)bɨq¢Ç>þ!ŠÌµOÂÁ‘(QL( Ë‹/WœÙÒ`”8W•p2§ÏM!/RŒ#Múñ§SR;{>JIfÍ«,‰ ò&Õ¯˜¢‚[ +S¡f7fœ(•¬[HbßÊKWaܺxóêww¯ß¿€õ L¸°a Í^̸q¦ÁŽ#Kž\2å˘#[Î̹3àÍžC‹– z´éÓNK£^Íú¡êÖÉVöl˨&B›°q¾Î]lÏP®Ú/ ”7ÄÝÆ#Ò̲vmEÛ›¢Þ‘#ÒëÖ§#ÕXýlr†Ïø}gö;­V¬æoMßÒ·z³]×k;ñ;ú±Õ^5Ê^¾zíýþåwóñWTRøÕžI "SÞ|çà„¡ð½Ô`oö‰·!1²5g ÀEî5‡ái-å"‚‚Ø!ƒ1Âf[ :„#jÅíh r>)dX3ò4ä‘HŠd’L6YY‘vD)å”TViå•Xf©å–\v Ë‚F:)æ˜ÍÄ¢#™h¦ ’™Š©éfšK¾)gŒqÎi'~uÞ©§qyîé'k}þ)èhƒÑ&S mÝxˆ¢ƒ0Ú !ŽBªae“6r(¥Ú¸è•¤‘¤¸h’ž4¢‘Ƨ¨6”!\Um÷›©˜"ª)n%:+¬œꈪˆ”Ü£þm¸Þ& ±›Âê+§þ Ë•¡µûk£¿­%ÎR[b¥‰ð*­¥Üzµ¬¶w½Ø"²%¡DKy‡¢§&²Ë.vÚý¯Kµ{âsÏŽ*/¼èvpwgå+nvý~Ô®wî&5ov—Òûn¿C=—oгúæ°©Õ\¯ÆowªˆG§¯¿7ò«a¼Ö]ªrÂØXé¨ì°oP^H¡€úèìóŠïýéƒ@ïLªÐ3# tÏßUÑ2›ÓÏ*M5ÔX§×´ÕJsMâÁYÈlØ漞Ì:{ ±Ð#j-2Ù§¶6Œn¯õÖgÃXì¤ì¡ôÔ^K÷„úy½ŸÞþó°rÝ8Íúí-Ûz¯JÐq¬s %qH˜ÍktN-£þ-¸ÍRNÔ‹uS&ÙÈKWnä“ mYîh<~¡M)Çtå ™Q!%x‹ü*!׺~„(iä %[Š£J’y¯â^P­%µú…´‹YãeEyºÁUŽ2eDs›—æ:JnqL­Q"·×Qô1'¥‰ó‚1÷/ýá šÐ“¦&³ªÕnŠ‚)Ô [ÓøÍ+2”$s=dT¼Ä×¾úõ¯€ ¬`KX,±‰(€ÀØÆ:Öm,dëØÊZö±‘½¬f7ËÙÎZ™õ¬hGKÚÒšö´¨M­jWËÚÖºöµ°­lgKÛÚ2ÖŸ°Àp€Þúö·À ®p‡KÜâ÷¸Èõmþ°Üä:÷¹Ð®t§KÝêZ÷ºØÍ®v·ËÝîz÷»ÞÅdp…ñš÷¼èM¯z×K…ðä½ì¯|çKßúÚ7îÍï}÷Ëßþú÷¿Ip/| àøÀN°Ì`;øÁŽð} La [øÂÎ0¬ {øÃ q2Àa›øÄ(Nq‰;œâ»øÅ^±0`LãÛx¿+ÎñwÌã«WÆ>²‡¬ ùÈHNrŒ¬ä&;ùÉ(`2”§Lå*_@ÊVβ–}Üà-{ùË!.1–gü1ƒùÌhž¯ Aas¸¼æ Lòæ:§ùÎxž‚™¡a’>ó9ÎüðóžþçB:Àv4œåÜå çwÑkæÇ˜MéJß`Ï]&t£ _B{ÚÒ õÚìæH78 tž´¨WÍj(¨ºÕ°Žõ^-ëZÛ:´¾µ®wÍë^ûú×D(¬°‡MìˆØ…Žë= dçYÙ>ü’³7kC{‡;™öŸ©|mf[Û~æv?¿ îjï¸Û7$·¶Í}ctÛPÝü-¶¼§tì£v} ¼q¼ÁÜ®×Ý zšD-ŠFlº³Hx`¤ýov°Œ™âN1 ™R†©áÿUøg0ÞA—™Ì%Ð8."VIÜ‘ûžpSÁÔñDΑ¦3›Cîp°ÎM{™`Å/ÎòþŒ¯|Á çô›ÃMôNã7 £jìÎêOŽ÷Wä~I¹\ÞèR·yæ2Ôt•Îfãt¸Óãýs`šèúÝvѯlä­Jêõµ)=fCNC-Ì¡t_"PÆnö5C:æ}¿ò¸ù®òTMqଢhâE0NÀÝ9|Ïý{S-x”Žž{¸HçgÖå&ëH÷"ÇšÙŒðˆ¾O>¯fZÑ’•Á3\Æ$¤8 ÁôiªC}‘,y£L“¢4Ï#‡UŸa= _žP»žsÝÏ:ìÝd½|iª:ãÿ´ø+êÏ`_ò÷hÍs–tøS½hF—ÿûâ??ªÃ´zç·>iѱ_ú¤³¯çþ©´–ãûWoÎüГÊýˆæv‚"}ñ%€ºap€Ç{üD€ìe€ºA,(€{2öÆ' HgO˜^8È€ç!1w EHJtQ9’`!HØ%¨z\7FøfB´‚9¾WvN uí@GvT2ˆ£"2ÙsTñw„¡7H2yO„ x‚×—|JW;³Ç3§ó#3˜¼1‚ÁÁ÷KH3|À‡}ÂÇ.H_X…(…Rƒ»‚K¸Ä}WÈ(k˜…>ƒTˆ^tX(ø>ºSqõÇI!¥‡+URÊ÷‚ˆDô†E‰o"†æ5o˜X‡‡í'‡û•Xþ”e[¢8ФxZ¸Õl`ˆO–8^»^®øŠ°X]õƉª(‰àd”¨Q¶x‹=–‰¾ø‹T²‰¼¸e hZ¿PŠÈ˜ŒÊÈXǸŒ¥uŠÃf­ø\W‹ÖxØÈ\VÑ5‹Ñjå—fáøä8bi'ŽïÅn帎$öigVaìQt_æqòx `^¦øØíÈbõxeþ8ÿˆvùiêHå¦v im ©itÙ6f‘½f‘[¦‘Ù:FPö‘jבy‘Gf’$™’*¹’,Ù’.„kf™ö’ºÆðj6ya9™uù’4YTçfà't¨V.‡aF)þi2'~D9gI©”?)“ô¸i6“Vt; ƒSÉiUi¦¶•Q ”X7`G•dùwc‰”TG~L hgsO–RÙ•É•™V‚YagW—/nxé“r‰g¤Æ–qö}ãØnm~§V”5˜Ãˆ’C™Ž9™”Y™–y™˜™™š¹™œÙ‘’‰‹y‹ŸÉe¡¹†6š¥‰Ž§™šÓ†š‰lÀ›²IXÞX³y›ÃV›E–WÝâo1‹­Ál®Æ›½"ŒUðB „Ĺ(»HbÈÙœ5œF´ŠY÷œž8†Ëù$×iÒ¹ÔIÝ)DßÙ~2žä•Ú9áyæù›,˜‚¥ÄG=þðyAøA•ŸÄ76rwÙ$*Ð)xŸvSKr4ŸA“w— ŸÐÇt êé:uHTmHw8h  ZBÞF‹‚TÇBpüÙ Ú&±ÂAžÂ4Ra¡‡—o‹·ƒm¢µ1¢î©&µˆ67VÔ‘ˆDHË$ž·ReÕ·M`×2×T£FXzåÑ„]ñ„aœ- @ÉL4s£6?³ÇGñ×£2Ó¥IHGÊ1$c9Pjq"£0G7E?7G!Ðq}Ú×}O%?QõS[Ø\“œkÚ+Ÿ„…n9û©§UÅ:s*{:Ê…Sjú÷"M3%J‡×ò™7p Kò·¨”s4þ]Ø"i¨tÙdž¾!¥,@¥y©’Ã-”úKžz©²“©&ª‚ºTíÙ§wú¤¾£†ÖW¨µ´ªu:I&GKv¨S²t¨µJ#Æ’!xÈ««5q{²úz˜º‡Õ×+zœ:WV0#=d|Zy^—«@ê*ˆ8Fh5;d¥;Å<°Š®æc3Œ¸6ÇÊ~•á?J¸­,Ѥó­ƒXLZcˆW®;•ñ꣌ºZăäp­ëÙ¢z1¯SÊuaóú°u¸q‹kè )kÃÙ±Úð±.$±¥*²#»±#€±¢a²+À²éF²+ä²*³ï&³*D³)`³3t± û<+C>[²×:þ±(«8ûvE{²G+¢*»`¸µƒEªÖ´N;ŸZÍèŒ\Ûµ^‹Ð´R;¶d%T«ÓX]ÍÅlÛ¶në[º™Yûµt[·vëŒ[ÛZa;k¬™iû¶€¸‚Ëk›]q;‰}›¸i`®©¸*Ù¸渒+‘“[¹ñf¹˜›¹š»¹œÛ¹Œë¹  ˆ¡«™»a£›™¥{©{ºß¸ºˆËº–éºÁ»±K»¶[d·›»º»»ë˜—“¼ ›€y“ÃKuF•0w”¼¼—U'”P¹”Gf›6t|éŽÌ»k{yjt鎲[fÇk—V½r–½°¾/7¾Ò[¾¸K—CþÇ‘æëlÛËgðëjLY–ñ‹ƒ‰¿ÿ–¿)’Ø+ºð½þ»š#IÀÑImì‘ ¬f ¼À÷Øvö%Á¬¿éÀYÁ ü»ô”«Áìh–Æ• lÁn9Â'\Âò¨_L‚é¨ÂþÈÂ÷Â0ì‘Ë;Á\ý{Ãq—Ã:\ke›%‡ûÖ´½á›DÌjF "g›Ä‡¶Ä½ ³NÌeu!ÅSlmU¼´WŒ‹Yü´[¼‘]üÅàx “SpnèÅbleî–tˆ÷¢ʰݢÅiÜn Š¥þ*q~°ÒѰh<ÇSvm$G¬¢srÚÇ~üdݦyÇw?¤R@hZȇüÄät‡8¥©àÄÇþ‘|šdÜud†HèŸ{gÈ™œdP,P¢<Ê'ƨ|g¥¼ V¼Ê"Öʺðʰ b²|ƵŒf·Dþ,Ò ·Ì&‹A|%MœÒ56·wÓ£µ·.d;¸8í\C\Ó<ÝÓ>M;spring-security-2.0.7.RELEASE/docs/reference/anon-auth-provider.xml0000644000000000000000000001274111766764657022024 0ustar Anonymous Authentication
Overview Particularly in the case of web request URI security, sometimes it is more convenient to assign configuration attributes against every possible secure object invocation. Put differently, sometimes it is nice to say ROLE_SOMETHING is required by default and only allow certain exceptions to this rule, such as for login, logout and home pages of an application. There are also other situations where anonymous authentication would be desired, such as when an auditing interceptor queries the SecurityContextHolder to identify which principal was responsible for a given operation. Such classes can be authored with more robustness if they know the SecurityContextHolder always contains an Authentication object, and never null.
Configuration Spring Security provides three classes that together provide an anonymous authentication feature. AnonymousAuthenticationToken is an implementation of Authentication, and stores the GrantedAuthority[]s which apply to the anonymous principal. There is a corresponding AnonymousAuthenticationProvider, which is chained into the ProviderManager so that AnonymousAuthenticationTokens are accepted. Finally, there is an AnonymousProcessingFilter, which is chained after the normal authentication mechanisms and automatically add an AnonymousAuthenticationToken to the SecurityContextHolder if there is no existing Authentication held there. The definition of the filter and authentication provider appears as follows: ]]> The key is shared between the filter and authentication provider, so that tokens created by the former are accepted by the latter. The userAttribute is expressed in the form of usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]. This is the same syntax as used after the equals sign for InMemoryDaoImpl's userMap property. As explained earlier, the benefit of anonymous authentication is that all URI patterns can have security applied to them. For example: " + ]]> Rounding out the anonymous authentication discussion is the AuthenticationTrustResolver interface, with its corresponding AuthenticationTrustResolverImpl implementation. This interface provides an isAnonymous(Authentication) method, which allows interested classes to take into account this special type of authentication status. The ExceptionTranslationFilter uses this interface in processing AccessDeniedExceptions. If an AccessDeniedException is thrown, and the authentication is of an anonymous type, instead of throwing a 403 (forbidden) response, the filter will instead commence the AuthenticationEntryPoint so the principal can authenticate properly. This is a necessary distinction, otherwise principals would always be deemed "authenticated" and never be given an opportunity to login via form, basic, digest or some other normal authentication mechanism
spring-security-2.0.7.RELEASE/docs/reference/community.xml0000644000000000000000000000521011766764657020317 0ustar Spring Security Community
Issue Tracking Spring Security uses JIRA to manage bug reports and enhancement requests. If you find a bug, please log a report using JIRA. Do not log it on the support forum, mailing list or by emailing the project's developers. Such approaches are ad-hoc and we prefer to manage bugs using a more formal process. If possible, in your issue report please provide a JUnit test that demonstrates any incorrect behaviour. Or, better yet, provide a patch that corrects the issue. Similarly, enhancements are welcome to be logged in the issue tracker, although we only accept enhancement requests if you include corresponding unit tests. This is necessary to ensure project test coverage is adequately maintained. You can access the issue tracker at http://jira.springframework.org/browse/SEC.
Becoming Involved We welcome your involvement in Spring Security project. There are many ways of contributing, including reading the forum and responding to questions from other people, writing new code, improving existing code, assisting with documentation, developing samples or tutorials, or simply making suggestions.
Further Information Questions and comments on Spring Security are welcome. You can use the Spring Community Forum web site at http://forum.springframework.org to discuss Spring Security with other users of the framework. Remember to use JIRA for bug reports, as explained above. Everyone is also welcome to join the Acegisecurity-developer mailing list and participate in design discussions. The traffic volume is very light.
spring-security-2.0.7.RELEASE/docs/reference/appendix-db-schema.xml0000644000000000000000000001134711766764657021734 0ustar Security Database Schema There are various database schema used by the framework and this appendix provides a single reference point to them all. You only need to provide the tables for the areas of functonality you require. DDL statements are given for the HSQLDB database. You can use these as a guideline for defining the schema for the database you are using.
User Schema The standard JDBC implementation of the UserDetailsService requires tables to load the password, account status (enabled or disabled) and a list of authorities (roles) for the user. create table users( username varchar_ignorecase(50) not null primary key, password varchar_ignorecase(50) not null, enabled boolean not null); create table authorities ( username varchar_ignorecase(50) not null, authority varchar_ignorecase(50) not null, constraint fk_authorities_users foreign key(username) references users(username)); create unique index ix_auth_username on authorities (username,authority);;
Group Authorities Spring Security 2.0 introduced support for group authorities create table groups ( id bigint generated by default as identity(start with 0) primary key, group_name varchar_ignorecase(50) not null); create table group_authorities ( group_id bigint not null, authority varchar(50) not null, constraint fk_group_authorities_group foreign key(group_id) references groups(id)); create table group_members ( id bigint generated by default as identity(start with 0) primary key, username varchar(50) not null, group_id bigint not null, constraint fk_group_members_group foreign key(group_id) references groups(id));
Persistent Login (Remember-Me) Schema This table is used to store data used by the more secure persistent token remember-me implementation. If you are using JdbcTokenRepositoryImpl either directly or through the namespace, then you will need this table. create table persistent_logins ( username varchar(64) not null, series varchar(64) primary key, token varchar(64) not null, last_used timestamp not null);
ACL Schema The tables used by the Spring Security ACL implementation. create table acl_sid ( id bigint generated by default as identity(start with 100) not null primary key, principal boolean not null, sid varchar_ignorecase(100) not null, constraint unique_uk_1 unique(sid,principal) ); create table acl_class ( id bigint generated by default as identity(start with 100) not null primary key, class varchar_ignorecase(100) not null, constraint unique_uk_2 unique(class) ); create table acl_object_identity ( id bigint generated by default as identity(start with 100) not null primary key, object_id_class bigint not null, object_id_identity bigint not null, parent_object bigint, owner_sid bigint, entries_inheriting boolean not null, constraint unique_uk_3 unique(object_id_class,object_id_identity), constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id), constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id), constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id) ); create table acl_entry ( id bigint generated by default as identity(start with 100) not null primary key, acl_object_identity bigint not null,ace_order int not null,sid bigint not null, mask integer not null,granting boolean not null,audit_success boolean not null, audit_failure boolean not null,constraint unique_uk_4 unique(acl_object_identity,ace_order), constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id), constraint foreign_fk_5 foreign key(sid) references acl_sid(id) );
spring-security-2.0.7.RELEASE/dist/0000755000000000000000000000000011766764113013613 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-cas-client/0000755000000000000000000000000011766764113021002 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-cas-client/META-INF/0000755000000000000000000000000011623521774022136 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-cas-client/META-INF/MANIFEST.MF0000644000000000000000000000014311623521772023564 0ustar Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: 20.1-b02-384 (Apple Inc.) spring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/0000755000000000000000000000000011623517156021564 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/0000755000000000000000000000000011623517156025004 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/0000755000000000000000000000000011623517156026653 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/ui/0000755000000000000000000000000011623517156027270 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/ui/cas/0000755000000000000000000000000011623517156030036 5ustar ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/ui/cas/ServiceProperties.javaspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/ui/cas/Se0000644000000000000000000000557411623517156030343 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.cas; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Stores properties related to this CAS service. *

* Each web application capable of processing CAS tickets is known as a service. * This class stores the properties that are relevant to the local CAS service, being the application * that is being secured by Spring Security. * * @author Ben Alex * @version $Id$ */ public class ServiceProperties implements InitializingBean { //~ Instance fields ================================================================================================ private String service; private boolean sendRenew = false; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(this.service, "service must be specified."); } /** * Represents the service the user is authenticating to. *

* This service is the callback URL belonging to the local Spring Security System for Spring secured application. * For example, *

     * https://www.mycompany.com/application/j_spring_cas_security_check
     * 
* * @return the URL of the service the user is authenticating to */ public String getService() { return service; } /** * Indicates whether the renew parameter should be sent to the CAS login URL and CAS * validation URL. *

* If true, it will force CAS to authenticate the user again (even if the * user has previously authenticated). During ticket validation it will require the ticket was generated as a * consequence of an explicit login. High security applications would probably set this to true. * Defaults to false, providing automated single sign on. * * @return whether to send the renew parameter to CAS */ public boolean isSendRenew() { return sendRenew; } public void setSendRenew(boolean sendRenew) { this.sendRenew = sendRenew; } public void setService(String service) { this.service = service; } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/ui/cas/CasProcessingFilterEntryPoint.javaspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/ui/cas/Ca0000644000000000000000000001057711623517156030316 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.cas; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.jasig.cas.client.util.CommonUtils; import org.springframework.security.AuthenticationException; import org.springframework.security.ui.AuthenticationEntryPoint; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Used by the ExceptionTranslationFilter to commence authentication via the JA-SIG Central * Authentication Service (CAS). *

* The user's browser will be redirected to the JA-SIG CAS enterprise-wide login page. * This page is specified by the loginUrl property. Once login is complete, the CAS login page will * redirect to the page indicated by the service property. The service is a HTTP URL * belonging to the current application. The service URL is monitored by the {@link CasProcessingFilter}, * which will validate the CAS login was successful. * * @author Ben Alex * @author Scott Battaglia * @version $Id$ */ public class CasProcessingFilterEntryPoint implements AuthenticationEntryPoint, InitializingBean { //~ Instance fields ================================================================================================ private ServiceProperties serviceProperties; private String loginUrl; /** * Determines whether the Service URL should include the session id for the specific user. As of CAS 3.0.5, the * session id will automatically be stripped. However, older versions of CAS (i.e. CAS 2), do not automatically * strip the session identifier (this is a bug on the part of the older server implementations), so an option to * disable the session encoding is provided for backwards compatibility. * * By default, encoding is enabled. */ private boolean encodeServiceUrlWithSessionId = true; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(this.loginUrl, "loginUrl must be specified"); Assert.notNull(this.serviceProperties, "serviceProperties must be specified"); } public void commence(final ServletRequest servletRequest, final ServletResponse servletResponse, final AuthenticationException authenticationException) throws IOException, ServletException { final HttpServletResponse response = (HttpServletResponse) servletResponse; final String urlEncodedService = CommonUtils.constructServiceUrl(null, response, this.serviceProperties.getService(), null, "ticket", this.encodeServiceUrlWithSessionId); final String redirectUrl = CommonUtils.constructRedirectUrl(this.loginUrl, "service", urlEncodedService, this.serviceProperties.isSendRenew(), false); response.sendRedirect(redirectUrl); } /** * The enterprise-wide CAS login URL. Usually something like * https://www.mycompany.com/cas/login. * * @return the enterprise-wide CAS login URL */ public String getLoginUrl() { return this.loginUrl; } public ServiceProperties getServiceProperties() { return this.serviceProperties; } public void setLoginUrl(final String loginUrl) { this.loginUrl = loginUrl; } public void setServiceProperties(final ServiceProperties serviceProperties) { this.serviceProperties = serviceProperties; } public void setEncodeServiceUrlWithSessionId(final boolean encodeServiceUrlWithSessionId) { this.encodeServiceUrlWithSessionId = encodeServiceUrlWithSessionId; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/ui/cas/CasProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/ui/cas/Ca0000644000000000000000000001366111623517156030313 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.cas; import java.io.IOException; import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage; import org.jasig.cas.client.util.CommonUtils; import org.jasig.cas.client.validation.TicketValidator; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.ui.FilterChainOrder; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Processes a CAS service ticket.

A service ticket consists of an opaque ticket string. It arrives at this * filter by the user's browser successfully authenticating using CAS, and then receiving a HTTP redirect to a * service. The opaque ticket string is presented in the ticket request parameter. This * filter monitors the service URL so it can receive the service ticket and process it. The CAS server * knows which service URL to use via the {@link ServiceProperties#getService()} method.

*

Processing the service ticket involves creating a UsernamePasswordAuthenticationToken which * uses {@link #CAS_STATEFUL_IDENTIFIER} for the principal and the opaque ticket string as the * credentials.

*

The configured AuthenticationManager is expected to provide a provider that can recognise * UsernamePasswordAuthenticationTokens containing this special principal name, and process * them accordingly by validation with the CAS server.

*

By configuring a shared {@link ProxyGrantingTicketStorage} between the {@link TicketValidator} and the CasProcessingFilter * one can have the CasProcessingFilter handle the proxying requirements for CAS. In addition, the URI endpoint for the proxying * would also need to be configured (i.e. the part after protocol, hostname, and port). * *

Do not use this class directly. Instead configure web.xml to use the {@link * org.springframework.security.util.FilterToBeanProxy}.

* * @author Ben Alex * @version $Id$ */ public class CasProcessingFilter extends AbstractProcessingFilter { //~ Static fields/initializers ===================================================================================== /** Used to identify a CAS request for a stateful user agent, such as a web browser. */ public static final String CAS_STATEFUL_IDENTIFIER = "_cas_stateful_"; /** * Used to identify a CAS request for a stateless user agent, such as a remoting protocol client (eg * Hessian, Burlap, SOAP etc). Results in a more aggressive caching strategy being used, as the absence of a * HttpSession will result in a new authentication attempt on every request. */ public static final String CAS_STATELESS_IDENTIFIER = "_cas_stateless_"; /** * The last portion of the receptor url, i.e. /proxy/receptor */ private String proxyReceptorUrl; /** * The backing storage to store ProxyGrantingTicket requests. */ private ProxyGrantingTicketStorage proxyGrantingTicketStorage; //~ Methods ======================================================================================================== public Authentication attemptAuthentication(final HttpServletRequest request) throws AuthenticationException { final String username = CAS_STATEFUL_IDENTIFIER; String password = request.getParameter("ticket"); if (password == null) { password = ""; } UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); return this.getAuthenticationManager().authenticate(authRequest); } /** * This filter by default responds to /j_spring_cas_security_check. * * @return the default */ public String getDefaultFilterProcessesUrl() { return "/j_spring_cas_security_check"; } public int getOrder() { return FilterChainOrder.CAS_PROCESSING_FILTER; } /** * Overridden to provide proxying capabilities. */ protected boolean requiresAuthentication(final HttpServletRequest request, final HttpServletResponse response) { final String requestUri = request.getRequestURI(); if (CommonUtils.isEmpty(this.proxyReceptorUrl) || !requestUri.endsWith(this.proxyReceptorUrl) || this.proxyGrantingTicketStorage == null) { return super.requiresAuthentication(request, response); } try { CommonUtils.readAndRespondToProxyReceptorRequest(request, response, this.proxyGrantingTicketStorage); return false; } catch (final IOException e) { return super.requiresAuthentication(request, response); } } public final void setProxyReceptorUrl(final String proxyReceptorUrl) { this.proxyReceptorUrl = proxyReceptorUrl; } public final void setProxyGrantingTicketStorage( final ProxyGrantingTicketStorage proxyGrantingTicketStorage) { this.proxyGrantingTicketStorage = proxyGrantingTicketStorage; } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/ui/cas/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/ui/cas/pa0000644000000000000000000000017111623517156030360 0ustar Authenticates standard web browser users via JA-SIG Central Authentication Service (CAS). ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers/spring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers0000755000000000000000000000000011623517156030611 5ustar ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers/cas/spring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers0000755000000000000000000000000011623517156030611 5ustar ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers/cas/CasAuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers0000644000000000000000000002205611623517156030620 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.cas; import org.jasig.cas.client.validation.Assertion; import org.jasig.cas.client.validation.TicketValidationException; import org.jasig.cas.client.validation.TicketValidator; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.BadCredentialsException; import org.springframework.security.providers.AuthenticationProvider; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.providers.cas.cache.NullStatelessTicketCache; import org.springframework.security.ui.cas.CasProcessingFilter; import org.springframework.security.ui.cas.ServiceProperties; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.security.userdetails.UserDetailsChecker; import org.springframework.security.userdetails.checker.AccountStatusUserDetailsChecker; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that integrates with JA-SIG Central Authentication Service * (CAS). *

* This AuthenticationProvider is capable of validating {@link UsernamePasswordAuthenticationToken} * requests which contain a principal name equal to either * {@link CasProcessingFilter#CAS_STATEFUL_IDENTIFIER} or {@link CasProcessingFilter#CAS_STATELESS_IDENTIFIER}. * It can also validate a previously created {@link CasAuthenticationToken}. * * @author Ben Alex * @version $Id$ */ public class CasAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class); //~ Instance fields ================================================================================================ private UserDetailsService userDetailsService; private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache(); private String key; private TicketValidator ticketValidator; private ServiceProperties serviceProperties; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.userDetailsService, "A userDetailsService must be set"); Assert.notNull(this.ticketValidator, "A ticketValidator must be set"); Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set"); Assert.hasText(this.key, "A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated"); Assert.notNull(this.messages, "A message source must be set"); Assert.notNull(this.serviceProperties, "serviceProperties is a required field."); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } if (authentication instanceof UsernamePasswordAuthenticationToken && (!CasProcessingFilter.CAS_STATEFUL_IDENTIFIER.equals(authentication.getPrincipal().toString()) && !CasProcessingFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal().toString()))) { // UsernamePasswordAuthenticationToken not CAS related return null; } // If an existing CasAuthenticationToken, just check we created it if (authentication instanceof CasAuthenticationToken) { if (this.key.hashCode() == ((CasAuthenticationToken) authentication).getKeyHash()) { return authentication; } else { throw new BadCredentialsException(messages.getMessage("CasAuthenticationProvider.incorrectKey", "The presented CasAuthenticationToken does not contain the expected key")); } } // Ensure credentials are presented if ((authentication.getCredentials() == null) || "".equals(authentication.getCredentials())) { throw new BadCredentialsException(messages.getMessage("CasAuthenticationProvider.noServiceTicket", "Failed to provide a CAS service ticket to validate")); } boolean stateless = false; if (authentication instanceof UsernamePasswordAuthenticationToken && CasProcessingFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal())) { stateless = true; } CasAuthenticationToken result = null; if (stateless) { // Try to obtain from cache result = statelessTicketCache.getByTicketId(authentication.getCredentials().toString()); } if (result == null) { result = this.authenticateNow(authentication); result.setDetails(authentication.getDetails()); } if (stateless) { // Add to cache statelessTicketCache.putTicketInCache(result); } return result; } private final CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException { try { final Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(), serviceProperties.getService()); final UserDetails userDetails = loadUserByAssertion(assertion); userDetailsChecker.check(userDetails); return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(), userDetails.getAuthorities(), userDetails, assertion); } catch (final TicketValidationException e) { throw new BadCredentialsException(e.getMessage(), e); } } /** * Template method for retrieving the UserDetails based on the assertion. Default is to call configured userDetailsService and pass the username. Deployers * can override this method and retrieve the user based on any criteria they desire. * * @param assertion The CAS Assertion. * @returns the UserDetails. */ protected UserDetails loadUserByAssertion(final Assertion assertion) { return this.userDetailsService.loadUserByUsername(assertion.getPrincipal().getName()); } protected UserDetailsService getUserDetailsService() { return userDetailsService; } public void setUserDetailsService(final UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } public void setServiceProperties(final ServiceProperties serviceProperties) { this.serviceProperties = serviceProperties; } protected String getKey() { return key; } public void setKey(String key) { this.key = key; } public StatelessTicketCache getStatelessTicketCache() { return statelessTicketCache; } protected TicketValidator getTicketValidator() { return ticketValidator; } public void setMessageSource(final MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setStatelessTicketCache(final StatelessTicketCache statelessTicketCache) { this.statelessTicketCache = statelessTicketCache; } public void setTicketValidator(final TicketValidator ticketValidator) { this.ticketValidator = ticketValidator; } public boolean supports(final Class authentication) { if (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)) { return true; } else if (CasAuthenticationToken.class.isAssignableFrom(authentication)) { return true; } else { return false; } } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers/cas/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers0000644000000000000000000000023111623517156030607 0ustar An authentication provider that can process JA-SIG Central Authentication Service (CAS) service tickets and proxy tickets. ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers/cas/StatelessTicketCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers0000644000000000000000000001012311623517156030610 0ustar /* Copyright 2004 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.cas; /** * Caches CAS service tickets and CAS proxy tickets for stateless connections. * *

* When a service ticket or proxy ticket is validated against the CAS server, * it is unable to be used again. Most types of callers are stateful and are * associated with a given HttpSession. This allows the * affirmative CAS validation outcome to be stored in the * HttpSession, meaning the removal of the ticket from the CAS * server is not an issue. *

* *

* Stateless callers, such as remoting protocols, cannot take advantage of * HttpSession. If the stateless caller is located a significant * network distance from the CAS server, acquiring a fresh service ticket or * proxy ticket for each invocation would be expensive. *

* *

* To avoid this issue with stateless callers, it is expected stateless callers * will obtain a single service ticket or proxy ticket, and then present this * same ticket to the Spring Security secured application on each * occasion. As no HttpSession is available for such callers, the * affirmative CAS validation outcome cannot be stored in this location. *

* *

* The StatelessTicketCache enables the service tickets and proxy * tickets belonging to stateless callers to be placed in a cache. This * in-memory cache stores the CasAuthenticationToken, effectively * providing the same capability as a HttpSession with the ticket * identifier being the key rather than a session identifier. *

* *

* Implementations should provide a reasonable timeout on stored entries, such * that the stateless caller are not required to unnecessarily acquire fresh * CAS service tickets or proxy tickets. *

* * @author Ben Alex * @version $Id$ */ public interface StatelessTicketCache { //~ Methods ================================================================ /** * Retrieves the CasAuthenticationToken associated with the * specified ticket. * *

* If not found, returns a * nullCasAuthenticationToken. *

* * @return the fully populated authentication token */ CasAuthenticationToken getByTicketId(String serviceTicket); /** * Adds the specified CasAuthenticationToken to the cache. * *

* The {@link CasAuthenticationToken#getCredentials()} method is used to * retrieve the service ticket number. *

* * @param token to be added to the cache */ void putTicketInCache(CasAuthenticationToken token); /** * Removes the specified ticket from the cache, as per {@link * #removeTicketFromCache(String)}. * *

* Implementations should use {@link * CasAuthenticationToken#getCredentials()} to obtain the ticket and then * delegate to to the {@link #removeTicketFromCache(String)} method. *

* * @param token to be removed */ void removeTicketFromCache(CasAuthenticationToken token); /** * Removes the specified ticket from the cache, meaning that future calls * will require a new service ticket. * *

* This is in case applications wish to provide a session termination * capability for their stateless clients. *

* * @param serviceTicket to be removed */ void removeTicketFromCache(String serviceTicket); } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers/cas/CasAuthenticationToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers0000644000000000000000000001116411623517156030616 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.cas; import org.jasig.cas.client.validation.Assertion; import org.springframework.security.GrantedAuthority; import org.springframework.security.providers.AbstractAuthenticationToken; import org.springframework.security.userdetails.UserDetails; import java.io.Serializable; /** * Represents a successful CAS Authentication. * * @author Ben Alex * @author Scott Battaglia * @version $Id$ */ public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private final Object credentials; private final Object principal; private final UserDetails userDetails; private final int keyHash; private final Assertion assertion; //~ Constructors =================================================================================================== /** * Constructor. * * @param key to identify if this object made by a given {@link * CasAuthenticationProvider} * @param principal typically the UserDetails object (cannot be null) * @param credentials the service/proxy ticket ID from CAS (cannot be * null) * @param authorities the authorities granted to the user (from the {@link * org.springframework.security.userdetails.UserDetailsService}) (cannot be null) * @param userDetails the user details (from the {@link * org.springframework.security.userdetails.UserDetailsService}) (cannot be null) * @param assertion the assertion returned from the CAS servers. It contains the principal and how to obtain a * proxy ticket for the user. * * @throws IllegalArgumentException if a null was passed */ public CasAuthenticationToken(final String key, final Object principal, final Object credentials, final GrantedAuthority[] authorities, final UserDetails userDetails, final Assertion assertion) { super(authorities); if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal) || (credentials == null) || "".equals(credentials) || (authorities == null) || (userDetails == null) || (assertion == null)) { throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } this.keyHash = key.hashCode(); this.principal = principal; this.credentials = credentials; this.userDetails = userDetails; this.assertion = assertion; setAuthenticated(true); } //~ Methods ======================================================================================================== public boolean equals(final Object obj) { if (!super.equals(obj)) { return false; } if (obj instanceof CasAuthenticationToken) { CasAuthenticationToken test = (CasAuthenticationToken) obj; if (!this.assertion.equals(test.getAssertion())) { return false; } if (this.getKeyHash() != test.getKeyHash()) { return false; } return true; } return false; } public Object getCredentials() { return this.credentials; } public int getKeyHash() { return this.keyHash; } public Object getPrincipal() { return this.principal; } public Assertion getAssertion() { return this.assertion; } public UserDetails getUserDetails() { return userDetails; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString()); sb.append(" Assertion: ").append(this.assertion); sb.append(" Credentials (Service/Proxy Ticket): ").append(this.credentials); return (sb.toString()); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers/cas/cache/spring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers0000755000000000000000000000000011623517156030611 5ustar ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers/cas/cache/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers0000644000000000000000000000014111623517156030607 0ustar Caches CAS tickets for the CasAuthenticationProvider. ././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers/cas/cache/EhCacheBasedTicketCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers0000644000000000000000000000660511623517156030622 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.cas.cache; import net.sf.ehcache.CacheException; import net.sf.ehcache.Element; import net.sf.ehcache.Ehcache; import org.springframework.security.providers.cas.CasAuthenticationToken; import org.springframework.security.providers.cas.StatelessTicketCache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.util.Assert; /** * Caches tickets using a Spring IoC defined EHCACHE. * * @author Ben Alex * @version $Id$ */ public class EhCacheBasedTicketCache implements StatelessTicketCache, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(EhCacheBasedTicketCache.class); //~ Instance fields ================================================================================================ private Ehcache cache; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "cache mandatory"); } public CasAuthenticationToken getByTicketId(String serviceTicket) { Element element = null; try { element = cache.get(serviceTicket); } catch (CacheException cacheException) { throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage()); } if (logger.isDebugEnabled()) { logger.debug("Cache hit: " + (element != null) + "; service ticket: " + serviceTicket); } if (element == null) { return null; } else { return (CasAuthenticationToken) element.getValue(); } } public Ehcache getCache() { return cache; } public void putTicketInCache(CasAuthenticationToken token) { Element element = new Element(token.getCredentials().toString(), token); if (logger.isDebugEnabled()) { logger.debug("Cache put: " + element.getKey()); } cache.put(element); } public void removeTicketFromCache(CasAuthenticationToken token) { if (logger.isDebugEnabled()) { logger.debug("Cache remove: " + token.getCredentials().toString()); } this.removeTicketFromCache(token.getCredentials().toString()); } public void removeTicketFromCache(String serviceTicket) { cache.remove(serviceTicket); } public void setCache(Ehcache cache) { this.cache = cache; } } ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers/cas/cache/NullStatelessTicketCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-cas-client/org/springframework/security/providers0000644000000000000000000000421211623517156030612 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.cas.cache; import org.springframework.security.providers.cas.CasAuthenticationProvider; import org.springframework.security.providers.cas.CasAuthenticationToken; import org.springframework.security.providers.cas.StatelessTicketCache; /** * Implementation of @link {@link StatelessTicketCache} that has no backing cache. Useful * in instances where storing of tickets for stateless session management is not required. *

* This is the default StatelessTicketCache of the @link {@link CasAuthenticationProvider} to * eliminate the unnecessary dependency on EhCache that applications have even if they are not using * the stateless session management. * * @author Scott Battaglia * @version $Id$ * *@see CasAuthenticationProvider */ public final class NullStatelessTicketCache implements StatelessTicketCache { /** * @return null since we are not storing any tickets. */ public CasAuthenticationToken getByTicketId(final String serviceTicket) { return null; } /** * This is a no-op since we are not storing tickets. */ public void putTicketInCache(final CasAuthenticationToken token) { // nothing to do } /** * This is a no-op since we are not storing tickets. */ public void removeTicketFromCache(final CasAuthenticationToken token) { // nothing to do } /** * This is a no-op since we are not storing tickets. */ public void removeTicketFromCache(final String serviceTicket) { // nothing to do } } spring-security-2.0.7.RELEASE/dist/spring-security-portlet/0000755000000000000000000000000011766764113020451 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-portlet/META-INF/0000755000000000000000000000000011623521764021604 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-portlet/META-INF/MANIFEST.MF0000644000000000000000000000014311623521762023232 0ustar Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: 20.1-b02-384 (Apple Inc.) spring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/0000755000000000000000000000000011623517156021233 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/0000755000000000000000000000000011623517156024453 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/0000755000000000000000000000000011623517156026322 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/ui/0000755000000000000000000000000011623517156026737 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/ui/portlet/0000755000000000000000000000000011623517156030430 5ustar ././@LongLink0000000000000000000000000000022500000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/ui/portlet/PortletPreAuthenticatedAuthenticationDetails.javaspring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/ui/portlet/P0000644000000000000000000000306711623517156030560 0ustar package org.springframework.security.ui.portlet; import java.util.Arrays; import javax.portlet.PortletRequest; import org.springframework.security.GrantedAuthority; import org.springframework.security.MutableGrantedAuthoritiesContainer; import org.springframework.util.Assert; public class PortletPreAuthenticatedAuthenticationDetails extends PortletAuthenticationDetails implements MutableGrantedAuthoritiesContainer { private GrantedAuthority[] preAuthenticatedGrantedAuthorities = null; public PortletPreAuthenticatedAuthenticationDetails(PortletRequest request) { super(request); } public GrantedAuthority[] getGrantedAuthorities() { Assert.notNull(preAuthenticatedGrantedAuthorities, "Pre-authenticated granted authorities have not been set"); GrantedAuthority[] result = new GrantedAuthority[preAuthenticatedGrantedAuthorities.length]; System.arraycopy(preAuthenticatedGrantedAuthorities, 0, result, 0, result.length); return result; } public void setGrantedAuthorities(GrantedAuthority[] authorities) { this.preAuthenticatedGrantedAuthorities = new GrantedAuthority[authorities.length]; System.arraycopy(authorities, 0, preAuthenticatedGrantedAuthorities, 0, preAuthenticatedGrantedAuthorities.length); } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString() + "; "); sb.append("preAuthenticatedGrantedAuthorities: " + Arrays.asList(preAuthenticatedGrantedAuthorities)); return sb.toString(); } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/ui/portlet/PortletAuthenticationDetails.javaspring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/ui/portlet/P0000644000000000000000000000211411623517156030550 0ustar package org.springframework.security.ui.portlet; import java.io.Serializable; import java.util.Map; import javax.portlet.PortletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class PortletAuthenticationDetails implements Serializable { //~ Instance fields ================================================================================================ protected final Log logger = LogFactory.getLog(PortletAuthenticationDetails.class); protected Map userInfo; //~ Constructors =================================================================================================== public PortletAuthenticationDetails(PortletRequest request) { try { userInfo = (Map)request.getAttribute(PortletRequest.USER_INFO); } catch (Exception e) { logger.warn("unable to retrieve USER_INFO map from portlet request", e); } } public Map getUserInfo() { return userInfo; } public String toString() { return "User info: " + userInfo; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/ui/portlet/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/ui/portlet/p0000644000000000000000000000020511623517156030607 0ustar Authentication interceptor (and related classes) for use with the Portlet 1.0 (JSR 168) Specification. ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/ui/portlet/PortletProcessingInterceptor.javaspring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/ui/portlet/P0000644000000000000000000003315711623517156030563 0ustar /* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.portlet; import java.io.IOException; import java.security.Principal; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.PortletRequest; import javax.portlet.PortletResponse; import javax.portlet.PortletSession; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationManager; import org.springframework.security.context.SecurityContext; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.ui.AuthenticationDetailsSource; import org.springframework.security.ui.AuthenticationDetailsSourceImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.web.portlet.HandlerInterceptor; import org.springframework.web.portlet.ModelAndView; /** *

This interceptor is responsible for processing portlet authentication requests. This * is the portlet equivalent of the AuthenticationProcessingFilter used for * traditional servlet-based web applications. It is applied to both ActionRequests * and RenderRequests alike. If authentication is successful, the resulting * {@link Authentication} object will be placed into the SecurityContext, which * is guaranteed to have already been created by an earlier interceptor. If authentication * fails, the AuthenticationException will be placed into the * APPLICATION_SCOPE of the PortletSession with the attribute defined * by {@link AbstractProcessingFilter#SPRING_SECURITY_LAST_EXCEPTION_KEY}.

* *

Some portals do not properly provide the identity of the current user via the * getRemoteUser() or getUserPrincipal() methods of the * PortletRequest. In these cases they sometimes make it available in the * USER_INFO map provided as one of the attributes of the request. If this is * the case in your portal, you can specify a list of USER_INFO attributes * to check for the username via the userNameAttributes property of this bean. * You can also completely override the {@link #getPrincipalFromRequest(PortletRequest)} * and {@link #getCredentialsFromRequest(PortletRequest)} methods to suit the particular * behavior of your portal.

* *

This interceptor will put the PortletRequest object into the * details property of the Authentication object that is sent * as a request to the AuthenticationManager. This is done so that the request * is available to classes like {@link ContainerPortletAuthoritiesPopulator} that need * access to information from the portlet container. The {@link PortletAuthenticationProvider} * will replace this with the USER_INFO map in the resulting Authentication * object.

* * @see org.springframework.security.ui.AbstractProcessingFilter * @see org.springframework.security.ui.webapp.AuthenticationProcessingFilter * @author John A. Lewis * @since 2.0 * @version $Id$ */ public class PortletProcessingInterceptor implements HandlerInterceptor, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(PortletProcessingInterceptor.class); //~ Instance fields ================================================================================================ private AuthenticationManager authenticationManager; private List userNameAttributes; private AuthenticationDetailsSource authenticationDetailsSource; private boolean useAuthTypeAsCredentials = false; public PortletProcessingInterceptor() { authenticationDetailsSource = new AuthenticationDetailsSourceImpl(); ((AuthenticationDetailsSourceImpl)authenticationDetailsSource).setClazz(PortletAuthenticationDetails.class); } //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(authenticationManager, "An AuthenticationManager must be set"); } public boolean preHandleAction(ActionRequest request, ActionResponse response, Object handler) throws Exception { return preHandle(request, response, handler); } public boolean preHandleRender(RenderRequest request, RenderResponse response, Object handler) throws Exception { return preHandle(request, response, handler); } public void postHandleRender(RenderRequest request, RenderResponse response, Object handler, ModelAndView modelAndView) throws Exception { } public void afterActionCompletion(ActionRequest request, ActionResponse response, Object handler, Exception ex) throws Exception { } public void afterRenderCompletion(RenderRequest request, RenderResponse response, Object handler, Exception ex) throws Exception { } /** * Common preHandle method for both the action and render phases of the interceptor. */ private boolean preHandle(PortletRequest request, PortletResponse response, Object handler) throws Exception { // get the SecurityContext SecurityContext ctx = SecurityContextHolder.getContext(); if (logger.isDebugEnabled()) logger.debug("Checking secure context token: " + ctx.getAuthentication()); // if there is no existing Authentication object, then lets create one if (ctx.getAuthentication() == null) { try { // build the authentication request from the PortletRequest PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken( getPrincipalFromRequest(request), getCredentialsFromRequest(request)); // put the PortletRequest into the authentication request as the "details" authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); if (logger.isDebugEnabled()) logger.debug("Beginning authentication request for user '" + authRequest.getName() + "'"); onPreAuthentication(request, response); // ask the authentication manager to authenticate the request // it will throw an AuthenticationException if it fails, otherwise it succeeded Authentication authResult = authenticationManager.authenticate(authRequest); // process a successful authentication if (logger.isDebugEnabled()) { logger.debug("Authentication success: " + authResult); } ctx.setAuthentication(authResult); onSuccessfulAuthentication(request, response, authResult); } catch (AuthenticationException failed) { // process an unsuccessful authentication if (logger.isDebugEnabled()) { logger.debug("Authentication failed - updating ContextHolder to contain null Authentication", failed); } ctx.setAuthentication(null); request.getPortletSession().setAttribute( AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY, failed, PortletSession.APPLICATION_SCOPE); onUnsuccessfulAuthentication(request, response, failed); } } return true; } /** * This method attempts to extract a principal from the portlet request. * According to the JSR 168 spec, the PortletRequest should return the name * of the user in the getRemoteUser() method. It should also provide a * java.security.Principal object from the getUserPrincipal() * method. We will first try these to come up with a valid username. *

Unfortunately, some portals do not properly return these values for authenticated * users. So, if neither of those succeeds and if the userNameAttributes * property has been populated, then we will search through the USER_INFO * map from the request to see if we can find a valid username. *

This method can be overridden by subclasses to provide special handling * for portals with weak support for the JSR 168 spec.

* @param request the portlet request object * @return the determined principal object, or null if none found */ protected Object getPrincipalFromRequest(PortletRequest request) { // first try getRemoteUser() String remoteUser = request.getRemoteUser(); if (remoteUser != null) { return remoteUser; } // next try getUserPrincipal() Principal userPrincipal = request.getUserPrincipal(); if (userPrincipal != null) { String userPrincipalName = userPrincipal.getName(); if (userPrincipalName != null) { return userPrincipalName; } } // last try entries in USER_INFO if any attributes were defined if (this.userNameAttributes != null) { Map userInfo = null; try { userInfo = (Map)request.getAttribute(PortletRequest.USER_INFO); } catch (Exception e) { logger.warn("unable to retrieve USER_INFO map from portlet request", e); } if (userInfo != null) { Iterator i = this.userNameAttributes.iterator(); while(i.hasNext()) { Object principal = (String)userInfo.get(i.next()); if (principal != null) { return principal; } } } } // none found so return null return null; } /** * This method attempts to extract a credentials from the portlet request. * We are trusting the portal framework to authenticate the user, so all * we are really doing is trying to put something intelligent in here to * indicate the user is authenticated. According to the JSR 168 spec, * PortletRequest.getAuthType() should return a non-null value if the * user is authenticated and should be null if not authenticated. So we * will use this as the credentials and the token will be trusted as * authenticated if the credentials are not null. *

This method can be overridden by subclasses to provide special handling * for portals with weak support for the JSR 168 spec. If that is done, * be sure the value is non-null for authenticated users and null for * non-authenticated users.

* @param request the portlet request object * @return the determined credentials object, or null if none found */ protected Object getCredentialsFromRequest(PortletRequest request) { if (useAuthTypeAsCredentials) { return request.getAuthType(); } return "dummy"; } /** * Callback for custom processing prior to the authentication attempt. * @param request the portlet request to be authenticated * @param response the portlet response to be authenticated * @throws AuthenticationException to indicate that authentication attempt is not valid and should be terminated * @throws IOException */ protected void onPreAuthentication(PortletRequest request, PortletResponse response) throws AuthenticationException, IOException {} /** * Callback for custom processing after a successful authentication attempt. * @param request the portlet request that was authenticated * @param response the portlet response that was authenticated * @param authResult the resulting Authentication object * @throws IOException */ protected void onSuccessfulAuthentication(PortletRequest request, PortletResponse response, Authentication authResult) throws IOException {} /** * Callback for custom processing after an unsuccessful authentication attempt. * @param request the portlet request that failed authentication * @param response the portlet response that failed authentication * @param failed the AuthenticationException that occurred * @throws IOException */ protected void onUnsuccessfulAuthentication(PortletRequest request, PortletResponse response, AuthenticationException failed) throws IOException {} public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } public void setUserNameAttributes(List userNameAttributes) { this.userNameAttributes = userNameAttributes; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { this.authenticationDetailsSource = authenticationDetailsSource; } /** * It true, the "authType" proerty of the PortletRequest will be used as the credentials. * Defaults to false. * * @param useAuthTypeAsCredentials */ public void setUseAuthTypeAsCredentials(boolean useAuthTypeAsCredentials) { this.useAuthTypeAsCredentials = useAuthTypeAsCredentials; } } ././@LongLink0000000000000000000000000000023300000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/ui/portlet/PortletPreAuthenticatedAuthenticationDetailsSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/ui/portlet/P0000644000000000000000000000164711623517156030562 0ustar package org.springframework.security.ui.portlet; import java.util.ArrayList; import javax.portlet.PortletRequest; import org.springframework.security.ui.preauth.j2ee.AbstractPreAuthenticatedAuthenticationDetailsSource; public class PortletPreAuthenticatedAuthenticationDetailsSource extends AbstractPreAuthenticatedAuthenticationDetailsSource { public PortletPreAuthenticatedAuthenticationDetailsSource() { setClazz(PortletPreAuthenticatedAuthenticationDetails.class); } protected String[] getUserRoles(Object context, String[] mappableRoles) { ArrayList portletRoles = new ArrayList(); for (int i = 0; i < mappableRoles.length; i++) { if (((PortletRequest)context).isUserInRole(mappableRoles[i])) { portletRoles.add(mappableRoles[i]); } } return (String[]) portletRoles.toArray(new String[portletRoles.size()]); } } spring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/context/0000755000000000000000000000000011623517156030006 5ustar ././@LongLink0000000000000000000000000000022100000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/context/PortletSessionContextIntegrationInterceptor.javaspring-security-2.0.7.RELEASE/dist/spring-security-portlet/org/springframework/security/context/Port0000644000000000000000000005042211623517156030660 0ustar /* * Copyright 2005-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.context; import java.lang.reflect.Method; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.PortletException; import javax.portlet.PortletRequest; import javax.portlet.PortletResponse; import javax.portlet.PortletSession; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import org.springframework.web.portlet.HandlerInterceptor; import org.springframework.web.portlet.ModelAndView; /** *

This interceptor populates the {@link SecurityContextHolder} with information obtained from the * PortletSession. It is applied to both ActionRequests and * RenderRequests

* *

The PortletSession will be queried to retrieve the SecurityContext that should * be stored against the SecurityContextHolder for the duration of the portlet request. At the * end of the request, any updates made to the SecurityContextHolder will be persisted back to the * PortletSession by this interceptor.

* *

If a valid SecurityContext cannot be obtained from the PortletSession for * whatever reason, a fresh SecurityContext will be created and used instead. The created object * will be of the instance defined by the {@link #setContext(Class)} method (which defaults to * {@link org.springframework.security.context.SecurityContextImpl}.

* *

A PortletSession may be created by this interceptor if one does not already exist. If at the * end of the portlet request the PortletSession does not exist, one will only be created if * the current contents of the SecurityContextHolder are not the {@link java.lang.Object#equals} * to a new instance of {@link #context}. This avoids needless PortletSession creation, * and automates the storage of changes made to the SecurityContextHolder. There is one exception to * this rule, that is if the {@link #forceEagerSessionCreation} property is true, in which case * sessions will always be created irrespective of normal session-minimization logic (the default is * false, as this is resource intensive and not recommended).

* *

If for whatever reason no PortletSession should ever be created, the * {@link #allowSessionCreation} property should be set to false. Only do this if you really need * to conserve server memory and ensure all classes using the SecurityContextHolder are designed to * have no persistence of the SecurityContext between web requests. Please note that if * {@link #forceEagerSessionCreation} is true, the allowSessionCreation must also be * true (setting it to false will cause a startup-time error).

*

This interceptor must be executed before

any authentication processing mechanisms. These * mechanisms (specifically {@link org.springframework.security.ui.portlet.PortletProcessingInterceptor}) expect the * SecurityContextHolder to contain a valid SecurityContext by the time they execute.

* *

An important nuance to this interceptor is that (by default) the SecurityContext is stored * into the APPLICATION_SCOPE of the PortletSession. This doesn't just mean you will be * sharing it with all the other portlets in your webapp (which is generally a good idea). It also means that (if * you have done all the other appropriate magic), you will share this SecurityContext with servlets in * your webapp. This is very useful if you have servlets serving images or processing AJAX calls from your portlets * since they can now use the {@link HttpSessionContextIntegrationFilter} to access the same SecurityContext * object from the session. This allows these calls to be secured as well as the portlet calls.

* * Much of the logic of this interceptor comes from the {@link HttpSessionContextIntegrationFilter} class which * fills the same purpose on the servlet side. Ben Alex and Patrick Burlson are listed as authors here because they * are the authors of that class and there are blocks of code that essentially identical between the two. (Making this * a good candidate for refactoring someday.) * *

Unlike HttpSessionContextIntegrationFilter, this interceptor does not check to see if it is * getting applied multiple times. This shouldn't be a problem since the application of interceptors is under the * control of the Spring Portlet MVC framework and tends to be more explicit and more predictable than the application * of filters. However, you should still be careful to only apply this inteceptor to your request once.

* * @author John A. Lewis * @author Ben Alex * @author Patrick Burleson * @since 2.0 * @version $Id$ */ public class PortletSessionContextIntegrationInterceptor implements InitializingBean, HandlerInterceptor { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(PortletSessionContextIntegrationInterceptor.class); public static final String SPRING_SECURITY_CONTEXT_KEY = HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY; private static final String SESSION_EXISTED = PortletSessionContextIntegrationInterceptor.class.getName() + ".SESSION_EXISTED"; private static final String CONTEXT_HASHCODE = PortletSessionContextIntegrationInterceptor.class.getName() + ".CONTEXT_HASHCODE"; //~ Instance fields ================================================================================================ private Class context = SecurityContextImpl.class; private Object contextObject; /** * Indicates if this interceptor can create a PortletSession if * needed (sessions are always created sparingly, but setting this value to * false will prohibit sessions from ever being created). * Defaults to true. Do not set to false if * you are have set {@link #forceEagerSessionCreation} to true, * as the properties would be in conflict. */ private boolean allowSessionCreation = true; /** * Indicates if this interceptor is required to create a PortletSession * for every request before proceeding through the request process, even if the * PortletSession would not ordinarily have been created. By * default this is false, which is entirely appropriate for * most circumstances as you do not want a PortletSession * created unless the interceptor actually needs one. It is envisaged the main * situation in which this property would be set to true is * if using other interceptors that depend on a PortletSession * already existing. This is only required in specialized cases, so leave it set to * false unless you have an actual requirement and aware of the * session creation overhead. */ private boolean forceEagerSessionCreation = false; /** * Indicates whether the SecurityContext will be cloned from * the PortletSession. The default is to simply reference * (the default is false). The default may cause issues if * concurrent threads need to have a different security identity from other * threads being concurrently processed that share the same * PortletSession. In most normal environments this does not * represent an issue, as changes to the security identity in one thread is * allowed to affect the security identity in other threads associated with * the same PortletSession. For unusual cases where this is not * permitted, change this value to true and ensure the * {@link #context} is set to a SecurityContext that * implements {@link Cloneable} and overrides the clone() * method. */ private boolean cloneFromPortletSession = false; /** * Indicates wether the APPLICATION_SCOPE mode of the * PortletSession should be used for storing the * SecurityContext. The default is
true
. * This allows it to be shared between the portlets in the webapp and * potentially with servlets in the webapp as well. If this is set to * false, then the PORTLET_SCOPE will be used * instead. */ private boolean useApplicationScopePortletSession = true; //~ Constructors =================================================================================================== public PortletSessionContextIntegrationInterceptor() throws PortletException { this.contextObject = generateNewContext(); } //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { // check that the value of context is legal if ((this.context == null) || (!SecurityContext.class.isAssignableFrom(this.context))) { throw new IllegalArgumentException("context must be defined and implement SecurityContext " + "(typically use org.springframework.security.context.SecurityContextImpl; existing class is " + this.context + ")"); } // check that session creation options make sense if ((forceEagerSessionCreation == true) && (allowSessionCreation == false)) { throw new IllegalArgumentException( "If using forceEagerSessionCreation, you must set allowSessionCreation to also be true"); } } public boolean preHandleAction(ActionRequest request, ActionResponse response, Object handler) throws Exception { // call to common preHandle method return preHandle(request, response, handler); } public boolean preHandleRender(RenderRequest request, RenderResponse response, Object handler) throws Exception { // call to common preHandle method return preHandle(request, response, handler); } public void postHandleRender(RenderRequest request, RenderResponse response, Object handler, ModelAndView modelAndView) throws Exception { // no-op } public void afterActionCompletion(ActionRequest request, ActionResponse response, Object handler, Exception ex) throws Exception { // call to common afterCompletion method afterCompletion(request, response, handler, ex); } public void afterRenderCompletion(RenderRequest request, RenderResponse response, Object handler, Exception ex) throws Exception { // call to common afterCompletion method afterCompletion(request, response, handler, ex); } private boolean preHandle(PortletRequest request, PortletResponse response, Object handler) throws Exception { PortletSession portletSession = null; boolean portletSessionExistedAtStartOfRequest = false; // see if the portlet session already exists (or should be eagerly created) try { portletSession = request.getPortletSession(forceEagerSessionCreation); } catch (IllegalStateException ignored) {} // if there is a session, then see if there is a context to bring in if (portletSession != null) { // remember that the session already existed portletSessionExistedAtStartOfRequest = true; // attempt to retrieve the context from the session Object contextFromSessionObject = portletSession.getAttribute(SPRING_SECURITY_CONTEXT_KEY, portletSessionScope()); // if we got a context then place it into the holder if (contextFromSessionObject != null) { // if we are supposed to clone it, then do so if (cloneFromPortletSession) { Assert.isInstanceOf(Cloneable.class, contextFromSessionObject, "Context must implement Clonable and provide a Object.clone() method"); try { Method m = contextFromSessionObject.getClass().getMethod("clone", new Class[] {}); if (!m.isAccessible()) { m.setAccessible(true); } contextFromSessionObject = m.invoke(contextFromSessionObject, new Object[] {}); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } // if what we got is a valid context then place it into the holder, otherwise create a new one if (contextFromSessionObject instanceof SecurityContext) { if (logger.isDebugEnabled()) logger.debug("Obtained from SPRING_SECURITY_CONTEXT a valid SecurityContext and " + "set to SecurityContextHolder: '" + contextFromSessionObject + "'"); SecurityContextHolder.setContext((SecurityContext) contextFromSessionObject); } else { if (logger.isWarnEnabled()) logger.warn("SPRING_SECURITY_CONTEXT did not contain a SecurityContext but contained: '" + contextFromSessionObject + "'; are you improperly modifying the PortletSession directly " + "(you should always use SecurityContextHolder) or using the PortletSession attribute " + "reserved for this class? - new SecurityContext instance associated with " + "SecurityContextHolder"); SecurityContextHolder.setContext(generateNewContext()); } } else { // there was no context in the session, so create a new context and put it in the holder if (logger.isDebugEnabled()) logger.debug("PortletSession returned null object for SPRING_SECURITY_CONTEXT - new " + "SecurityContext instance associated with SecurityContextHolder"); SecurityContextHolder.setContext(generateNewContext()); } } else { // there was no session, so create a new context and place it in the holder if (logger.isDebugEnabled()) logger.debug("No PortletSession currently exists - new SecurityContext instance " + "associated with SecurityContextHolder"); SecurityContextHolder.setContext(generateNewContext()); } // place attributes onto the request to remember if the session existed and the hashcode of the context request.setAttribute(SESSION_EXISTED, new Boolean(portletSessionExistedAtStartOfRequest)); request.setAttribute(CONTEXT_HASHCODE, new Integer(SecurityContextHolder.getContext().hashCode())); return true; } private void afterCompletion(PortletRequest request, PortletResponse response, Object handler, Exception ex) throws Exception { PortletSession portletSession = null; // retrieve the attributes that remember if the session existed and the hashcode of the context boolean portletSessionExistedAtStartOfRequest = ((Boolean)request.getAttribute(SESSION_EXISTED)).booleanValue(); int oldContextHashCode = ((Integer)request.getAttribute(CONTEXT_HASHCODE)).intValue(); // try to retrieve an existing portlet session try { portletSession = request.getPortletSession(false); } catch (IllegalStateException ignored) {} // if there is now no session but there was one at the beginning then it must have been invalidated if ((portletSession == null) && portletSessionExistedAtStartOfRequest) { if (logger.isDebugEnabled()) logger.debug("PortletSession is now null, but was not null at start of request; " + "session was invalidated, so do not create a new session"); } // create a new portlet session if we need to if ((portletSession == null) && !portletSessionExistedAtStartOfRequest) { // if we're not allowed to create a new session, then report that if (!allowSessionCreation) { if (logger.isDebugEnabled()) logger.debug("The PortletSession is currently null, and the " + "PortletSessionContextIntegrationInterceptor is prohibited from creating a PortletSession " + "(because the allowSessionCreation property is false) - SecurityContext thus not " + "stored for next request"); } // if the context was changed during the request, then go ahead and create a session else if (!contextObject.equals(SecurityContextHolder.getContext())) { if (logger.isDebugEnabled()) logger.debug("PortletSession being created as SecurityContextHolder contents are non-default"); try { portletSession = request.getPortletSession(true); } catch (IllegalStateException ignored) {} } // if nothing in the context changed, then don't bother to create a session else { if (logger.isDebugEnabled()) logger.debug("PortletSession is null, but SecurityContextHolder has not changed from default: ' " + SecurityContextHolder.getContext() + "'; not creating PortletSession or storing SecurityContextHolder contents"); } } // if the session exists and the context has changes, then store the context back into the session if ((portletSession != null) && (SecurityContextHolder.getContext().hashCode() != oldContextHashCode)) { portletSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext(), portletSessionScope()); if (logger.isDebugEnabled()) logger.debug("SecurityContext stored to PortletSession: '" + SecurityContextHolder.getContext() + "'"); } // remove the contents of the holder SecurityContextHolder.clearContext(); if (logger.isDebugEnabled()) logger.debug("SecurityContextHolder set to new context, as request processing completed"); } /** * Creates a new SecurityContext object. The specific class is * determined by the setting of the {@link #context} property. * @return the new SecurityContext * @throws PortletException if the creation throws an InstantiationException or * an IllegalAccessException, then this method will wrap them in a * PortletException */ public SecurityContext generateNewContext() throws PortletException { try { return (SecurityContext) this.context.newInstance(); } catch (InstantiationException ie) { throw new PortletException(ie); } catch (IllegalAccessException iae) { throw new PortletException(iae); } } private int portletSessionScope() { // return the appropriate scope setting based on our property value return (this.useApplicationScopePortletSession ? PortletSession.APPLICATION_SCOPE : PortletSession.PORTLET_SCOPE); } public Class getContext() { return context; } public void setContext(Class secureContext) { this.context = secureContext; } public boolean isAllowSessionCreation() { return allowSessionCreation; } public void setAllowSessionCreation(boolean allowSessionCreation) { this.allowSessionCreation = allowSessionCreation; } public boolean isForceEagerSessionCreation() { return forceEagerSessionCreation; } public void setForceEagerSessionCreation(boolean forceEagerSessionCreation) { this.forceEagerSessionCreation = forceEagerSessionCreation; } public boolean isCloneFromPortletSession() { return cloneFromPortletSession; } public void setCloneFromPortletSession(boolean cloneFromPortletSession) { this.cloneFromPortletSession = cloneFromPortletSession; } public boolean isUseApplicationScopePortletSession() { return useApplicationScopePortletSession; } public void setUseApplicationScopePortletSession( boolean useApplicationScopePortletSession) { this.useApplicationScopePortletSession = useApplicationScopePortletSession; } } spring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/0000755000000000000000000000000011766764113021020 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/META-INF/0000755000000000000000000000000011623521762022151 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/META-INF/MANIFEST.MF0000644000000000000000000000014311623521760023577 0ustar Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: 20.1-b02-384 (Apple Inc.) spring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/0000755000000000000000000000000011623517156021602 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/0000755000000000000000000000000011623517156025022 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/0000755000000000000000000000000011623517156026671 5ustar ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/annotation/spring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/annotatio0000755000000000000000000000000011623517156030606 5ustar ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/annotation/SecuredMethodDefinitionSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/annotatio0000644000000000000000000000347311623517156030617 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.annotation; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Collection; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.method.AbstractFallbackMethodDefinitionSource; /** * Sources method security metadata from Spring Security's {@link Secured} annotation. * * @author Ben Alex * @version $Id$ */ public class SecuredMethodDefinitionSource extends AbstractFallbackMethodDefinitionSource { protected ConfigAttributeDefinition findAttributes(Class clazz) { return processAnnotation(clazz.getAnnotation(Secured.class)); } protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) { return processAnnotation(AnnotationUtils.findAnnotation(method, Secured.class)); } public Collection getConfigAttributeDefinitions() { return null; } private ConfigAttributeDefinition processAnnotation(Annotation a) { if (a == null || !(a instanceof Secured)) { return null; } Secured secured = (Secured) a; return new ConfigAttributeDefinition(secured.value()); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/annotation/Jsr250Voter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/annotatio0000644000000000000000000000446011623517156030614 0ustar package org.springframework.security.annotation; import org.springframework.security.GrantedAuthority; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.Authentication; import org.springframework.security.vote.AccessDecisionVoter; import java.util.Iterator; /** * Voter on JSR-250 configuration attributes. * * @author Ryan Heaton * @since 2.0 */ public class Jsr250Voter implements AccessDecisionVoter { /** * The specified config attribute is supported if its an instance of a {@link Jsr250SecurityConfig}. * * @param configAttribute The config attribute. * @return whether the config attribute is supported. */ public boolean supports(ConfigAttribute configAttribute) { return configAttribute instanceof Jsr250SecurityConfig; } /** * All classes are supported. * * @param clazz the class. * @return true */ public boolean supports(Class clazz) { return true; } /** * Votes according to JSR 250. * * @param authentication The authentication object. * @param object The access object. * @param definition The configuration definition. * @return The vote. */ public int vote(Authentication authentication, Object object, ConfigAttributeDefinition definition) { int result = ACCESS_ABSTAIN; Iterator iter = definition.getConfigAttributes().iterator(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (Jsr250SecurityConfig.PERMIT_ALL_ATTRIBUTE.equals(attribute)) { return ACCESS_GRANTED; } if (Jsr250SecurityConfig.DENY_ALL_ATTRIBUTE.equals(attribute)) { return ACCESS_DENIED; } if (supports(attribute)) { result = ACCESS_DENIED; // Attempt to find a matching granted authority for (GrantedAuthority authority : authentication.getAuthorities()) { if (attribute.getAttribute().equals(authority.getAuthority())) { return ACCESS_GRANTED; } } } } return result; } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/annotation/Secured.javaspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/annotatio0000644000000000000000000000353011623517156030611 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Java 5 annotation for describing service layer security attributes. * *

The Secured annotation is used to define a list of security * configuration attributes for business methods. This annotation can be used * as a Java 5 alternative to XML configuration. *

For example: *

 *     @Secured ({"ROLE_USER"})
 *     public void create(Contact contact);
 *
 *     @Secured ({"ROLE_USER", "ROLE_ADMIN"})
 *     public void update(Contact contact);
 *
 *     @Secured ({"ROLE_ADMIN"})
 *     public void delete(Contact contact);
 * 
* @author Mark St.Godard * @version $Id$ */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Secured { /** * Returns the list of security configuration attributes. * (i.e. ROLE_USER, ROLE_ADMIN etc.) * @return String[] The secure method attributes */ public String[] value(); } ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/annotation/Jsr250MethodDefinitionSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/annotatio0000644000000000000000000000473011623517156030614 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.annotation; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.annotation.security.DenyAll; import javax.annotation.security.PermitAll; import javax.annotation.security.RolesAllowed; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.method.AbstractFallbackMethodDefinitionSource; /** * Sources method security metadata from major JSR 250 security annotations. * * @author Ben Alex * @version $Id$ * @since 2.0 */ public class Jsr250MethodDefinitionSource extends AbstractFallbackMethodDefinitionSource { protected ConfigAttributeDefinition findAttributes(Class clazz) { return processAnnotations(clazz.getAnnotations()); } protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) { return processAnnotations(AnnotationUtils.getAnnotations(method)); } public Collection getConfigAttributeDefinitions() { return null; } private ConfigAttributeDefinition processAnnotations(Annotation[] annotations) { if (annotations == null || annotations.length == 0) { return null; } for (Annotation a: annotations) { if (a instanceof DenyAll) { return new ConfigAttributeDefinition(Jsr250SecurityConfig.DENY_ALL_ATTRIBUTE); } if (a instanceof PermitAll) { return new ConfigAttributeDefinition(Jsr250SecurityConfig.PERMIT_ALL_ATTRIBUTE); } if (a instanceof RolesAllowed) { RolesAllowed ra = (RolesAllowed) a; List attributes = new ArrayList(); for (String allowed : ra.value()) { attributes.add(new Jsr250SecurityConfig(allowed)); } return new ConfigAttributeDefinition(attributes); } } return null; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/annotation/Jsr250SecurityConfig.javaspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/org/springframework/security/annotatio0000644000000000000000000000124511623517156030612 0ustar package org.springframework.security.annotation; import org.springframework.security.SecurityConfig; import javax.annotation.security.PermitAll; import javax.annotation.security.DenyAll; /** * Security config applicable as a JSR 250 annotation attribute. * * @author Ryan Heaton * @since 2.0 */ public class Jsr250SecurityConfig extends SecurityConfig { public static final Jsr250SecurityConfig PERMIT_ALL_ATTRIBUTE = new Jsr250SecurityConfig(PermitAll.class.getName()); public static final Jsr250SecurityConfig DENY_ALL_ATTRIBUTE = new Jsr250SecurityConfig(DenyAll.class.getName()); public Jsr250SecurityConfig(String role) { super(role); } }././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/core-tiger.src.main.resources.placeholderspring-security-2.0.7.RELEASE/dist/spring-security-core-tiger/core-tiger.src.main.resources.placehol0000644000000000000000000000000011623517156030274 0ustar spring-security-2.0.7.RELEASE/dist/spring-security-ntlm/0000755000000000000000000000000011766764113017732 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-ntlm/META-INF/0000755000000000000000000000000011623521764021065 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-ntlm/META-INF/MANIFEST.MF0000644000000000000000000000014311623521762022513 0ustar Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: 20.1-b02-384 (Apple Inc.) spring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/0000755000000000000000000000000011623517156020514 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/0000755000000000000000000000000011623517156023734 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/0000755000000000000000000000000011623517156025603 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/0000755000000000000000000000000011623517156026220 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/0000755000000000000000000000000011623517156027172 5ustar ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/NtlmProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/NtlmPro0000644000000000000000000005374611623517156030527 0ustar /* Copyright 2004-2007 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.ntlm; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationCredentialsNotFoundException; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationManager; import org.springframework.security.BadCredentialsException; import org.springframework.security.InsufficientAuthenticationException; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; import org.springframework.security.ui.SpringSecurityFilter; import org.springframework.security.ui.FilterChainOrder; import org.springframework.security.ui.AuthenticationDetailsSource; import org.springframework.security.ui.WebAuthenticationDetailsSource; import org.springframework.security.ui.webapp.AuthenticationProcessingFilter; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import jcifs.Config; import jcifs.UniAddress; import jcifs.ntlmssp.Type1Message; import jcifs.ntlmssp.Type2Message; import jcifs.ntlmssp.Type3Message; import jcifs.smb.NtlmChallenge; import jcifs.smb.NtlmPasswordAuthentication; import jcifs.smb.SmbAuthException; import jcifs.smb.SmbException; import jcifs.smb.SmbSession; import jcifs.util.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.net.UnknownHostException; import java.util.Enumeration; import java.util.Properties; /** * A clean-room implementation for Spring Security of an NTLM HTTP filter * leveraging the JCIFS library. *

* NTLM is a Microsoft-developed protocol providing single sign-on capabilities * to web applications and other integrated applications. It allows a web * server to automatically discover the username of a browser client when that * client is logged into a Windows domain and is using an NTLM-aware browser. * A web application can then reuse the user's Windows credentials without * having to ask for them again. *

* Because NTLM only provides the username of the Windows client, a Spring * Security NTLM deployment must have a UserDetailsService that * provides a UserDetails object with the empty string as the * password and whatever GrantedAuthority values necessary to * pass the FilterSecurityInterceptor. *

* The Spring Security bean configuration file must also place the * ExceptionTranslationFilter before this filter in the * FilterChainProxy definition. * * @author Davide Baroncelli * @author Edward Smith * @version $Id$ */ public class NtlmProcessingFilter extends SpringSecurityFilter implements InitializingBean { //~ Static fields/initializers ===================================================================================== private static Log logger = LogFactory.getLog(NtlmProcessingFilter.class); private static final String STATE_ATTR = "SpringSecurityNtlm"; private static final String CHALLENGE_ATTR = "NtlmChal"; private static final Integer BEGIN = new Integer(0); private static final Integer NEGOTIATE = new Integer(1); private static final Integer COMPLETE = new Integer(2); private static final Integer DELAYED = new Integer(3); //~ Instance fields ================================================================================================ /** Should the filter load balance among multiple domain controllers, default false */ private boolean loadBalance; /** Should the domain name be stripped from the username, default true */ private boolean stripDomain = true; /** Should the filter initiate NTLM negotiations, default true */ private boolean forceIdentification = true; /** Should the filter retry NTLM on authorization failure, default false */ private boolean retryOnAuthFailure; private String soTimeout; private String cachePolicy; private String defaultDomain; private String domainController; private AuthenticationManager authenticationManager; private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); //~ Methods ======================================================================================================== /** * Ensures an AuthenticationManager and authentication failure * URL have been provided in the bean configuration file. */ public void afterPropertiesSet() throws Exception { Assert.notNull(this.authenticationManager, "An AuthenticationManager is required"); // Default to 5 minutes if not already specified Config.setProperty("jcifs.smb.client.soTimeout", soTimeout == null ? "300000" : soTimeout); // Default to 20 minutes if not already specified Config.setProperty("jcifs.netbios.cachePolicy", cachePolicy == null ? "1200" : cachePolicy); if (domainController == null) { domainController = defaultDomain; } } /** * Sets the AuthenticationManager to use. * * @param authenticationManager the AuthenticationManager to use. */ public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } /** * The NT domain against which clients should be authenticated. If the SMB * client username and password are also set, then preauthentication will * be used which is necessary to initialize the SMB signing digest. SMB * signatures are required by default on Windows 2003 domain controllers. * * @param defaultDomain The name of the default domain. */ public void setDefaultDomain(String defaultDomain) { this.defaultDomain = defaultDomain; Config.setProperty("jcifs.smb.client.domain", defaultDomain); } /** * Sets the SMB client username. * * @param smbClientUsername The SMB client username. */ public void setSmbClientUsername(String smbClientUsername) { Config.setProperty("jcifs.smb.client.username", smbClientUsername); } /** * Sets the SMB client password. * * @param smbClientPassword The SMB client password. */ public void setSmbClientPassword(String smbClientPassword) { Config.setProperty("jcifs.smb.client.password", smbClientPassword); } /** * Sets the SMB client SSN limit. When set to 1, every * authentication is forced to use a separate transport. This effectively * ignores SMB signing requirements, however at the expense of reducing * scalability. Preauthentication with a domain, username, and password is * the preferred method for working with servers that require signatures. * * @param smbClientSSNLimit The SMB client SSN limit. */ public void setSmbClientSSNLimit(String smbClientSSNLimit) { Config.setProperty("jcifs.smb.client.ssnLimit", smbClientSSNLimit); } /** * Configures JCIFS to use a WINS server. It is preferred to use a WINS * server over a specific domain controller. Set this property instead of * domainController if there is a WINS server available. * * @param netbiosWINS The WINS server JCIFS will use. */ public void setNetbiosWINS(String netbiosWINS) { Config.setProperty("jcifs.netbios.wins", netbiosWINS); } /** * The IP address of any SMB server that should be used to authenticate * HTTP clients. * * @param domainController The IP address of the domain controller. */ public void setDomainController(String domainController) { this.domainController = domainController; } /** * If the default domain is specified and the domain controller is not * specified, then query for domain controllers by name. When load * balance is true, rotate through the list of domain * controllers when authenticating users. * * @param loadBalance The load balance flag value. */ public void setLoadBalance(boolean loadBalance) { this.loadBalance = loadBalance; } /** * Configures NtlmProcessingFilter to strip the Windows * domain name from the username when set to true, which * is the default value. * * @param stripDomain The strip domain flag value. */ public void setStripDomain(boolean stripDomain) { this.stripDomain = stripDomain; } /** * Sets the jcifs.smb.client.soTimeout property to the * timeout value specified in milliseconds. Defaults to 5 minutes * if not specified. * * @param timeout The milliseconds timeout value. */ public void setSoTimeout(String timeout) { this.soTimeout = timeout; } /** * Sets the jcifs.netbios.cachePolicy property to the * number of seconds a NetBIOS address is cached by JCIFS. Defaults to * 20 minutes if not specified. * * @param numSeconds The number of seconds a NetBIOS address is cached. */ public void setCachePolicy(String numSeconds) { this.cachePolicy = numSeconds; } /** * Loads properties starting with "jcifs" into the JCIFS configuration. * Any other properties are ignored. * * @param props The JCIFS properties to set. */ public void setJcifsProperties(Properties props) { String name; for (Enumeration e=props.keys(); e.hasMoreElements();) { name = (String) e.nextElement(); if (name.startsWith("jcifs.")) { Config.setProperty(name, props.getProperty(name)); } } } /** * Returns true if NTLM authentication is forced. * * @return true if NTLM authentication is forced. */ public boolean isForceIdentification() { return this.forceIdentification; } /** * Sets a flag denoting whether NTLM authentication should be forced. * * @param forceIdentification the force identification flag value to set. */ public void setForceIdentification(boolean forceIdentification) { this.forceIdentification = forceIdentification; } /** * Sets a flag denoting whether NTLM should retry whenever authentication * fails. Retry will occur if the credentials are rejected by the domain controller or if an * an {@link AuthenticationCredentialsNotFoundException} * or {@link InsufficientAuthenticationException} is thrown. * * @param retryOnFailure the retry on failure flag value to set. */ public void setRetryOnAuthFailure(boolean retryOnFailure) { this.retryOnAuthFailure = retryOnFailure; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "authenticationDetailsSource cannot be null"); this.authenticationDetailsSource = authenticationDetailsSource; } protected void doFilterHttp(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) throws IOException, ServletException { final HttpSession session = request.getSession(); Integer ntlmState = (Integer) session.getAttribute(STATE_ATTR); // Start NTLM negotiations the first time through the filter if (ntlmState == null) { if (forceIdentification) { logger.debug("Starting NTLM handshake"); session.setAttribute(STATE_ATTR, BEGIN); throw new NtlmBeginHandshakeException(); } else { logger.debug("NTLM handshake not yet started"); session.setAttribute(STATE_ATTR, DELAYED); } } // IE will send a Type 1 message to reauthenticate the user during an HTTP POST if (ntlmState == COMPLETE && this.reAuthOnIEPost(request)) ntlmState = BEGIN; final String authMessage = request.getHeader("Authorization"); if (ntlmState != COMPLETE && authMessage != null && authMessage.startsWith("NTLM ")) { final UniAddress dcAddress = this.getDCAddress(session); if (ntlmState == BEGIN) { logger.debug("Processing NTLM Type 1 Message"); session.setAttribute(STATE_ATTR, NEGOTIATE); this.processType1Message(authMessage, session, dcAddress); } else { logger.debug("Processing NTLM Type 3 Message"); final NtlmPasswordAuthentication auth = this.processType3Message(authMessage, session, dcAddress); logger.debug("NTLM negotiation complete"); this.logon(session, dcAddress, auth); session.setAttribute(STATE_ATTR, COMPLETE); // Do not reauthenticate the user in Spring Security during an IE POST final Authentication myCurrentAuth = SecurityContextHolder.getContext().getAuthentication(); if (myCurrentAuth == null || myCurrentAuth instanceof AnonymousAuthenticationToken) { logger.debug("Authenticating user credentials"); this.authenticate(request, response, session, auth); } } } chain.doFilter(request, response); } /** * Returns true if reauthentication is needed on an IE POST. */ private boolean reAuthOnIEPost(final HttpServletRequest request) { String ua = request.getHeader("User-Agent"); return (request.getMethod().equalsIgnoreCase("POST") && ua != null && ua.indexOf("MSIE") != -1); } /** * Creates and returns a Type 2 message from the provided Type 1 message. * * @param message the Type 1 message to process. * @param session the HTTPSession object. * @param dcAddress the domain controller address. * @throws IOException */ private void processType1Message(final String message, final HttpSession session, final UniAddress dcAddress) throws IOException { final Type2Message type2msg = new Type2Message( new Type1Message(Base64.decode(message.substring(5))), this.getChallenge(session, dcAddress), null); throw new NtlmType2MessageException(Base64.encode(type2msg.toByteArray())); } /** * Builds and returns an NtlmPasswordAuthentication object * from the provided Type 3 message. * * @param message the Type 3 message to process. * @param session the HTTPSession object. * @param dcAddress the domain controller address. * @return an NtlmPasswordAuthentication object. * @throws IOException */ private NtlmPasswordAuthentication processType3Message(final String message, final HttpSession session, final UniAddress dcAddress) throws IOException { final Type3Message type3msg = new Type3Message(Base64.decode(message.substring(5))); final byte[] lmResponse = (type3msg.getLMResponse() != null) ? type3msg.getLMResponse() : new byte[0]; final byte[] ntResponse = (type3msg.getNTResponse() != null) ? type3msg.getNTResponse() : new byte[0]; return new NtlmPasswordAuthentication( type3msg.getDomain(), type3msg.getUser(), this.getChallenge(session, dcAddress), lmResponse, ntResponse); } /** * Checks the user credentials against the domain controller. * * @param session the HTTPSession object. * @param dcAddress the domain controller address. * @param auth the NtlmPasswordAuthentication object. * @throws IOException */ private void logon(final HttpSession session, final UniAddress dcAddress, final NtlmPasswordAuthentication auth) throws IOException { try { SmbSession.logon(dcAddress, auth); if (logger.isDebugEnabled()) { logger.debug(auth + " successfully authenticated against " + dcAddress); } } catch(SmbAuthException e) { logger.error("Credentials " + auth + " were not accepted by the domain controller " + dcAddress); if (retryOnAuthFailure) { logger.debug("Restarting NTLM authentication handshake"); session.setAttribute(STATE_ATTR, BEGIN); throw new NtlmBeginHandshakeException(); } throw new BadCredentialsException("Bad NTLM credentials"); } finally { session.removeAttribute(CHALLENGE_ATTR); } } /** * Authenticates the user credentials acquired from NTLM against the Spring * Security AuthenticationManager. * * @param request the HttpServletRequest object. * @param response the HttpServletResponse object. * @param session the HttpSession object. * @param auth the NtlmPasswordAuthentication object. * @throws IOException */ private void authenticate(final HttpServletRequest request, final HttpServletResponse response, final HttpSession session, final NtlmPasswordAuthentication auth) throws IOException { final Authentication authResult; final UsernamePasswordAuthenticationToken authRequest; final Authentication backupAuth; authRequest = new NtlmUsernamePasswordAuthenticationToken(auth, stripDomain); authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); // Place the last username attempted into HttpSession for views session.setAttribute(AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY, authRequest.getName()); // Backup the current authentication in case of an AuthenticationException backupAuth = SecurityContextHolder.getContext().getAuthentication(); try { // Authenitcate the user with the authentication manager authResult = authenticationManager.authenticate(authRequest); } catch (AuthenticationException failed) { if (logger.isInfoEnabled()) { logger.info("Authentication request for user: " + authRequest.getName() + " failed: " + failed.toString()); } // Reset the backup Authentication object and rethrow the AuthenticationException SecurityContextHolder.getContext().setAuthentication(backupAuth); if (retryOnAuthFailure && (failed instanceof AuthenticationCredentialsNotFoundException || failed instanceof InsufficientAuthenticationException)) { logger.debug("Restart NTLM authentication handshake due to AuthenticationException"); session.setAttribute(STATE_ATTR, BEGIN); throw new NtlmBeginHandshakeException(); } throw failed; } // Set the Authentication object with the valid authentication result SecurityContextHolder.getContext().setAuthentication(authResult); } /** * Returns the domain controller address based on the loadBalance * setting. * * @param session the HttpSession object. * @return the domain controller address. * @throws UnknownHostException * @throws SmbException */ private UniAddress getDCAddress(final HttpSession session) throws UnknownHostException, SmbException { if (loadBalance) { NtlmChallenge chal = (NtlmChallenge) session.getAttribute(CHALLENGE_ATTR); if (chal == null) { chal = SmbSession.getChallengeForDomain(); session.setAttribute(CHALLENGE_ATTR, chal); } return chal.dc; } return UniAddress.getByName(domainController, true); } /** * Returns the domain controller challenge based on the loadBalance * setting. * * @param session the HttpSession object. * @param dcAddress the domain controller address. * @return the domain controller challenge. * @throws UnknownHostException * @throws SmbException */ private byte[] getChallenge(final HttpSession session, final UniAddress dcAddress) throws UnknownHostException, SmbException { if (loadBalance) { return ((NtlmChallenge) session.getAttribute(CHALLENGE_ATTR)).challenge; } return SmbSession.getChallenge(dcAddress); } public int getOrder() { return FilterChainOrder.NTLM_FILTER; } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/NtlmProcessingFilterEntryPoint.javaspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/NtlmPro0000644000000000000000000001115311623517156030511 0ustar /* Copyright 2004-2007 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.ntlm; import org.springframework.security.AuthenticationException; import org.springframework.security.ui.AuthenticationEntryPoint; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Used by ExceptionTranslationFilter to assist with the NTLM * negotiation. Also handles redirecting the user to the authentication * failure URL if an {@link AuthenticationException} that is not a subclass of * {@link NtlmBaseException} is received. * * @author Davide Baroncelli * @author Edward Smith * @version $Id$ */ public class NtlmProcessingFilterEntryPoint implements AuthenticationEntryPoint { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(NtlmProcessingFilterEntryPoint.class); //~ Instance fields ================================================================================================ /** Where to redirect the browser to if authentication fails */ private String authenticationFailureUrl; //~ Methods ======================================================================================================== /** * Sets the authentication failure URL. * * @param authenticationFailureUrl the authentication failure URL. */ public void setAuthenticationFailureUrl(String authenticationFailureUrl) { Assert.hasLength(authenticationFailureUrl, "authenticationFailureUrl must be specified"); this.authenticationFailureUrl = authenticationFailureUrl; } /** * Sends an NTLM challenge to the browser requiring authentication. The * WWW-Authenticate header is populated with the appropriate information * during the negotiation lifecycle by calling the getMessage() method * from an NTLM-specific subclass of {@link NtlmBaseException}: *

*

    *
  • {@link NtlmBeginHandshakeException}: NTLM *
  • {@link NtlmType2MessageException}: NTLM <base64-encoded type-2-message> *
* * If the {@link AuthenticationException} is not a subclass of * {@link NtlmBaseException}, then redirect the user to the authentication * failure URL. * * @param request The {@link HttpServletRequest} object. * @param response Then {@link HttpServletResponse} object. * @param authException Either {@link NtlmBeginHandshakeException}, * {@link NtlmType2MessageException}, or * {@link AuthenticationException} */ public void commence(final ServletRequest request, final ServletResponse response, final AuthenticationException authException) throws IOException, ServletException { final HttpServletResponse resp = (HttpServletResponse) response; if (authException instanceof NtlmBaseException) { if (authException instanceof NtlmType2MessageException) { ((NtlmType2MessageException) authException).preserveAuthentication(); } resp.setHeader("WWW-Authenticate", authException.getMessage()); resp.setHeader("Connection", "Keep-Alive"); resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); resp.setContentLength(0); resp.flushBuffer(); return; } if (authenticationFailureUrl == null) { if (!response.isCommitted()) { ((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, authException.getMessage()); } } else { String url = authenticationFailureUrl; if (!url.startsWith("http://") && !url.startsWith("https://")) { url = ((HttpServletRequest) request).getContextPath() + url; } resp.sendRedirect(resp.encodeRedirectURL(url)); } } } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/NtlmType2MessageException.javaspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/NtlmTyp0000644000000000000000000000277211623517156030534 0ustar /* Copyright 2004-2007 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.ntlm; import org.springframework.security.Authentication; import org.springframework.security.context.SecurityContextHolder; /** * Contains the NTLM Type 2 message that is sent back to the client during * negotiations. * * @author Edward Smith */ public class NtlmType2MessageException extends NtlmBaseException { private static final long serialVersionUID = 1L; private final Authentication auth; public NtlmType2MessageException(final String type2Msg) { super("NTLM " + type2Msg); auth = SecurityContextHolder.getContext().getAuthentication(); } /** * Preserve the existing Authentication object each time * Internet Explorer does a POST. */ public void preserveAuthentication() { if (auth != null) { SecurityContextHolder.getContext().setAuthentication(auth); } } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/NtlmBaseException.javaspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/NtlmBas0000644000000000000000000000226611623517156030463 0ustar /* Copyright 2004-2007 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.ntlm; import org.springframework.security.AuthenticationException; /** * Base class for NTLM exceptions so that it is easier to distinguish them * from other AuthenticationExceptions in the * {@link NtlmProcessingFilterEntryPoint}. Marked as abstract * since this exception is never supposed to be instantiated. * * @author Edward Smith */ public abstract class NtlmBaseException extends AuthenticationException { public NtlmBaseException(final String msg) { super(msg); } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/NtlmUsernamePasswordAuthenticationToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/NtlmUse0000644000000000000000000000457511623517156030517 0ustar /* Copyright 2004-2007 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.ntlm; import jcifs.smb.NtlmPasswordAuthentication; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.GrantedAuthority; import org.springframework.security.util.AuthorityUtils; /** * An NTLM-specific {@link UsernamePasswordAuthenticationToken} that allows any provider to bypass the problem of an * empty password since NTLM does not retrieve the user's password from the PDC. * * @author Sylvain Mougenot */ public class NtlmUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken { private static final long serialVersionUID = 1L; /** * Dummy authority array which is passed to the constructor of the parent class, * ensuring that the "authenticated" property is set to "true" by default. See SEC-609. */ private static final GrantedAuthority[] NTLM_AUTHENTICATED = AuthorityUtils.stringArrayToAuthorityArray(new String[] {"NTLM_AUTHENTICATED"}); /** * Spring Security often checks password ; but we do not have one. This is the replacement password */ public static final String DEFAULT_PASSWORD = ""; /** * Create an NTLM {@link UsernamePasswordAuthenticationToken} using the * JCIFS {@link NtlmPasswordAuthentication} object. * * @param ntlmAuth The {@link NtlmPasswordAuthentication} object. * @param stripDomain Uses just the username if true, * otherwise use the username and domain name. */ public NtlmUsernamePasswordAuthenticationToken(final NtlmPasswordAuthentication ntlmAuth, final boolean stripDomain) { super((stripDomain) ? ntlmAuth.getUsername() : ntlmAuth.getName(), DEFAULT_PASSWORD, NTLM_AUTHENTICATED); } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/NtlmBeginHandshakeException.javaspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/NtlmBeg0000644000000000000000000000162411623517156030450 0ustar /* Copyright 2004-2007 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.ntlm; /** * Signals the beginning of an NTLM handshaking process. * * @author Edward Smith */ public class NtlmBeginHandshakeException extends NtlmBaseException { public NtlmBeginHandshakeException() { super("NTLM"); } } spring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/ldap/0000755000000000000000000000000011623517156030112 5ustar ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/ldap/authenticator/spring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/ldap/au0000755000000000000000000000000011623517156030440 5ustar ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/ldap/authenticator/NtlmAwareLdapAuthenticator.javaspring-security-2.0.7.RELEASE/dist/spring-security-ntlm/org/springframework/security/ui/ntlm/ldap/au0000644000000000000000000001047511623517156030451 0ustar /** * */ package org.springframework.security.ui.ntlm.ldap.authenticator; import org.springframework.security.Authentication; import org.springframework.security.BadCredentialsException; import org.springframework.security.ldap.SpringSecurityContextSource; import org.springframework.security.ldap.SpringSecurityLdapTemplate; import org.springframework.security.providers.ldap.authenticator.BindAuthenticator; import org.springframework.security.ui.ntlm.NtlmUsernamePasswordAuthenticationToken; import org.springframework.ldap.NameNotFoundException; import org.springframework.ldap.core.DirContextOperations; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Iterator; /** * Loads the UserDetails if authentication was already performed by NTLM (indicated by the type of authentication * token submitted). Otherwise falls back to the parent class behaviour, attempting to bind as the user. * * @author sylvain.mougenot * */ public class NtlmAwareLdapAuthenticator extends BindAuthenticator { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(NtlmAwareLdapAuthenticator.class); //~ Constructors =================================================================================================== public NtlmAwareLdapAuthenticator(SpringSecurityContextSource contextSource) { super(contextSource); } //~ Methods ======================================================================================================== /** * Loads the user context information without binding. */ protected DirContextOperations loadUser(String aUserDn, String aUserName) { SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(getContextSource()); try { DirContextOperations user = template.retrieveEntry(aUserDn, getUserAttributes()); return user; } catch (NameNotFoundException e) { // This will be thrown if an invalid user name is used and the method may // be called multiple times to try different names, so we trap the exception. if (logger.isDebugEnabled()) { logger.debug("Failed to load user " + aUserDn + ": " + e.getMessage(), e); } } return null; } /** * If the supplied Authentication object is of type NtlmUsernamePasswordAuthenticationToken, * the information stored in the user's directory entry is loaded without attempting to authenticate them. * Otherwise the parent class is called to perform a bind operation to authenticate the user. */ public DirContextOperations authenticate(Authentication authentication) { if (!(authentication instanceof NtlmUsernamePasswordAuthenticationToken)) { // Not NTLM authenticated, so call the base class to authenticate the user. return super.authenticate(authentication); } if (!authentication.isAuthenticated()) { throw new BadCredentialsException("Unauthenticated NTLM authentication token found"); } if (logger.isDebugEnabled()) { logger.debug("authenticate(NtlmUsernamePasswordAuthenticationToken) - start"); //$NON-NLS-1$ } final String userName = authentication.getName(); DirContextOperations user = null; // If DN patterns are configured, try authenticating with them directly Iterator myDns = getUserDns(userName).iterator(); // tries them all until we found something while (myDns.hasNext() && (user == null)) { user = loadUser((String) myDns.next(), userName); } // Otherwise use the configured locator to find the user // and authenticate with the returned DN. if ((user == null) && (getUserSearch() != null)) { DirContextOperations userFromSearch = getUserSearch().searchForUser(userName); // lancer l'identificvation user = loadUser(userFromSearch.getDn().toString(), userName); } // Failed to locate the user in the LDAP directory if (user == null) { throw new BadCredentialsException(messages.getMessage("BindAuthenticator.badCredentials", "Bad credentials")); } if (logger.isDebugEnabled()) { logger.debug("authenticate(NtlmUsernamePasswordAuthenticationToken) - end"); //$NON-NLS-1$ } return user; } } spring-security-2.0.7.RELEASE/dist/spring-security-openid/0000755000000000000000000000000011766764113020236 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-openid/META-INF/0000755000000000000000000000000011623521772021370 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-openid/META-INF/MANIFEST.MF0000644000000000000000000000014311623521770023016 0ustar Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: 20.1-b02-384 (Apple Inc.) spring-security-2.0.7.RELEASE/dist/spring-security-openid/org/0000755000000000000000000000000011623517156021020 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/0000755000000000000000000000000011623517156024240 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/0000755000000000000000000000000011623517156026107 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/0000755000000000000000000000000011623517156026524 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/0000755000000000000000000000000011623517156030002 5ustar ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/consumers/spring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/con0000755000000000000000000000000011623517156030502 5ustar ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/consumers/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/con0000644000000000000000000000015611623517156030506 0ustar Implementations of the OpenIDConsumer interface using 3rd party libraries. ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/consumers/OpenID4JavaConsumer.javaspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/con0000644000000000000000000001315211623517156030506 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.openid.consumers; import org.springframework.security.providers.openid.OpenIDAuthenticationStatus; import org.springframework.security.providers.openid.OpenIDAuthenticationToken; import org.springframework.security.ui.openid.OpenIDConsumer; import org.springframework.security.ui.openid.OpenIDConsumerException; import org.openid4java.association.AssociationException; import org.openid4java.consumer.ConsumerException; import org.openid4java.consumer.ConsumerManager; import org.openid4java.consumer.VerificationResult; import org.openid4java.discovery.DiscoveryException; import org.openid4java.discovery.DiscoveryInformation; import org.openid4java.discovery.Identifier; import org.openid4java.message.AuthRequest; import org.openid4java.message.MessageException; import org.openid4java.message.ParameterList; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * * @author Ray Krueger */ public class OpenID4JavaConsumer implements OpenIDConsumer { //~ Instance fields ================================================================================================ private final ConsumerManager consumerManager; //~ Constructors =================================================================================================== public OpenID4JavaConsumer(ConsumerManager consumerManager) { this.consumerManager = consumerManager; } public OpenID4JavaConsumer() throws ConsumerException { this(new ConsumerManager()); } //~ Methods ======================================================================================================== public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl) throws OpenIDConsumerException { return beginConsumption(req, identityUrl, returnToUrl, returnToUrl); } public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl, String realm) throws OpenIDConsumerException { List discoveries; try { discoveries = consumerManager.discover(identityUrl); } catch (DiscoveryException e) { throw new OpenIDConsumerException("Error during discovery", e); } DiscoveryInformation information = consumerManager.associate(discoveries); HttpSession session = req.getSession(true); session.setAttribute(DiscoveryInformation.class.getName(), information); AuthRequest authReq; try { authReq = consumerManager.authenticate(information, returnToUrl, realm); } catch (MessageException e) { throw new OpenIDConsumerException("Error processing ConumerManager authentication", e); } catch (ConsumerException e) { throw new OpenIDConsumerException("Error processing ConumerManager authentication", e); } return authReq.getDestinationUrl(true); } public OpenIDAuthenticationToken endConsumption(HttpServletRequest request) throws OpenIDConsumerException { // extract the parameters from the authentication response // (which comes in as a HTTP request from the OpenID provider) ParameterList openidResp = new ParameterList(request.getParameterMap()); // retrieve the previously stored discovery information DiscoveryInformation discovered = (DiscoveryInformation) request.getSession() .getAttribute(DiscoveryInformation.class.getName()); // extract the receiving URL from the HTTP request StringBuffer receivingURL = request.getRequestURL(); String queryString = request.getQueryString(); if ((queryString != null) && (queryString.length() > 0)) { receivingURL.append("?").append(request.getQueryString()); } // verify the response VerificationResult verification; try { verification = consumerManager.verify(receivingURL.toString(), openidResp, discovered); } catch (MessageException e) { throw new OpenIDConsumerException("Error verifying openid response", e); } catch (DiscoveryException e) { throw new OpenIDConsumerException("Error verifying openid response", e); } catch (AssociationException e) { throw new OpenIDConsumerException("Error verifying openid response", e); } // examine the verification result and extract the verified identifier Identifier verified = verification.getVerifiedId(); if (verified != null) { return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, verified.getIdentifier(), "some message"); } else { return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, discovered.getClaimedIdentifier().getIdentifier(), "Verification status message: [" + verification.getStatusMsg() + "]"); } } } ././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/OpenIDAuthenticationRequiredException.javaspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/Ope0000644000000000000000000000215711623517156030455 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.openid; import org.springframework.security.AuthenticationException; /** * @author Ray Krueger */ public class OpenIDAuthenticationRequiredException extends AuthenticationException { private final String claimedIdentity; public OpenIDAuthenticationRequiredException(String msg, String claimedIdentity) { super(msg); this.claimedIdentity = claimedIdentity; } public String getClaimedIdentity() { return claimedIdentity; } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/pac0000644000000000000000000000016611623517156030473 0ustar Authenticates standard web browser users via OpenID. ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/OpenIDAuthenticationProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/Ope0000644000000000000000000002446011623517156030456 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.openid; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationServiceException; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.providers.openid.OpenIDAuthenticationToken; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.ui.FilterChainOrder; import org.springframework.security.ui.openid.consumers.OpenID4JavaConsumer; import org.springframework.security.ui.webapp.AuthenticationProcessingFilter; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.Map; /** * @author Robin Bramley, Opsera Ltd * @author Ray Krueger * @version $Id$ * @since 2.0 */ public class OpenIDAuthenticationProcessingFilter extends AbstractProcessingFilter { //~ Static fields/initializers ===================================================================================== private static final Log log = LogFactory.getLog(OpenIDAuthenticationProcessingFilter.class); public static final String DEFAULT_CLAIMED_IDENTITY_FIELD = "j_username"; //~ Instance fields ================================================================================================ private OpenIDConsumer consumer; private String claimedIdentityFieldName = DEFAULT_CLAIMED_IDENTITY_FIELD; private Map realmMapping = new HashMap(); //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); if (consumer == null) { consumer = new OpenID4JavaConsumer(); } } public Authentication attemptAuthentication(HttpServletRequest req) throws AuthenticationException { OpenIDAuthenticationToken token; String identity = req.getParameter("openid.identity"); if (!StringUtils.hasText(identity)) { // Make the username available to the view String username = obtainUsername(req); setLastUsername(username, req); throw new OpenIDAuthenticationRequiredException("External Authentication Required", username); } try { token = consumer.endConsumption(req); } catch (OpenIDConsumerException oice) { throw new AuthenticationServiceException("Consumer error", oice); } token.setDetails(authenticationDetailsSource.buildDetails(req)); // delegate to the auth provider Authentication authentication = this.getAuthenticationManager().authenticate(token); if (authentication.isAuthenticated()) { setLastUsername(token.getIdentityUrl(), req); } return authentication; } private void setLastUsername(String username, HttpServletRequest request) { HttpSession session = request.getSession(false); if (session != null || getAllowSessionCreation()) { request.getSession().setAttribute(AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY, username); } } protected String determineFailureUrl(HttpServletRequest request, AuthenticationException failed) { if (failed instanceof OpenIDAuthenticationRequiredException) { OpenIDAuthenticationRequiredException openIdRequiredException = (OpenIDAuthenticationRequiredException) failed; String claimedIdentity = openIdRequiredException.getClaimedIdentity(); if (StringUtils.hasText(claimedIdentity)) { try { String returnToUrl = buildReturnToUrl(request); String realm = lookupRealm(returnToUrl); return consumer.beginConsumption(request, claimedIdentity, returnToUrl, realm); } catch (OpenIDConsumerException e) { log.error("Unable to consume claimedIdentity [" + claimedIdentity + "]", e); } } } return super.determineFailureUrl(request, failed); } protected String lookupRealm(String returnToUrl) { String mapping = (String) realmMapping.get(returnToUrl); if (mapping == null) { try { URL url = new URL(returnToUrl); int port = (url.getPort() == -1) ? 80 : url.getPort(); StringBuffer realmBuffer = new StringBuffer(returnToUrl.length()) .append(url.getProtocol()) .append("://") .append(url.getHost()) .append(":").append(port) .append("/"); mapping = realmBuffer.toString(); } catch (MalformedURLException e) { log.warn("returnToUrl was not a valid URL: [" + returnToUrl + "]", e); } } return mapping; } protected String buildReturnToUrl(HttpServletRequest request) { return request.getRequestURL().toString(); } public String getClaimedIdentityFieldName() { return claimedIdentityFieldName; } public OpenIDConsumer getConsumer() { return consumer; } public String getDefaultFilterProcessesUrl() { return "/j_spring_openid_security_check"; } protected boolean isAuthenticated(HttpServletRequest request) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); return (auth != null) && auth.isAuthenticated(); } /** * The OpenIdAuthenticationProcessingFilter will ignore the request coming in if this method returns false. * The default functionality checks if the request scheme starts with http.
This method should be overridden in subclasses that wish to consider a different strategy * * @param request HttpServletRequest we're processing * @return true if this request is determined to be an OpenID request. */ protected boolean isOpenIdRequest(HttpServletRequest request) { String username = obtainUsername(request); return (StringUtils.hasText(username)) && username.toLowerCase().startsWith("http"); } protected String obtainUsername(HttpServletRequest req) { return req.getParameter(claimedIdentityFieldName); } protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { if (failed instanceof OpenIDAuthenticationRequiredException) { OpenIDAuthenticationRequiredException openIdAuthenticationRequiredException = (OpenIDAuthenticationRequiredException) failed; request.setAttribute(OpenIDAuthenticationRequiredException.class.getName(), openIdAuthenticationRequiredException.getClaimedIdentity()); } } public void setClaimedIdentityFieldName(String claimedIdentityFieldName) { this.claimedIdentityFieldName = claimedIdentityFieldName; } public void setConsumer(OpenIDConsumer consumer) { this.consumer = consumer; } protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { SecurityContextHolder.getContext().setAuthentication(null); if (logger.isDebugEnabled()) { logger.debug("Updated SecurityContextHolder to contain null Authentication"); } String failureUrl = determineFailureUrl(request, failed); if (logger.isDebugEnabled()) { logger.debug("Authentication request failed: " + failed.toString()); } if (getAllowSessionCreation()) { try { request.getSession().setAttribute(SPRING_SECURITY_LAST_EXCEPTION_KEY, failed); } catch (Exception ignored) { } } super.getRememberMeServices().loginFail(request, response); sendRedirect(request, response, failureUrl); } public int getOrder() { return FilterChainOrder.OPENID_PROCESSING_FILTER; } /** * Maps the return_to url to a realm.
* For example http://www.example.com/j_spring_openid_security_check -> http://www.example.com/realm
* If no mapping is provided then the returnToUrl will be parsed to extract the protocol, hostname and port followed * by a trailing slash.
* This means that http://www.example.com/j_spring_openid_security_check will automatically * become http://www.example.com:80/ * * @return Map containing returnToUrl -> realm mappings */ public Map getRealmMapping() { return realmMapping; } /** * Maps the return_to url to a realm.
* For example http://www.example.com/j_spring_openid_security_check -> http://www.example.com/realm
* If no mapping is provided then the returnToUrl will be parsed to extract the protocol, hostname and port followed * by a trailing slash.
* This means that http://www.example.com/j_spring_openid_security_check will automatically * become http://www.example.com:80/ * * @param realmMapping containing returnToUrl -> realm mappings */ public void setRealmMapping(Map realmMapping) { this.realmMapping = realmMapping; } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/OpenIDConsumerException.javaspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/Ope0000644000000000000000000000223011623517156030445 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.openid; /** * Thrown by an OpenIDConsumer if it cannot process a request * * @author Robin Bramley, Opsera Ltd */ public class OpenIDConsumerException extends Exception { //~ Constructors =================================================================================================== public OpenIDConsumerException(String message) { super(message); } public OpenIDConsumerException(String message, Throwable t) { super(message, t); } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/OpenIDConsumer.javaspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/ui/openid/Ope0000644000000000000000000000415511623517156030455 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.openid; import org.springframework.security.providers.openid.OpenIDAuthenticationToken; import javax.servlet.http.HttpServletRequest; /** * An interface for OpenID library implementations * * @author Ray Krueger * @author Robin Bramley, Opsera Ltd */ public interface OpenIDConsumer { /** * @deprecated Use {@link #beginConsumption(javax.servlet.http.HttpServletRequest, String, String, String)} */ public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl) throws OpenIDConsumerException; /** * Given the request, the claimedIdentity, the return to url, and a realm, lookup the openId authentication * page the user should be redirected to. * * @param req HttpServletRequest * @param claimedIdentity String URI the user presented during authentication * @param returnToUrl String URI of the URL we want the user sent back to by the OP * @param realm URI pattern matching the realm we want the user to see * @return String URI to redirect user to for authentication * @throws OpenIDConsumerException if anything bad happens */ public String beginConsumption(HttpServletRequest req, String claimedIdentity, String returnToUrl, String realm) throws OpenIDConsumerException; public OpenIDAuthenticationToken endConsumption(HttpServletRequest req) throws OpenIDConsumerException; } spring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/0000755000000000000000000000000011623517156030124 5ustar ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/openid/spring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/ope0000755000000000000000000000000011623517156030630 5ustar ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/openid/AuthenticationCancelledException.javaspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/ope0000644000000000000000000000240411623517156030632 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.openid; import org.springframework.security.AuthenticationException; /** * Indicates that OpenID authentication was cancelled * * @author Robin Bramley, Opsera Ltd * @version $Id$ */ public class AuthenticationCancelledException extends AuthenticationException { //~ Constructors =================================================================================================== public AuthenticationCancelledException(String msg) { super(msg); } public AuthenticationCancelledException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/openid/OpenIDAuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/ope0000644000000000000000000001202311623517156030630 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.openid; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationServiceException; import org.springframework.security.BadCredentialsException; import org.springframework.security.providers.AuthenticationProvider; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.util.Assert; /** * Finalises the OpenID authentication by obtaining local authorities for the authenticated user. *

* The authorities are obtained by calling the configured UserDetailsService. * The UserDetails it returns must, at minimum, contain the username and GrantedAuthority[] * objects applicable to the authenticated user. Note that by default, Spring Security ignores the password and * enabled/disabled status of the UserDetails because this is * authentication-related and should have been enforced by another provider server. *

* The UserDetails returned by implementations is stored in the generated AuthenticationToken, * so additional properties such as email addresses, telephone numbers etc can easily be stored. * * @author Robin Bramley, Opsera Ltd. */ public class OpenIDAuthenticationProvider implements AuthenticationProvider, InitializingBean { //~ Instance fields ================================================================================================ private UserDetailsService userDetailsService; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.userDetailsService, "The userDetailsService must be set"); } /* (non-Javadoc) * @see org.springframework.security.providers.AuthenticationProvider#authenticate(org.springframework.security.Authentication) */ public Authentication authenticate(final Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } if (authentication instanceof OpenIDAuthenticationToken) { OpenIDAuthenticationToken response = (OpenIDAuthenticationToken) authentication; OpenIDAuthenticationStatus status = response.getStatus(); // handle the various possibilites if (status == OpenIDAuthenticationStatus.SUCCESS) { // Lookup user details UserDetails userDetails = userDetailsService.loadUserByUsername(response.getIdentityUrl()); return new OpenIDAuthenticationToken(userDetails.getAuthorities(), response.getStatus(), response.getIdentityUrl()); } else if (status == OpenIDAuthenticationStatus.CANCELLED) { throw new AuthenticationCancelledException("Log in cancelled"); } else if (status == OpenIDAuthenticationStatus.ERROR) { throw new AuthenticationServiceException("Error message from server: " + response.getMessage()); } else if (status == OpenIDAuthenticationStatus.FAILURE) { throw new BadCredentialsException("Log in failed - identity could not be verified"); } else if (status == OpenIDAuthenticationStatus.SETUP_NEEDED) { throw new AuthenticationServiceException( "The server responded setup was needed, which shouldn't happen"); } else { throw new AuthenticationServiceException("Unrecognized return value " + status.toString()); } } return null; } /** * Used to load the authorities for the authenticated OpenID user. */ public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } /* (non-Javadoc) * @see org.springframework.security.providers.AuthenticationProvider#supports(java.lang.Class) */ public boolean supports(Class authentication) { return OpenIDAuthenticationToken.class.isAssignableFrom(authentication); } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/openid/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/ope0000644000000000000000000000031511623517156030631 0ustar An authentication provider that can process OpenID Authentication Tokens as created by implementations of the OpenIDConsumer interface. ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/openid/OpenIDAuthenticationStatus.javaspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/ope0000644000000000000000000000557111623517156030642 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.openid; import java.io.ObjectStreamException; import java.io.Serializable; /** * Based on JanRain status codes * * @author JanRain Inc. * @author Robin Bramley, Opsera Ltd */ public class OpenIDAuthenticationStatus implements Serializable { //~ Static fields/initializers ===================================================================================== private static final long serialVersionUID = -998877665544332211L; private static int nextOrdinal = 0; /** This code indicates a successful authentication request */ public static final OpenIDAuthenticationStatus SUCCESS = new OpenIDAuthenticationStatus("success"); /** This code indicates a failed authentication request */ public static final OpenIDAuthenticationStatus FAILURE = new OpenIDAuthenticationStatus("failure"); /** This code indicates the server reported an error */ public static final OpenIDAuthenticationStatus ERROR = new OpenIDAuthenticationStatus("error"); /** This code indicates that the user needs to do additional work to prove their identity */ public static final OpenIDAuthenticationStatus SETUP_NEEDED = new OpenIDAuthenticationStatus("setup needed"); /** This code indicates that the user cancelled their login request */ public static final OpenIDAuthenticationStatus CANCELLED = new OpenIDAuthenticationStatus("cancelled"); private static final OpenIDAuthenticationStatus[] PRIVATE_VALUES = {SUCCESS, FAILURE, ERROR, SETUP_NEEDED, CANCELLED}; //~ Instance fields ================================================================================================ private String name; private final int ordinal = nextOrdinal++; //~ Constructors =================================================================================================== private OpenIDAuthenticationStatus(String name) { this.name = name; } //~ Methods ======================================================================================================== private Object readResolve() throws ObjectStreamException { return PRIVATE_VALUES[ordinal]; } public String toString() { return name; } } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/openid/OpenIDAuthenticationToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-openid/org/springframework/security/providers/ope0000644000000000000000000000532511623517156030637 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.openid; import org.springframework.security.GrantedAuthority; import org.springframework.security.providers.AbstractAuthenticationToken; /** * OpenID Authentication Token * * @author Robin Bramley, Opsera Ltd */ public class OpenIDAuthenticationToken extends AbstractAuthenticationToken { //~ Instance fields ================================================================================================ private OpenIDAuthenticationStatus status; private String identityUrl; private String message; //~ Constructors =================================================================================================== public OpenIDAuthenticationToken(OpenIDAuthenticationStatus status, String identityUrl, String message) { super(new GrantedAuthority[0]); this.status = status; this.identityUrl = identityUrl; this.message = message; setAuthenticated(false); } /** * Created by the OpenIDAuthenticationProvider on successful authentication. * Do not use directly * */ public OpenIDAuthenticationToken(GrantedAuthority[] authorities, OpenIDAuthenticationStatus status, String identityUrl) { super(authorities); this.status = status; this.identityUrl = identityUrl; setAuthenticated(true); } //~ Methods ======================================================================================================== /* (non-Javadoc) * @see org.springframework.security.Authentication#getCredentials() */ public Object getCredentials() { return null; } public String getIdentityUrl() { return identityUrl; } public String getMessage() { return message; } /* (non-Javadoc) * @see org.springframework.security.Authentication#getPrincipal() */ public Object getPrincipal() { return identityUrl; } public OpenIDAuthenticationStatus getStatus() { return status; } } spring-security-2.0.7.RELEASE/dist/spring-security-core/0000755000000000000000000000000011766764113017710 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-core/META-INF/0000755000000000000000000000000011623521746021043 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-core/META-INF/spring.handlers0000644000000000000000000000015511623517156024070 0ustar http\://www.springframework.org/schema/security=org.springframework.security.config.SecurityNamespaceHandler spring-security-2.0.7.RELEASE/dist/spring-security-core/META-INF/spring.schemas0000644000000000000000000000144611623517156023717 0ustar http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-2.0.6.xsd http\://www.springframework.org/schema/security/spring-security-2.0.xsd=org/springframework/security/config/spring-security-2.0.xsd http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd http\://www.springframework.org/schema/security/spring-security-2.0.4.xsd=org/springframework/security/config/spring-security-2.0.4.xsd http\://www.springframework.org/schema/security/spring-security-2.0.6.xsd=org/springframework/security/config/spring-security-2.0.6.xsd spring-security-2.0.7.RELEASE/dist/spring-security-core/META-INF/MANIFEST.MF0000644000000000000000000000014311623521744022471 0ustar Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: 20.1-b02-384 (Apple Inc.) spring-security-2.0.7.RELEASE/dist/spring-security-core/org/0000755000000000000000000000000011421405512020456 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/0000755000000000000000000000000011421405512023676 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/0000755000000000000000000000000011623517156025561 5ustar ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/Authentication.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/Authentication.0000644000000000000000000001174311623517156030547 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; import java.io.Serializable; import java.security.Principal; /** * Represents an authentication request. * *

* An Authentication object is not considered authenticated until * it is processed by an {@link AuthenticationManager}. *

* *

* Stored in a request {@link org.springframework.security.context.SecurityContext}. *

* * @author Ben Alex * @version $Id$ */ public interface Authentication extends Principal, Serializable { //~ Methods ======================================================================================================== /** * Set by an AuthenticationManager to indicate the authorities that the principal has been * granted. Note that classes should not rely on this value as being valid unless it has been set by a trusted * AuthenticationManager.

Implementations should ensure that modifications to the returned * array do not affect the state of the Authentication object (e.g. by returning an array copy).

* * @return the authorities granted to the principal, or null if authentication has not been completed */ GrantedAuthority[] getAuthorities(); /** * The credentials that prove the principal is correct. This is usually a password, but could be anything * relevant to the AuthenticationManager. Callers are expected to populate the credentials. * * @return the credentials that prove the identity of the Principal */ Object getCredentials(); /** * Stores additional details about the authentication request. These might be an IP address, certificate * serial number etc. * * @return additional details about the authentication request, or null if not used */ Object getDetails(); /** * The identity of the principal being authenticated. This is usually a username. Callers are expected to * populate the principal. * * @return the Principal being authenticated */ Object getPrincipal(); /** * Used to indicate to AbstractSecurityInterceptor whether it should present the * authentication token to the AuthenticationManager. Typically an AuthenticationManager * (or, more often, one of its AuthenticationProviders) will return an immutable authentication token * after successful authentication, in which case that token can safely return true to this method. * Returning true will improve performance, as calling the AuthenticationManager for * every request will no longer be necessary.

For security reasons, implementations of this interface * should be very careful about returning true to this method unless they are either immutable, or * have some way of ensuring the properties have not been changed since original creation.

* * @return true if the token has been authenticated and the AbstractSecurityInterceptor does not need * to represent the token for re-authentication to the AuthenticationManager */ boolean isAuthenticated(); /** * See {@link #isAuthenticated()} for a full description.

Implementations should always allow this * method to be called with a false parameter, as this is used by various classes to specify the * authentication token should not be trusted. If an implementation wishes to reject an invocation with a * true parameter (which would indicate the authentication token is trusted - a potential security * risk) the implementation should throw an {@link IllegalArgumentException}.

* * @param isAuthenticated true if the token should be trusted (which may result in an exception) or * false if the token should not be trusted * * @throws IllegalArgumentException if an attempt to make the authentication token trusted (by passing * true as the argument) is rejected due to the implementation being immutable or * implementing its own alternative approach to {@link #isAuthenticated()} */ void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException; } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages.propertiesspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages.proper0000644000000000000000000001026011623517156030620 0ustar AuthByAdapterProvider.incorrectKey=The presented AuthByAdapter implementation does not contain the expected key BasicAclEntryAfterInvocationProvider.noPermission=Authentication {0} has NO permissions at all to the domain object {1} BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentication {0} has ACL permissions to the domain object, but not the required ACL permission to the domain object {1} ConcurrentSessionControllerImpl.exceededAllowed=Maximum sessions of {0} for this principal exceeded ProviderManager.providerNotFound=No AuthenticationProvider found for {0} AnonymousAuthenticationProvider.incorrectKey=The presented AnonymousAuthenticationToken does not contain the expected key CasAuthenticationProvider.incorrectKey=The presented CasAuthenticationToken does not contain the expected key CasAuthenticationProvider.noServiceTicket=Failed to provide a CAS service ticket to validate NamedCasProxyDecider.untrusted=Nearest proxy {0} is untrusted RejectProxyTickets.reject=Proxy tickets are rejected AbstractSecurityInterceptor.authenticationNotFound=An Authentication object was not found in the SecurityContext AbstractUserDetailsAuthenticationProvider.onlySupports=Only UsernamePasswordAuthenticationToken is supported AbstractUserDetailsAuthenticationProvider.locked=User account is locked AbstractUserDetailsAuthenticationProvider.disabled=User is disabled AbstractUserDetailsAuthenticationProvider.expired=User account has expired AbstractUserDetailsAuthenticationProvider.credentialsExpired=User credentials have expired AbstractUserDetailsAuthenticationProvider.badCredentials=Bad credentials X509AuthenticationProvider.certificateNull=Certificate is null DaoX509AuthoritiesPopulator.noMatching=No matching pattern was found in subjectDN: {0} RememberMeAuthenticationProvider.incorrectKey=The presented RememberMeAuthenticationToken does not contain the expected key RunAsImplAuthenticationProvider.incorrectKey=The presented RunAsUserToken does not contain the expected key DigestProcessingFilter.missingMandatory=Missing mandatory digest value; received header {0} DigestProcessingFilter.missingAuth=Missing mandatory digest value for 'auth' QOP; received header {0} DigestProcessingFilter.incorrectRealm=Response realm name {0} does not match system realm name of {1} DigestProcessingFilter.nonceExpired=Nonce has expired/timed out DigestProcessingFilter.nonceEncoding=Nonce is not encoded in Base64; received nonce {0} DigestProcessingFilter.nonceNotTwoTokens=Nonce should have yielded two tokens but was {0} DigestProcessingFilter.nonceNotNumeric=Nonce token should have yielded a numeric first token, but was {0} DigestProcessingFilter.nonceCompromised=Nonce token compromised {0} DigestProcessingFilter.usernameNotFound=Username {0} not found DigestProcessingFilter.incorrectResponse=Incorrect response JdbcDaoImpl.notFound=User {0} not found JdbcDaoImpl.noAuthority=User {0} has no GrantedAuthority SwitchUserProcessingFilter.noCurrentUser=No current user associated with this request SwitchUserProcessingFilter.noOriginalAuthentication=Could not find original Authentication object SwitchUserProcessingFilter.usernameNotFound=Username {0} not found SwitchUserProcessingFilter.locked=User account is locked SwitchUserProcessingFilter.disabled=User is disabled SwitchUserProcessingFilter.expired=User account has expired SwitchUserProcessingFilter.credentialsExpired=User credentials have expired AbstractAccessDecisionManager.accessDenied=Access is denied LdapAuthenticationProvider.emptyUsername=Empty username not allowed LdapAuthenticationProvider.emptyPassword=Bad credentials DefaultIntitalDirContextFactory.communicationFailure=Unable to connect to LDAP server DefaultIntitalDirContextFactory.badCredentials=Bad credentials DefaultIntitalDirContextFactory.unexpectedException=Failed to obtain InitialDirContext due to unexpected exception PasswordComparisonAuthenticator.badCredentials=Bad credentials BindAuthenticator.badCredentials=Bad credentials BindAuthenticator.failedToLoadAttributes=Bad credentials UserDetailsService.locked=User account is locked UserDetailsService.disabled=User is disabled UserDetailsService.expired=User account has expired UserDetailsService.credentialsExpired=User credentials have expired ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymapping/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymappin0000755000000000000000000000000011623517156030737 5ustar ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymapping/SimpleMappableAttributesRetriever.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymappin0000644000000000000000000000222311623517156030740 0ustar package org.springframework.security.authoritymapping; import org.springframework.util.Assert; /** * This class implements the MappableAttributesRetriever interface by just returning * a list of mappable attributes as previously set using the corresponding setter * method. * * @author Ruud Senden * @since 2.0 */ public class SimpleMappableAttributesRetriever implements MappableAttributesRetriever { private String[] mappableAttributes = null; /* * (non-Javadoc) * * @see org.springframework.security.authoritymapping.MappableAttributesRetriever#getMappableAttributes() */ public String[] getMappableAttributes() { Assert.notNull(mappableAttributes, "No mappable roles have been set"); String[] copy = new String[mappableAttributes.length]; System.arraycopy(mappableAttributes, 0, copy, 0, copy.length); return copy; } public void setMappableAttributes(String[] aMappableRoles) { this.mappableAttributes = new String[aMappableRoles.length]; System.arraycopy(aMappableRoles, 0, mappableAttributes, 0, mappableAttributes.length); } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymapping/XmlMappableAttributesRetriever.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymappin0000644000000000000000000001531211623517156030743 0ustar package org.springframework.security.authoritymapping; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.util.Arrays; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jaxen.JaxenException; import org.jaxen.dom.DOMXPath; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * This implementation for the MappableAttributesRetriever interface retrieves the * list of mappable attributes from an XML file. *

* This class is defined as abstract because it is too generic to be used * directly. As this class is usually used to read very specific XML files (e.g. * web.xml, ejb-jar.xml), subclasses should usually define the actual * XPath-expression to use, and define a more specifically named setter for the * XML InputStream (e.g. setWebXmlInputStream). * * @author Ruud Senden * @since 2.0 */ public abstract class XmlMappableAttributesRetriever implements MappableAttributesRetriever, InitializingBean { private static final Log logger = LogFactory.getLog(XmlMappableAttributesRetriever.class); private String[] mappableAttributes = null; private InputStream xmlInputStream = null; private String xpathExpression = null; private boolean closeInputStream = true; /** * Check whether all required properties have been set. */ public void afterPropertiesSet() throws Exception { Assert.notNull(xmlInputStream, "An XML InputStream must be set"); Assert.notNull(xpathExpression, "An XPath expression must be set"); mappableAttributes = getMappableAttributes(xmlInputStream); } public String[] getMappableAttributes() { String[] copy = new String[mappableAttributes.length]; System.arraycopy(mappableAttributes, 0, copy, 0, copy.length); return copy; } /** * Get the mappable roles from the specified XML document. */ private String[] getMappableAttributes(InputStream aStream) { if (logger.isDebugEnabled()) { logger.debug("Reading mappable attributes from XML document"); } try { Document doc = getDocument(aStream); String[] roles = getMappableAttributes(doc); if (logger.isDebugEnabled()) { logger.debug("Mappable attributes from XML document: " + Arrays.asList(roles)); } return roles; } finally { if (closeInputStream) { try { aStream.close(); } catch (Exception e) { logger.debug("Input stream could not be closed", e); } } } } /** * @return Document for the specified InputStream */ private Document getDocument(InputStream aStream) { Document doc; try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(false); DocumentBuilder db = factory.newDocumentBuilder(); db.setEntityResolver(new MyEntityResolver()); doc = db.parse(new IgnoreCloseInputStream(aStream)); return doc; } catch (FactoryConfigurationError e) { throw new RuntimeException("Unable to parse document object", e); } catch (ParserConfigurationException e) { throw new RuntimeException("Unable to parse document object", e); } catch (SAXException e) { throw new RuntimeException("Unable to parse document object", e); } catch (IOException e) { throw new RuntimeException("Unable to parse document object", e); } } /** * @param doc * The Document from which to read the list of roles * @return String[] the list of roles. * @throws JaxenException */ private String[] getMappableAttributes(Document doc) { try { DOMXPath xpath = new DOMXPath(xpathExpression); List roleElements = xpath.selectNodes(doc); String[] roles = new String[roleElements.size()]; for (int i = 0; i < roles.length; i++) { roles[i] = ((Node) roleElements.get(i)).getNodeValue(); } return roles; } catch (JaxenException e) { throw new RuntimeException("Unable to retrieve mappable roles", e); } catch (DOMException e) { throw new RuntimeException("Unable to retrieve mappable roles", e); } } /** * Subclasses should provide this method with a more specific name (e.g. * indicating the type of XML file the subclass expects, like * setWebXmlInputStream). */ protected void setXmlInputStream(InputStream aStream) { this.xmlInputStream = aStream; } /** * Subclasses usually want to set an XPath expression by themselves (e.g. * not user-configurable). However subclasses may provide configuration * options to for example choose from a list of predefined XPath expressions * (e.g. to support multiple versions of the same type of XML file), as such * we provide a setter instead of mandatory constructor argument. */ protected void setXpathExpression(String anXpathExpression) { xpathExpression = anXpathExpression; } /** * Define whether the provided InputStream must be closed after reading it. */ public void setCloseInputStream(boolean b) { closeInputStream = b; } /** * We do not need to resolve external entities, so just return an empty * String. */ private static final class MyEntityResolver implements EntityResolver { public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { return new InputSource(new StringReader("")); } } public static final class IgnoreCloseInputStream extends FilterInputStream { public IgnoreCloseInputStream(InputStream stream) { super(stream); } public void close() throws IOException { // do nothing } } } ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymapping/Attributes2GrantedAuthoritiesMapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymappin0000644000000000000000000000176411623517156030751 0ustar package org.springframework.security.authoritymapping; import org.springframework.security.GrantedAuthority; /** * Interface to be implemented by classes that can map a list of security attributes (such as roles or * group names) to a list of Spring Security GrantedAuthorities. * * @author Ruud Senden * @since 2.0 */ public interface Attributes2GrantedAuthoritiesMapper { /** * Implementations of this method should map the given list of attributes to a * list of Spring Security GrantedAuthorities. There are no restrictions for the * mapping process; a single attribute can be mapped to multiple Spring Security * GrantedAuthorities, all attributes can be mapped to a single Spring Security * GrantedAuthority, some attributes may not be mapped, etc. * * @param attribute the attributes to be mapped * @return the list of mapped GrantedAuthorities */ public GrantedAuthority[] getGrantedAuthorities(String[] attributes); } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymapping/MappableAttributesRetriever.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymappin0000644000000000000000000000114111623517156030736 0ustar package org.springframework.security.authoritymapping; /** * Interface to be implemented by classes that can retrieve a list of mappable * security attribute strings (for example the list of all available J2EE roles in a web or EJB * application). * * @author Ruud Senden * @since 2.0 */ public interface MappableAttributesRetriever { /** * Implementations of this method should return a list of all string attributes which * can be mapped to GrantedAuthoritys. * * @return list of all mappable roles */ String[] getMappableAttributes(); } ././@LongLink0000000000000000000000000000022700000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymapping/MapBasedAttributes2GrantedAuthoritiesMapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymappin0000644000000000000000000001322511623517156030744 0ustar package org.springframework.security.authoritymapping; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthorityImpl; import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** *

* This class implements the Attributes2GrantedAuthoritiesMapper and * MappableAttributesRetriever interfaces based on the supplied Map. * It supports both one-to-one and one-to-many mappings. The granted * authorities to map to can be supplied either as a String or as a * GrantedAuthority object. *

* @author Ruud Senden */ public class MapBasedAttributes2GrantedAuthoritiesMapper implements Attributes2GrantedAuthoritiesMapper, MappableAttributesRetriever, InitializingBean { private Map attributes2grantedAuthoritiesMap = null; private String stringSeparator = ","; private String[] mappableAttributes = null; /** * Check whether all properties have been set to correct values, and do some preprocessing. */ public void afterPropertiesSet() { Assert.notEmpty(attributes2grantedAuthoritiesMap,"A non-empty attributes2grantedAuthoritiesMap must be supplied"); attributes2grantedAuthoritiesMap = preProcessMap(attributes2grantedAuthoritiesMap); try { mappableAttributes = (String[])attributes2grantedAuthoritiesMap.keySet().toArray(new String[]{}); } catch ( ArrayStoreException ase ) { throw new IllegalArgumentException("attributes2grantedAuthoritiesMap contains non-String objects as keys"); } } /** * Preprocess the given map * @param orgMap The map to process * @return the processed Map */ private Map preProcessMap(Map orgMap) { Map result = new HashMap(orgMap.size()); Iterator it = orgMap.entrySet().iterator(); while ( it.hasNext() ) { Map.Entry entry = (Map.Entry)it.next(); result.put(entry.getKey(),getGrantedAuthorityCollection(entry.getValue())); } return result; } /** * Convert the given value to a collection of Granted Authorities * * @param value * The value to convert to a GrantedAuthority Collection * @return Collection containing the GrantedAuthority Collection */ private Collection getGrantedAuthorityCollection(Object value) { Collection result = new ArrayList(); addGrantedAuthorityCollection(result,value); return result; } /** * Convert the given value to a collection of Granted Authorities, * adding the result to the given result collection. * * @param value * The value to convert to a GrantedAuthority Collection * @return Collection containing the GrantedAuthority Collection */ private void addGrantedAuthorityCollection(Collection result, Object value) { if ( value != null ) { if ( value instanceof Collection ) { addGrantedAuthorityCollection(result,(Collection)value); } else if ( value instanceof Object[] ) { addGrantedAuthorityCollection(result,(Object[])value); } else if ( value instanceof String ) { addGrantedAuthorityCollection(result,(String)value); } else if ( value instanceof GrantedAuthority ) { result.add(value); } else { throw new IllegalArgumentException("Invalid object type: "+value.getClass().getName()); } } } private void addGrantedAuthorityCollection(Collection result, Collection value) { Iterator it = value.iterator(); while ( it.hasNext() ) { addGrantedAuthorityCollection(result,it.next()); } } private void addGrantedAuthorityCollection(Collection result, Object[] value) { for ( int i = 0 ; i < value.length ; i++ ) { addGrantedAuthorityCollection(result,value[i]); } } private void addGrantedAuthorityCollection(Collection result, String value) { StringTokenizer st = new StringTokenizer(value,stringSeparator,false); while ( st.hasMoreTokens() ) { String nextToken = st.nextToken(); if ( StringUtils.hasText(nextToken) ) { result.add(new GrantedAuthorityImpl(nextToken)); } } } /** * Map the given array of attributes to Spring Security GrantedAuthorities. */ public GrantedAuthority[] getGrantedAuthorities(String[] attributes) { List gaList = new ArrayList(); for (int i = 0; i < attributes.length; i++) { Collection c = (Collection)attributes2grantedAuthoritiesMap.get(attributes[i]); if ( c != null ) { gaList.addAll(c); } } GrantedAuthority[] result = new GrantedAuthority[gaList.size()]; result = (GrantedAuthority[])gaList.toArray(result); return result; } /** * @return Returns the attributes2grantedAuthoritiesMap. */ public Map getAttributes2grantedAuthoritiesMap() { return attributes2grantedAuthoritiesMap; } /** * @param attributes2grantedAuthoritiesMap The attributes2grantedAuthoritiesMap to set. */ public void setAttributes2grantedAuthoritiesMap(Map attributes2grantedAuthoritiesMap) { this.attributes2grantedAuthoritiesMap = attributes2grantedAuthoritiesMap; } /** * * @see org.springframework.security.authoritymapping.MappableAttributesRetriever#getMappableAttributes() */ public String[] getMappableAttributes() { return mappableAttributes; } /** * @return Returns the stringSeparator. */ public String getStringSeparator() { return stringSeparator; } /** * @param stringSeparator The stringSeparator to set. */ public void setStringSeparator(String stringSeparator) { this.stringSeparator = stringSeparator; } } ././@LongLink0000000000000000000000000000022500000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymapping/SimpleAttributes2GrantedAuthoritiesMapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/authoritymappin0000644000000000000000000000717511623517156030753 0ustar package org.springframework.security.authoritymapping; import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthorityImpl; import java.util.Locale; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** *

* This class implements the Attributes2GrantedAuthoritiesMapper interface by doing a * one-to-one mapping from roles to Spring Security GrantedAuthorities. Optionally a * prefix can be added, and the attribute name can be converted to upper or lower * case. *

* By default, the attribute is prefixed with "ROLE_" unless it already starts with * "ROLE_", and no case conversion is done. * * @author Ruud Senden * @since 2.0 */ public class SimpleAttributes2GrantedAuthoritiesMapper implements Attributes2GrantedAuthoritiesMapper, InitializingBean { private String attributePrefix = "ROLE_"; private boolean convertAttributeToUpperCase = false; private boolean convertAttributeToLowerCase = false; private boolean addPrefixIfAlreadyExisting = false; /** * Check whether all properties have been set to correct values. */ public void afterPropertiesSet() throws Exception { Assert.isTrue(!(isConvertAttributeToUpperCase() && isConvertAttributeToLowerCase()), "Either convertAttributeToUpperCase or convertAttributeToLowerCase can be set to true, but not both"); } /** * Map the given list of string attributes one-to-one to Spring Security GrantedAuthorities. */ public GrantedAuthority[] getGrantedAuthorities(String[] attributes) { GrantedAuthority[] result = new GrantedAuthority[attributes.length]; for (int i = 0; i < attributes.length; i++) { result[i] = getGrantedAuthority(attributes[i]); } return result; } /** * Map the given role one-on-one to a Spring Security GrantedAuthority, optionally * doing case conversion and/or adding a prefix. * * @param attribute * The attribute for which to get a GrantedAuthority * @return GrantedAuthority representing the given role. */ private GrantedAuthority getGrantedAuthority(String attribute) { if (isConvertAttributeToLowerCase()) { attribute = attribute.toLowerCase(Locale.getDefault()); } else if (isConvertAttributeToUpperCase()) { attribute = attribute.toUpperCase(Locale.getDefault()); } if (isAddPrefixIfAlreadyExisting() || !attribute.startsWith(getAttributePrefix())) { return new GrantedAuthorityImpl(getAttributePrefix() + attribute); } else { return new GrantedAuthorityImpl(attribute); } } private boolean isConvertAttributeToLowerCase() { return convertAttributeToLowerCase; } public void setConvertAttributeToLowerCase(boolean b) { convertAttributeToLowerCase = b; } private boolean isConvertAttributeToUpperCase() { return convertAttributeToUpperCase; } public void setConvertAttributeToUpperCase(boolean b) { convertAttributeToUpperCase = b; } private String getAttributePrefix() { return attributePrefix == null ? "" : attributePrefix; } public void setAttributePrefix(String string) { attributePrefix = string; } private boolean isAddPrefixIfAlreadyExisting() { return addPrefixIfAlreadyExisting; } public void setAddPrefixIfAlreadyExisting(boolean b) { addPrefixIfAlreadyExisting = b; } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/0000755000000000000000000000000011623520546026173 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/0000755000000000000000000000000011623517156030316 5ustar ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/AbstractRememberMeServices.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/A0000644000000000000000000003450311623517156030426 0ustar package org.springframework.security.ui.rememberme; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.security.Authentication; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.AccountStatusException; import org.springframework.security.providers.rememberme.RememberMeAuthenticationToken; import org.springframework.security.ui.AuthenticationDetailsSource; import org.springframework.security.ui.WebAuthenticationDetailsSource; import org.springframework.security.ui.logout.LogoutHandler; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.security.userdetails.UserDetailsChecker; import org.springframework.security.userdetails.checker.AccountStatusUserDetailsChecker; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Base class for RememberMeServices implementations. * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public abstract class AbstractRememberMeServices implements RememberMeServices, InitializingBean, LogoutHandler { //~ Static fields/initializers ===================================================================================== public static final String SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY = "SPRING_SECURITY_REMEMBER_ME_COOKIE"; public static final String DEFAULT_PARAMETER = "_spring_security_remember_me"; private static final String DELIMITER = ":"; //~ Instance fields ================================================================================================ protected final Log logger = LogFactory.getLog(getClass()); protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private UserDetailsService userDetailsService; private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); private String cookieName = SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY; private String parameter = DEFAULT_PARAMETER; private boolean alwaysRemember; private String key; private int tokenValiditySeconds = 1209600; // 14 days public void afterPropertiesSet() throws Exception { Assert.hasLength(key); Assert.hasLength(parameter); Assert.hasLength(cookieName); Assert.notNull(userDetailsService); } /** * Template implementation which locates the Spring Security cookie, decodes it into * a delimited array of tokens and submits it to subclasses for processing * via the processAutoLoginCookie method. *

* The returned username is then used to load the UserDetails object for the user, which in turn * is used to create a valid authentication token. */ public final Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) { String rememberMeCookie = extractRememberMeCookie(request); if (rememberMeCookie == null) { return null; } logger.debug("Remember-me cookie detected"); UserDetails user = null; try { String[] cookieTokens = decodeCookie(rememberMeCookie); user = processAutoLoginCookie(cookieTokens, request, response); userDetailsChecker.check(user); } catch (CookieTheftException cte) { cancelCookie(request, response); throw cte; } catch (UsernameNotFoundException noUser) { cancelCookie(request, response); logger.debug("Remember-me login was valid but corresponding user not found.", noUser); return null; } catch (InvalidCookieException invalidCookie) { cancelCookie(request, response); logger.debug("Invalid remember-me cookie: " + invalidCookie.getMessage()); return null; } catch (AccountStatusException statusInvalid) { cancelCookie(request, response); logger.debug("Invalid UserDetails: " + statusInvalid.getMessage()); return null; } catch (RememberMeAuthenticationException e) { cancelCookie(request, response); logger.debug(e.getMessage()); return null; } logger.debug("Remember-me cookie accepted"); RememberMeAuthenticationToken auth = new RememberMeAuthenticationToken(key, user, user.getAuthorities()); auth.setDetails(authenticationDetailsSource.buildDetails(request)); return auth; } /** * Locates the Spring Security remember me cookie in the request. * * @param request the submitted request which is to be authenticated * @return the cookie value (if present), null otherwise. */ private String extractRememberMeCookie(HttpServletRequest request) { Cookie[] cookies = request.getCookies(); if ((cookies == null) || (cookies.length == 0)) { return null; } for (int i = 0; i < cookies.length; i++) { if (cookieName.equals(cookies[i].getName())) { return cookies[i].getValue(); } } return null; } /** * Decodes the cookie and splits it into a set of token strings using the ":" delimiter. * * @param cookieValue the value obtained from the submitted cookie * @return the array of tokens. * @throws InvalidCookieException if the cookie was not base64 encoded. */ protected String[] decodeCookie(String cookieValue) throws InvalidCookieException { for (int j = 0; j < cookieValue.length() % 4; j++) { cookieValue = cookieValue + "="; } if (!Base64.isArrayByteBase64(cookieValue.getBytes())) { throw new InvalidCookieException( "Cookie token was not Base64 encoded; value was '" + cookieValue + "'"); } String cookieAsPlainText = new String(Base64.decodeBase64(cookieValue.getBytes())); return StringUtils.delimitedListToStringArray(cookieAsPlainText, DELIMITER); } /** * Inverse operation of decodeCookie. * * @param cookieTokens the tokens to be encoded. * @return base64 encoding of the tokens concatenated with the ":" delimiter. */ protected String encodeCookie(String[] cookieTokens) { StringBuffer sb = new StringBuffer(); for(int i=0; i < cookieTokens.length; i++) { sb.append(cookieTokens[i]); if (i < cookieTokens.length - 1) { sb.append(DELIMITER); } } String value = sb.toString(); sb = new StringBuffer(new String(Base64.encodeBase64(value.getBytes()))); while (sb.charAt(sb.length() - 1) == '=') { sb.deleteCharAt(sb.length() - 1); } return sb.toString(); } public final void loginFail(HttpServletRequest request, HttpServletResponse response) { logger.debug("Interactive login attempt was unsuccessful."); cancelCookie(request, response); onLoginFail(request, response); } protected void onLoginFail(HttpServletRequest request, HttpServletResponse response) {} /** * Examines the incoming request and checks for the presence of the configured "remember me" parameter. * If it's present, or if alwaysRemember is set to true, calls onLoginSucces. */ public final void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) { if (!rememberMeRequested(request, parameter)) { logger.debug("Remember-me login not requested."); return; } onLoginSuccess(request, response, successfulAuthentication); } /** * Called from loginSuccess when a remember-me login has been requested. * Typically implemented by subclasses to set a remember-me cookie and potentially store a record * of it if the implementation requires this. */ protected abstract void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication); /** * Allows customization of whether a remember-me login has been requested. * The default is to return true if alwaysRemember is set or the configured parameter name has * been included in the request and is set to the value "true". * * @param request the request submitted from an interactive login, which may include additional information * indicating that a persistent login is desired. * @param parameter the configured remember-me parameter name. * * @return true if the request includes information indicating that a persistent login has been * requested. */ protected boolean rememberMeRequested(HttpServletRequest request, String parameter) { if (alwaysRemember) { return true; } String paramValue = request.getParameter(parameter); if (paramValue != null) { if (paramValue.equalsIgnoreCase("true") || paramValue.equalsIgnoreCase("on") || paramValue.equalsIgnoreCase("yes") || paramValue.equals("1")) { return true; } } if (logger.isDebugEnabled()) { logger.debug("Did not send remember-me cookie (principal did not set parameter '" + parameter + "')"); } return false; } /** * Called from autoLogin to process the submitted persistent login cookie. Subclasses should * validate the cookie and perform any additional management required. * * @param cookieTokens the decoded and tokenized cookie value * @param request the request * @param response the response, to allow the cookie to be modified if required. * @return the UserDetails for the corresponding user account if the cookie was validated successfully. * @throws RememberMeAuthenticationException if the cookie is invalid or the login is invalid for some * other reason. * @throws UsernameNotFoundException if the user account corresponding to the login cookie couldn't be found * (for example if the user has been removed from the system). */ protected abstract UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) throws RememberMeAuthenticationException, UsernameNotFoundException; /** * Sets a "cancel cookie" (with maxAge = 0) on the response to disable persistent logins. * * @param request * @param response */ protected void cancelCookie(HttpServletRequest request, HttpServletResponse response) { logger.debug("Cancelling cookie"); Cookie cookie = new Cookie(cookieName, null); cookie.setMaxAge(0); cookie.setPath(StringUtils.hasLength(request.getContextPath()) ? request.getContextPath() : "/"); response.addCookie(cookie); } /** * Sets the cookie on the response * * @param tokens the tokens which will be encoded to make the cookie value. * @param maxAge the value passed to {@link Cookie#setMaxAge(int)} * @param request the request * @param response the response to add the cookie to. */ protected void setCookie(String[] tokens, int maxAge, HttpServletRequest request, HttpServletResponse response) { String cookieValue = encodeCookie(tokens); Cookie cookie = new Cookie(cookieName, cookieValue); cookie.setMaxAge(maxAge); cookie.setPath(StringUtils.hasLength(request.getContextPath()) ? request.getContextPath() : "/"); response.addCookie(cookie); } /** * Implementation of LogoutHandler. Default behaviour is to call cancelCookie(). */ public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { if (logger.isDebugEnabled()) { logger.debug( "Logout of user " + (authentication == null ? "Unknown" : authentication.getName())); } cancelCookie(request, response); } public void setCookieName(String cookieName) { this.cookieName = cookieName; } protected String getCookieName() { return cookieName; } public void setAlwaysRemember(boolean alwaysRemember) { this.alwaysRemember = alwaysRemember; } /** * Sets the name of the parameter which should be checked for to see if a remember-me has been requested * during a login request. This should be the same name you assign to the checkbox in your login form. * * @param parameter the HTTP request parameter */ public void setParameter(String parameter) { Assert.hasText(parameter, "Parameter name cannot be null"); this.parameter = parameter; } public String getParameter() { return parameter; } protected UserDetailsService getUserDetailsService() { return userDetailsService; } public void setUserDetailsService(UserDetailsService userDetailsService) { Assert.notNull(userDetailsService, "UserDetailsService canot be null"); this.userDetailsService = userDetailsService; } public void setKey(String key) { this.key = key; } public String getKey() { return key; } public void setTokenValiditySeconds(int tokenValiditySeconds) { this.tokenValiditySeconds = tokenValiditySeconds; } protected int getTokenValiditySeconds() { return tokenValiditySeconds; } protected AuthenticationDetailsSource getAuthenticationDetailsSource() { return authenticationDetailsSource; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource cannot be null"); this.authenticationDetailsSource = authenticationDetailsSource; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/RememberMeServices.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/R0000644000000000000000000001162311623517156030445 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.rememberme; import org.springframework.security.Authentication; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Implement by a class that is capable of providing a remember-me service. * *

* Spring Security filters (namely {@link * org.springframework.security.ui.AbstractProcessingFilter} and {@link * org.springframework.security.ui.rememberme.RememberMeProcessingFilter} will call * the methods provided by an implementation of this interface. *

* *

* Implementations may implement any type of remember-me capability they wish. * Rolling cookies (as per * http://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice) * can be used, as can simple implementations that don't require a persistent * store. Implementations also determine the validity period of a remember-me * cookie. This interface has been designed to accommodate any of these * remember-me models. *

* *

* This interface does not define how remember-me services should offer a * "cancel all remember-me tokens" type capability, as this will be * implementation specific and requires no hooks into Spring Security. *

* * @author Ben Alex * @version $Id$ */ public interface RememberMeServices { //~ Methods ======================================================================================================== /** * This method will be called whenever the SecurityContextHolder does not contain an * Authentication object and Spring Security wishes to provide an implementation with an * opportunity to authenticate the request using remember-me capabilities. Spring Security makes no attempt * whatsoever to determine whether the browser has requested remember-me services or presented a valid cookie. * Such determinations are left to the implementation. If a browser has presented an unauthorised cookie for * whatever reason, it should be silently ignored and invalidated using the HttpServletResponse * object.

The returned Authentication must be acceptable to {@link * org.springframework.security.AuthenticationManager} or * {@link org.springframework.security.providers.AuthenticationProvider} defined by the web application. It is recommended {@link * org.springframework.security.providers.rememberme.RememberMeAuthenticationToken} be used in most cases, as it has a * corresponding authentication provider.

* * @param request to look for a remember-me token within * @param response to change, cancel or modify the remember-me token * * @return a valid authentication object, or null if the request should not be authenticated */ Authentication autoLogin(HttpServletRequest request, HttpServletResponse response); /** * Called whenever an interactive authentication attempt was made, but the credentials supplied by the user * were missing or otherwise invalid. Implementations should invalidate any and all remember-me tokens indicated * in the HttpServletRequest. * * @param request that contained an invalid authentication request * @param response to change, cancel or modify the remember-me token */ void loginFail(HttpServletRequest request, HttpServletResponse response); /** * Called whenever an interactive authentication attempt is successful. An implementation may automatically * set a remember-me token in the HttpServletResponse, although this is not recommended. Instead, * implementations should typically look for a request parameter that indicates the browser has presented an * explicit request for authentication to be remembered, such as the presence of a HTTP POST parameter. * * @param request that contained the valid authentication request * @param response to change, cancel or modify the remember-me token * @param successfulAuthentication representing the successfully authenticated principal */ void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication); } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/NullRememberMeServices.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/N0000644000000000000000000000300611623517156030435 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.rememberme; import org.springframework.security.Authentication; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Implementation of {@link NullRememberMeServices} that does nothing.

Used as a default by several framework * classes.

* * @author Ben Alex * @version $Id$ */ public class NullRememberMeServices implements RememberMeServices { //~ Methods ======================================================================================================== public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) { return null; } public void loginFail(HttpServletRequest request, HttpServletResponse response) {} public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) {} } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/InvalidCookieException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/I0000644000000000000000000000062611623517156030435 0ustar package org.springframework.security.ui.rememberme; /** * Exception thrown by a RememberMeServices implementation to indicate * that a submitted cookie is of an invalid format or has expired. * * @author Luke Taylor * @version $Id$ */ public class InvalidCookieException extends RememberMeAuthenticationException { public InvalidCookieException(String message) { super(message); } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/JdbcTokenRepositoryImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/J0000644000000000000000000001457511623517156030446 0ustar package org.springframework.security.ui.rememberme; import org.springframework.dao.DataAccessException; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.jdbc.object.MappingSqlQuery; import org.springframework.jdbc.object.SqlUpdate; import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Date; /** * JDBC based persistent login token repository implementation. * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements PersistentTokenRepository { //~ Static fields/initializers ===================================================================================== /** Default SQL for creating the database table to store the tokens */ public static final String CREATE_TABLE_SQL = "create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, " + "token varchar(64) not null, last_used timestamp not null)"; /** The default SQL used by the getTokenBySeries query */ public static final String DEF_TOKEN_BY_SERIES_SQL = "select username,series,token,last_used from persistent_logins where series = ?"; /** The default SQL used by createNewToken */ public static final String DEF_INSERT_TOKEN_SQL = "insert into persistent_logins (username, series, token, last_used) values(?,?,?,?)"; /** The default SQL used by updateToken */ public static final String DEF_UPDATE_TOKEN_SQL = "update persistent_logins set token = ?, last_used = ? where series = ?"; /** The default SQL used by removeUserTokens */ public static final String DEF_REMOVE_USER_TOKENS_SQL = "delete from persistent_logins where username = ?"; //~ Instance fields ================================================================================================ private String tokensBySeriesSql = DEF_TOKEN_BY_SERIES_SQL; private String insertTokenSql = DEF_INSERT_TOKEN_SQL; private String updateTokenSql = DEF_UPDATE_TOKEN_SQL; private String removeUserTokensSql = DEF_REMOVE_USER_TOKENS_SQL; private boolean createTableOnStartup; protected MappingSqlQuery tokensBySeriesMapping; protected SqlUpdate insertToken; protected SqlUpdate updateToken; protected SqlUpdate removeUserTokens; protected void initDao() { tokensBySeriesMapping = new TokensBySeriesMapping(getDataSource()); insertToken = new InsertToken(getDataSource()); updateToken = new UpdateToken(getDataSource()); removeUserTokens = new RemoveUserTokens(getDataSource()); if (createTableOnStartup) { getJdbcTemplate().execute(CREATE_TABLE_SQL); } } public void createNewToken(PersistentRememberMeToken token) { insertToken.update( new Object[] {token.getUsername(), token.getSeries(), token.getTokenValue(), token.getDate()}); } public void updateToken(String series, String tokenValue, Date lastUsed) { updateToken.update(new Object[] {tokenValue, new Date(), series}); } /** * Loads the token data for the supplied series identifier. * * If an error occurs, it will be reported and null will be returned (since the result should just be a failed * persistent login). * * @param seriesId * @return the token matching the series, or null if no match found or an exception occurred. */ public PersistentRememberMeToken getTokenForSeries(String seriesId) { try { return (PersistentRememberMeToken) tokensBySeriesMapping.findObject(seriesId); } catch(IncorrectResultSizeDataAccessException moreThanOne) { logger.error("Querying token for series '" + seriesId + "' returned more than one value. Series" + "should be unique"); } catch(DataAccessException e) { logger.error("Failed to load token for series " + seriesId, e); } return null; } public void removeUserTokens(String username) { removeUserTokens.update(username); } /** * Intended for convenience in debugging. Will create the persistent_tokens database table when the class * is initialized during the initDao method. * * @param createTableOnStartup set to true to execute the */ public void setCreateTableOnStartup(boolean createTableOnStartup) { this.createTableOnStartup = createTableOnStartup; } //~ Inner Classes ================================================================================================== protected class TokensBySeriesMapping extends MappingSqlQuery { protected TokensBySeriesMapping(DataSource ds) { super(ds, tokensBySeriesSql); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected Object mapRow(ResultSet rs, int rowNum) throws SQLException { PersistentRememberMeToken token = new PersistentRememberMeToken(rs.getString(1), rs.getString(2), rs.getString(3), rs.getTimestamp(4)); return token; } } protected class UpdateToken extends SqlUpdate { public UpdateToken(DataSource ds) { super(ds, updateTokenSql); setMaxRowsAffected(1); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.TIMESTAMP)); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } } protected class InsertToken extends SqlUpdate { public InsertToken(DataSource ds) { super(ds, insertTokenSql); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.TIMESTAMP)); compile(); } } protected class RemoveUserTokens extends SqlUpdate { public RemoveUserTokens(DataSource ds) { super(ds, removeUserTokensSql); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/TokenBasedRememberMeServices.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/T0000644000000000000000000002164711623517156030456 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.rememberme; import org.springframework.security.Authentication; import org.springframework.security.userdetails.UserDetails; import org.springframework.util.StringUtils; import org.apache.commons.codec.digest.DigestUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Arrays; import java.util.Date; /** * Identifies previously remembered users by a Base-64 encoded cookie. * *

* This implementation does not rely on an external database, so is attractive * for simple applications. The cookie will be valid for a specific period from * the date of the last {@link #loginSuccess(HttpServletRequest, HttpServletResponse, Authentication)}. * As per the interface contract, this method will only be called when the * principal completes a successful interactive authentication. As such the time * period commences from the last authentication attempt where they furnished * credentials - not the time period they last logged in via remember-me. The * implementation will only send a remember-me token if the parameter defined by * {@link #setParameter(String)} is present. * *

* An {@link org.springframework.security.userdetails.UserDetailsService} is required by * this implementation, so that it can construct a valid * Authentication from the returned {@link org.springframework.security.userdetails.UserDetails}. * This is also necessary so that the user's password is available and can be checked as part of the encoded cookie. * *

* The cookie encoded by this implementation adopts the following form: * *

 * username + ":" + expiryTime + ":" + Md5Hex(username + ":" + expiryTime + ":" + password + ":" + key)
 * 
* *

* As such, if the user changes their password, any remember-me token will be * invalidated. Equally, the system administrator may invalidate every * remember-me token on issue by changing the key. This provides some reasonable * approaches to recovering from a remember-me token being left on a public * machine (eg kiosk system, Internet cafe etc). Most importantly, at no time is * the user's password ever sent to the user agent, providing an important * security safeguard. Unfortunately the username is necessary in this * implementation (as we do not want to rely on a database for remember-me * services) and as such high security applications should be aware of this * occasionally undesired disclosure of a valid username. * *

* This is a basic remember-me implementation which is suitable for many * applications. However, we recommend a database-based implementation if you * require a more secure remember-me approach (see {@link PersistentTokenBasedRememberMeServices}). * *

* By default the tokens will be valid for 14 days from the last successful * authentication attempt. This can be changed using * {@link #setTokenValiditySeconds(int)}. * * * @author Ben Alex * @version $Id$ */ public class TokenBasedRememberMeServices extends AbstractRememberMeServices { //~ Methods ======================================================================================================== public UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) { if (cookieTokens.length != 3) { throw new InvalidCookieException("Cookie token did not contain " + 2 + " tokens, but contained '" + Arrays.asList(cookieTokens) + "'"); } long tokenExpiryTime; try { tokenExpiryTime = new Long(cookieTokens[1]).longValue(); } catch (NumberFormatException nfe) { throw new InvalidCookieException("Cookie token[1] did not contain a valid number (contained '" + cookieTokens[1] + "')"); } if (isTokenExpired(tokenExpiryTime)) { throw new InvalidCookieException("Cookie token[1] has expired (expired on '" + new Date(tokenExpiryTime) + "'; current time is '" + new Date() + "')"); } // Check the user exists. // Defer lookup until after expiry time checked, to possibly avoid expensive database call. UserDetails userDetails = getUserDetailsService().loadUserByUsername(cookieTokens[0]); // Check signature of token matches remaining details. // Must do this after user lookup, as we need the DAO-derived password. // If efficiency was a major issue, just add in a UserCache implementation, // but recall that this method is usually only called once per HttpSession - if the token is valid, // it will cause SecurityContextHolder population, whilst if invalid, will cause the cookie to be cancelled. String expectedTokenSignature = makeTokenSignature(tokenExpiryTime, userDetails.getUsername(), userDetails.getPassword()); if (!expectedTokenSignature.equals(cookieTokens[2])) { throw new InvalidCookieException("Cookie token[2] contained signature '" + cookieTokens[2] + "' but expected '" + expectedTokenSignature + "'"); } return userDetails; } /** * Calculates the digital signature to be put in the cookie. Default value is * MD5 ("username:tokenExpiryTime:password:key") */ protected String makeTokenSignature(long tokenExpiryTime, String username, String password) { return DigestUtils.md5Hex(username + ":" + tokenExpiryTime + ":" + password + ":" + getKey()); } protected boolean isTokenExpired(long tokenExpiryTime) { return tokenExpiryTime < System.currentTimeMillis(); } public void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) { String username = retrieveUserName(successfulAuthentication); String password = retrievePassword(successfulAuthentication); // If unable to find a username and password, just abort as TokenBasedRememberMeServices is // unable to construct a valid token in this case. if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) { return; } int tokenLifetime = calculateLoginLifetime(request, successfulAuthentication); long expiryTime = System.currentTimeMillis() + 1000L*tokenLifetime; String signatureValue = makeTokenSignature(expiryTime, username, password); setCookie(new String[] {username, Long.toString(expiryTime), signatureValue}, tokenLifetime, request, response); if (logger.isDebugEnabled()) { logger.debug("Added remember-me cookie for user '" + username + "', expiry: '" + new Date(expiryTime) + "'"); } } /** * Calculates the validity period in seconds for a newly generated remember-me login. * After this period (from the current time) the remember-me login will be considered expired. * This method allows customization based on request parameters supplied with the login or information in * the Authentication object. The default value is just the token validity period property, * tokenValiditySeconds. *

* The returned value will be used to work out the expiry time of the token and will also be * used to set the maxAge property of the cookie. *

* * See SEC-485. * * @param request the request passed to onLoginSuccess * @param authentication the successful authentication object. * @return the lifetime in seconds. */ protected int calculateLoginLifetime(HttpServletRequest request, Authentication authentication) { return getTokenValiditySeconds(); } protected String retrieveUserName(Authentication authentication) { if (isInstanceOfUserDetails(authentication)) { return ((UserDetails) authentication.getPrincipal()).getUsername(); } else { return authentication.getPrincipal().toString(); } } protected String retrievePassword(Authentication authentication) { if (isInstanceOfUserDetails(authentication)) { return ((UserDetails) authentication.getPrincipal()).getPassword(); } else { return authentication.getCredentials().toString(); } } private boolean isInstanceOfUserDetails(Authentication authentication) { return authentication.getPrincipal() instanceof UserDetails; } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/CookieTheftException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/C0000644000000000000000000000040511623517156030422 0ustar package org.springframework.security.ui.rememberme; /** * @author Luke Taylor * @version $Id$ */ public class CookieTheftException extends RememberMeAuthenticationException { public CookieTheftException(String message) { super(message); } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/RememberMeAuthenticationException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/R0000644000000000000000000000052411623517156030443 0ustar package org.springframework.security.ui.rememberme; import org.springframework.security.AuthenticationException; /** * @author Luke Taylor * @version $Id$ */ public class RememberMeAuthenticationException extends AuthenticationException { public RememberMeAuthenticationException(String message) { super(message); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/p0000644000000000000000000000013511623517156030477 0ustar Support for remembering a user between different web sessions. ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/PersistentTokenRepository.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/P0000644000000000000000000000116611623517156030444 0ustar package org.springframework.security.ui.rememberme; import java.util.Date; /** * The abstraction used by {@link PersistentTokenBasedRememberMeServices} to store the persistent * login tokens for a user. * * @see JdbcTokenRepositoryImpl * @see InMemoryTokenRepositoryImpl * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public interface PersistentTokenRepository { void createNewToken(PersistentRememberMeToken token); void updateToken(String series, String tokenValue, Date lastUsed); PersistentRememberMeToken getTokenForSeries(String seriesId); void removeUserTokens(String username); } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/InMemoryTokenRepositoryImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/I0000644000000000000000000000356211623517156030437 0ustar package org.springframework.security.ui.rememberme; import org.springframework.dao.DataIntegrityViolationException; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * Simple PersistentTokenRepository implementation backed by a Map. Intended for testing only. * * @author Luke Taylor * @version $Id$ */ public class InMemoryTokenRepositoryImpl implements PersistentTokenRepository { private Map seriesTokens = new HashMap(); public synchronized void createNewToken(PersistentRememberMeToken token) { PersistentRememberMeToken current = (PersistentRememberMeToken) seriesTokens.get(token.getSeries()); if (current != null) { throw new DataIntegrityViolationException("Series Id '"+ token.getSeries() +"' already exists!"); } seriesTokens.put(token.getSeries(), token); } public synchronized void updateToken(String series, String tokenValue, Date lastUsed) { PersistentRememberMeToken token = getTokenForSeries(series); PersistentRememberMeToken newToken = new PersistentRememberMeToken(token.getUsername(), series, tokenValue, new Date()); // Store it, overwriting the existing one. seriesTokens.put(series, newToken); } public synchronized PersistentRememberMeToken getTokenForSeries(String seriesId) { return (PersistentRememberMeToken) seriesTokens.get(seriesId); } public synchronized void removeUserTokens(String username) { Iterator series = seriesTokens.keySet().iterator(); while (series.hasNext()) { Object seriesId = series.next(); PersistentRememberMeToken token = (PersistentRememberMeToken) seriesTokens.get(seriesId); if (username.equals(token.getUsername())) { series.remove(); } } } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/PersistentRememberMeToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/P0000644000000000000000000000140011623517156030433 0ustar package org.springframework.security.ui.rememberme; import java.util.Date; /** * @author Luke Taylor * @version $Id$ */ public class PersistentRememberMeToken { private String username; private String series; private String tokenValue; private Date date; public PersistentRememberMeToken(String username, String series, String tokenValue, Date date) { this.username = username; this.series = series; this.tokenValue = tokenValue; this.date = date; } public String getUsername() { return username; } public String getSeries() { return series; } public String getTokenValue() { return tokenValue; } public Date getDate() { return date; } } ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/PersistentTokenBasedRememberMeServices.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/P0000644000000000000000000001635011623517156030445 0ustar package org.springframework.security.ui.rememberme; import org.springframework.security.Authentication; import org.springframework.security.userdetails.UserDetails; import org.springframework.dao.DataAccessException; import org.apache.commons.codec.binary.Base64; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.security.SecureRandom; import java.util.Arrays; import java.util.Date; /** * {@link RememberMeServices} implementation based on Barry Jaspan's * Improved Persistent Login Cookie * Best Practice. * * There is a slight modification to the described approach, in that the username is not stored as part of the cookie * but obtained from the persistent store via an implementation of {@link PersistentTokenRepository}. The latter * should place a unique constraint on the series identifier, so that it is impossible for the same identifier to be * allocated to two different users. * *

User management such as changing passwords, removing users and setting user status should be combined * with maintenance of the user's persistent tokens. *

* *

Note that while this class will use the date a token was created to check whether a presented cookie * is older than the configured tokenValiditySeconds property and deny authentication in this case, * it will to delete such tokens from the storage. A suitable batch process should be run periodically to * remove expired tokens from the database. *

* * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices { private PersistentTokenRepository tokenRepository = new InMemoryTokenRepositoryImpl(); private SecureRandom random; public static final int DEFAULT_SERIES_LENGTH = 16; public static final int DEFAULT_TOKEN_LENGTH = 16; private int seriesLength = DEFAULT_SERIES_LENGTH; private int tokenLength = DEFAULT_TOKEN_LENGTH; public PersistentTokenBasedRememberMeServices() throws Exception { random = SecureRandom.getInstance("SHA1PRNG"); } /** * Locates the presented cookie data in the token repository, using the series id. * If the data compares successfully with that in the persistent store, a new token is generated and stored with * the same series. The corresponding cookie value is set on the response. * * @param cookieTokens the series and token values * * @throws RememberMeAuthenticationException if there is no stored token corresponding to the submitted cookie, or * if the token in the persistent store has expired. * @throws InvalidCookieException if the cookie doesn't have two tokens as expected. * @throws CookieTheftException if a presented series value is found, but the stored token is different from the * one presented. */ protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) { if (cookieTokens.length != 2) { throw new InvalidCookieException("Cookie token did not contain " + 2 + " tokens, but contained '" + Arrays.asList(cookieTokens) + "'"); } final String presentedSeries = cookieTokens[0]; final String presentedToken = cookieTokens[1]; PersistentRememberMeToken token = tokenRepository.getTokenForSeries(presentedSeries); if (token == null) { // No series match, so we can't authenticate using this cookie throw new RememberMeAuthenticationException("No persistent token found for series id: " + presentedSeries); } // We have a match for this user/series combination if (!presentedToken.equals(token.getTokenValue())) { // Token doesn't match series value. Delete all logins for this user and throw an exception to warn them. tokenRepository.removeUserTokens(token.getUsername()); throw new CookieTheftException(messages.getMessage("PersistentTokenBasedRememberMeServices.cookieStolen", "Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack.")); } if (token.getDate().getTime() + getTokenValiditySeconds()*1000 < System.currentTimeMillis()) { throw new RememberMeAuthenticationException("Remember-me login has expired"); } // Token also matches, so login is valid. Update the token value, keeping the *same* series number. if (logger.isDebugEnabled()) { logger.debug("Refreshing persistent login token for user '" + token.getUsername() + "', series '" + token.getSeries() + "'"); } PersistentRememberMeToken newToken = new PersistentRememberMeToken(token.getUsername(), token.getSeries(), generateTokenData(), new Date()); try { tokenRepository.updateToken(newToken.getSeries(), newToken.getTokenValue(), newToken.getDate()); addCookie(newToken, request, response); } catch (DataAccessException e) { logger.error("Failed to update token: ", e); throw new RememberMeAuthenticationException("Autologin failed due to data access problem"); } UserDetails user = getUserDetailsService().loadUserByUsername(token.getUsername()); return user; } /** * Creates a new persistent login token with a new series number, stores the data in the * persistent token repository and adds the corresponding cookie to the response. * */ protected void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) { String username = successfulAuthentication.getName(); logger.debug("Creating new persistent login for user " + username); PersistentRememberMeToken persistentToken = new PersistentRememberMeToken(username, generateSeriesData(), generateTokenData(), new Date()); try { tokenRepository.createNewToken(persistentToken); addCookie(persistentToken, request, response); } catch (DataAccessException e) { logger.error("Failed to save persistent token ", e); } } protected String generateSeriesData() { byte[] newSeries = new byte[seriesLength]; random.nextBytes(newSeries); return new String(Base64.encodeBase64(newSeries)); } protected String generateTokenData() { byte[] newToken = new byte[tokenLength]; random.nextBytes(newToken); return new String(Base64.encodeBase64(newToken)); } private void addCookie(PersistentRememberMeToken token, HttpServletRequest request, HttpServletResponse response) { setCookie(new String[] {token.getSeries(), token.getTokenValue()},getTokenValiditySeconds(), request, response); } public void setTokenRepository(PersistentTokenRepository tokenRepository) { this.tokenRepository = tokenRepository; } public void setSeriesLength(int seriesLength) { this.seriesLength = seriesLength; } public void setTokenLength(int tokenLength) { this.tokenLength = tokenLength; } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/RememberMeProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/rememberme/R0000644000000000000000000001657611623517156030461 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.rememberme; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationManager; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.event.authentication.InteractiveAuthenticationSuccessEvent; import org.springframework.security.ui.FilterChainOrder; import org.springframework.security.ui.SpringSecurityFilter; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.util.Assert; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Detects if there is no Authentication object in the SecurityContext, and populates it * with a remember-me authentication token if a {@link org.springframework.security.ui.rememberme.RememberMeServices} * implementation so requests.

Concrete RememberMeServices implementations will have their {@link * org.springframework.security.ui.rememberme.RememberMeServices#autoLogin(HttpServletRequest, HttpServletResponse)} method * called by this filter. The Authentication or null returned by that method will be placed * into the SecurityContext. The AuthenticationManager will be used, so that any concurrent * session management or other authentication-specific behaviour can be achieved. This is the same pattern as with * other authentication mechanisms, which call the AuthenticationManager as part of their contract.

*

If authentication is successful, an {@link * org.springframework.security.event.authentication.InteractiveAuthenticationSuccessEvent} will be published to the application * context. No events will be published if authentication was unsuccessful, because this would generally be recorded * via an AuthenticationManager-specific application event.

* * @author Ben Alex * @version $Id$ */ public class RememberMeProcessingFilter extends SpringSecurityFilter implements InitializingBean, ApplicationEventPublisherAware { //~ Instance fields ================================================================================================ private ApplicationEventPublisher eventPublisher; private AuthenticationManager authenticationManager; private RememberMeServices rememberMeServices; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(authenticationManager, "authenticationManager must be specified"); Assert.notNull(rememberMeServices, "rememberMeServices must be specified"); } public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (SecurityContextHolder.getContext().getAuthentication() == null) { Authentication rememberMeAuth = rememberMeServices.autoLogin(request, response); if (rememberMeAuth != null) { // Attempt authenticaton via AuthenticationManager try { rememberMeAuth = authenticationManager.authenticate(rememberMeAuth); // Store to SecurityContextHolder SecurityContextHolder.getContext().setAuthentication(rememberMeAuth); onSuccessfulAuthentication(request, response, rememberMeAuth); if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder populated with remember-me token: '" + SecurityContextHolder.getContext().getAuthentication() + "'"); } // Fire event if (this.eventPublisher != null) { eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent( SecurityContextHolder.getContext().getAuthentication(), this.getClass())); } } catch (AuthenticationException authenticationException) { if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder not populated with remember-me token, as " + "AuthenticationManager rejected Authentication returned by RememberMeServices: '" + rememberMeAuth + "'; invalidating remember-me token", authenticationException); } rememberMeServices.loginFail(request, response); onUnsuccessfulAuthentication(request, response, authenticationException); } } chain.doFilter(request, response); } else { if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder not populated with remember-me token, as it already contained: '" + SecurityContextHolder.getContext().getAuthentication() + "'"); } chain.doFilter(request, response); } } /** * Called if a remember-me token is presented and successfully authenticated by the RememberMeServices * autoLogin method and the AuthenticationManager. */ protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) { } /** * Called if the AuthenticationManager rejects the authentication object returned from the * RememberMeServices autoLogin method. This method will not be called when no remember-me * token is present in the request and autoLogin returns null. */ protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) { } public RememberMeServices getRememberMeServices() { return rememberMeServices; } public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } public void setRememberMeServices(RememberMeServices rememberMeServices) { this.rememberMeServices = rememberMeServices; } public int getOrder() { return FilterChainOrder.REMEMBER_ME_FILTER; } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/AuthenticationDetailsSourceImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/Authenticati0000644000000000000000000000564611623517156030556 0ustar package org.springframework.security.ui; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import org.springframework.security.ui.AuthenticationDetailsSource; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; /** * Base implementation of {@link AuthenticationDetailsSource}. *

* By default will create an instance of AuthenticationDetails. * Any object that accepts an Object as its sole constructor can * be used instead of this default. *

* * @author Ruud Senden * @since 2.0 */ public class AuthenticationDetailsSourceImpl implements AuthenticationDetailsSource { //~ Instance fields ================================================================================================ private Class clazz = AuthenticationDetails.class; //~ Methods ======================================================================================================== public Object buildDetails(Object context) { try { Constructor constructor = getFirstMatchingConstructor(context); return constructor.newInstance(new Object[] { context }); } catch (NoSuchMethodException ex) { ReflectionUtils.handleReflectionException(ex); } catch (InvocationTargetException ex) { ReflectionUtils.handleReflectionException(ex); } catch (InstantiationException ex) { ReflectionUtils.handleReflectionException(ex); } catch (IllegalAccessException ex) { ReflectionUtils.handleReflectionException(ex); } return null; } /** * Return the first matching constructor that can take the given object * as an argument. Please note that we cannot use * getDeclaredConstructor(new Class[]{object.getClass()}) * as this will only match if the constructor argument type matches * the object type exactly (instead of checking whether it is assignable) * * @param object the object for which to find a matching constructor * @return a matching constructor for the given object * @throws NoSuchMethodException if no matching constructor can be found */ private Constructor getFirstMatchingConstructor(Object object) throws NoSuchMethodException { Constructor[] constructors = clazz.getDeclaredConstructors(); Constructor constructor = null; for (int i = 0; i < constructors.length; i++) { Class[] parameterTypes = constructors[i].getParameterTypes(); if (parameterTypes.length == 1 && (object == null || parameterTypes[0].isInstance(object))) { constructor = constructors[i]; break; } } if (constructor == null) { if (object == null) { throw new NoSuchMethodException("No constructor found that can take a single argument"); } else { throw new NoSuchMethodException("No constructor found that can take a single argument of type " + object.getClass()); } } return constructor; } public void setClazz(Class clazz) { Assert.notNull(clazz, "Class required"); this.clazz = clazz; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/SpringSecurityFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/SpringSecuri0000644000000000000000000000415611623517156030544 0ustar package org.springframework.security.ui; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.Ordered; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletException; import javax.servlet.FilterChain; import javax.servlet.ServletResponse; import javax.servlet.FilterConfig; import javax.servlet.ServletRequest; import javax.servlet.Filter; import java.io.IOException; /** * Implements Ordered interface as required by security namespace configuration and implements unused filter * lifecycle methods and performs casting of request and response to http versions in doFilter method. * * @author Luke Taylor * @version $Id$ */ public abstract class SpringSecurityFilter implements Filter, Ordered { protected final Log logger = LogFactory.getLog(this.getClass()); /** * Does nothing. We use IoC container lifecycle services instead. * * @param filterConfig ignored * @throws ServletException ignored */ public final void init(FilterConfig filterConfig) throws ServletException { } /** * Does nothing. We use IoC container lifecycle services instead. */ public final void destroy() { } public final void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // Do we really need the checks on the types in practice ? if (!(request instanceof HttpServletRequest)) { throw new ServletException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("Can only process HttpServletResponse"); } doFilterHttp((HttpServletRequest)request, (HttpServletResponse)response, chain); } protected abstract void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException; public String toString() { return getClass().getName() + "[ order=" + getOrder() + "; ]"; } }././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/AbstractProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/AbstractProc0000644000000000000000000005651011623517156030517 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationManager; import org.springframework.security.util.RedirectUtils; import org.springframework.security.util.SessionUtils; import org.springframework.security.util.UrlUtils; import org.springframework.security.concurrent.SessionRegistry; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.event.authentication.InteractiveAuthenticationSuccessEvent; import org.springframework.security.ui.rememberme.NullRememberMeServices; import org.springframework.security.ui.rememberme.RememberMeServices; import org.springframework.security.ui.savedrequest.SavedRequest; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.io.IOException; import java.util.Properties; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Abstract processor of browser-based HTTP-based authentication requests. *

* This filter is responsible for processing authentication requests. If * authentication is successful, the resulting {@link Authentication} object * will be placed into the SecurityContext, which is guaranteed * to have already been created by an earlier filter. *

* If authentication fails, the AuthenticationException will be * placed into the HttpSession with the attribute defined by * {@link #SPRING_SECURITY_LAST_EXCEPTION_KEY}. *

* To use this filter, it is necessary to specify the following properties: *

    *
  • defaultTargetUrl indicates the URL that should be used * for redirection if the HttpSession attribute named * {@link #SPRING_SECURITY_SAVED_REQUEST_KEY} does not indicate the target URL once * authentication is completed successfully. eg: /. The * defaultTargetUrl will be treated as relative to the web-app's * context path, and should include the leading /. * Alternatively, inclusion of a scheme name (eg http:// or https://) as the * prefix will denote a fully-qualified URL and this is also supported. More * complex behaviour can be implemented by using a customised {@link TargetUrlResolver}.
  • *
  • authenticationFailureUrl (optional) indicates the URL that should be * used for redirection if the authentication request fails. eg: * /login.jsp?login_error=1. If not configured, sendError will be * called on the response, with the error code SC_UNAUTHORIZED.
  • *
  • filterProcessesUrl indicates the URL that this filter * will respond to. This parameter varies by subclass.
  • *
  • alwaysUseDefaultTargetUrl causes successful * authentication to always redirect to the defaultTargetUrl, * even if the HttpSession attribute named {@link * # SPRING_SECURITY_SAVED_REQUEST_KEY} defines the intended target URL.
  • *
*

* To configure this filter to redirect to specific pages as the result of * specific {@link AuthenticationException}s you can do the following. * Configure the exceptionMappings property in your application * xml. This property is a java.util.Properties object that maps a * fully-qualified exception class name to a redirection url target. For * example: * *

 *  <property name="exceptionMappings">
 *    <props>
 *      <prop> key="org.springframework.security.BadCredentialsException">/bad_credentials.jsp</prop>
 *    </props>
 *  </property>
 * 
* * The example above would redirect all * {@link org.springframework.security.BadCredentialsException}s thrown, to a page in the * web-application called /bad_credentials.jsp. *

* Any {@link AuthenticationException} thrown that cannot be matched in the * exceptionMappings will be redirected to the * authenticationFailureUrl *

* If authentication is successful, an {@link * org.springframework.security.event.authentication.InteractiveAuthenticationSuccessEvent} * will be published to the application context. No events will be published if * authentication was unsuccessful, because this would generally be recorded via * an AuthenticationManager-specific application event. *

* The filter has an optional attribute invalidateSessionOnSuccessfulAuthentication that will invalidate * the current session on successful authentication. This is to protect against session fixation attacks (see * this Wikipedia article for more information). * The behaviour is turned off by default. Additionally there is a property migrateInvalidatedSessionAttributes * which tells if on session invalidation we are to migrate all session attributes from the old session to a newly * created one. This is turned on by default, but not used unless invalidateSessionOnSuccessfulAuthentication * is true. If you are using this feature in combination with concurrent session control, you should set the * sessionRegistry property to make sure that the session information is updated consistently. * * @author Ben Alex * @version $Id$ */ public abstract class AbstractProcessingFilter extends SpringSecurityFilter implements InitializingBean, ApplicationEventPublisherAware, MessageSourceAware { //~ Static fields/initializers ===================================================================================== public static final String SPRING_SECURITY_SAVED_REQUEST_KEY = "SPRING_SECURITY_SAVED_REQUEST_KEY"; public static final String SPRING_SECURITY_LAST_EXCEPTION_KEY = "SPRING_SECURITY_LAST_EXCEPTION"; //~ Instance fields ================================================================================================ protected ApplicationEventPublisher eventPublisher; protected AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); private AuthenticationManager authenticationManager; protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private Properties exceptionMappings = new Properties(); /** * Delay use of NullRememberMeServices until initialization so that namespace has a chance to inject * the RememberMeServices implementation into custom implementations. */ private RememberMeServices rememberMeServices = null; private TargetUrlResolver targetUrlResolver = new TargetUrlResolverImpl(); /** Where to redirect the browser to if authentication fails */ private String authenticationFailureUrl; /** * Where to redirect the browser to if authentication is successful but * SPRING_SECURITY_SAVED_REQUEST_KEY is null */ private String defaultTargetUrl; /** * The URL destination that this filter intercepts and processes (usually * something like /j_spring_security_check) */ private String filterProcessesUrl = getDefaultFilterProcessesUrl(); /** * If true, will always redirect to the value of * {@link #getDefaultTargetUrl} upon successful authentication, irrespective * of the page that caused the authentication request (defaults to * false). */ private boolean alwaysUseDefaultTargetUrl = false; /** * Indicates if the filter chain should be continued prior to delegation to * {@link #successfulAuthentication(HttpServletRequest, HttpServletResponse, * Authentication)}, which may be useful in certain environment (eg * Tapestry). Defaults to false. */ private boolean continueChainBeforeSuccessfulAuthentication = false; /** * If true, causes any redirection URLs to be calculated minus the protocol * and context path (defaults to false). */ private boolean useRelativeContext = false; /** * Tells if we on successful authentication should invalidate the * current session. This is a common guard against session fixation attacks. * Defaults to false. */ private boolean invalidateSessionOnSuccessfulAuthentication = false; /** * If {@link #invalidateSessionOnSuccessfulAuthentication} is true, this * flag indicates that the session attributes of the session to be invalidated * are to be migrated to the new session. Defaults to true since * nothing will happpen unless {@link #invalidateSessionOnSuccessfulAuthentication} * is true. */ private boolean migrateInvalidatedSessionAttributes = true; private boolean allowSessionCreation = true; private boolean serverSideRedirect = false; private SessionRegistry sessionRegistry; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(filterProcessesUrl, "filterProcessesUrl must be specified"); Assert.isTrue(UrlUtils.isValidRedirectUrl(filterProcessesUrl), filterProcessesUrl + " isn't a valid redirect URL"); Assert.hasLength(defaultTargetUrl, "defaultTargetUrl must be specified"); Assert.isTrue(UrlUtils.isValidRedirectUrl(defaultTargetUrl), defaultTargetUrl + " isn't a valid redirect URL"); Assert.isTrue(UrlUtils.isValidRedirectUrl(authenticationFailureUrl), authenticationFailureUrl + " isn't a valid redirect URL"); Assert.notNull(authenticationManager, "authenticationManager must be specified"); Assert.notNull(targetUrlResolver, "targetUrlResolver cannot be null"); if (rememberMeServices == null) { rememberMeServices = new NullRememberMeServices(); } } /** * Performs actual authentication. * * @param request from which to extract parameters and perform the * authentication * * @return the authenticated user * * @throws AuthenticationException if authentication fails */ public abstract Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException; public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (requiresAuthentication(request, response)) { if (logger.isDebugEnabled()) { logger.debug("Request is to process authentication"); } Authentication authResult; try { onPreAuthentication(request, response); authResult = attemptAuthentication(request); } catch (AuthenticationException failed) { // Authentication failed unsuccessfulAuthentication(request, response, failed); return; } // Authentication success if (continueChainBeforeSuccessfulAuthentication) { chain.doFilter(request, response); } successfulAuthentication(request, response, authResult); return; } chain.doFilter(request, response); } public static String obtainFullSavedRequestUrl(HttpServletRequest request) { SavedRequest savedRequest = getSavedRequest(request); return savedRequest == null ? null : savedRequest.getFullRequestUrl(); } private static SavedRequest getSavedRequest(HttpServletRequest request) { HttpSession session = request.getSession(false); if (session == null) { return null; } SavedRequest savedRequest = (SavedRequest) session.getAttribute(SPRING_SECURITY_SAVED_REQUEST_KEY); return savedRequest; } protected void onPreAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException { } protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException { } protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { } /** *

* Indicates whether this filter should attempt to process a login request * for the current invocation. *

*

* It strips any parameters from the "path" section of the request URL (such * as the jsessionid parameter in * http://host/myapp/index.html;jsessionid=blah) before matching * against the filterProcessesUrl property. *

*

* Subclasses may override for special requirements, such as Tapestry * integration. *

* * @param request as received from the filter chain * @param response as received from the filter chain * * @return true if the filter should attempt authentication, * false otherwise */ protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) { String uri = request.getRequestURI(); int pathParamIndex = uri.indexOf(';'); if (pathParamIndex > 0) { // strip everything after the first semi-colon uri = uri.substring(0, pathParamIndex); } if ("".equals(request.getContextPath())) { return uri.endsWith(filterProcessesUrl); } return uri.endsWith(request.getContextPath() + filterProcessesUrl); } protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException { RedirectUtils.sendRedirect(request, response, url, useRelativeContext); } protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException, ServletException { if (logger.isDebugEnabled()) { logger.debug("Authentication success: " + authResult.toString()); } SecurityContextHolder.getContext().setAuthentication(authResult); if (logger.isDebugEnabled()) { logger.debug("Updated SecurityContextHolder to contain the following Authentication: '" + authResult + "'"); } if (invalidateSessionOnSuccessfulAuthentication) { SessionUtils.startNewSessionIfRequired(request, migrateInvalidatedSessionAttributes, sessionRegistry); } String targetUrl = determineTargetUrl(request); if (logger.isDebugEnabled()) { logger.debug("Redirecting to target URL from HTTP Session (or default): " + targetUrl); } onSuccessfulAuthentication(request, response, authResult); rememberMeServices.loginSuccess(request, response, authResult); // Fire event if (this.eventPublisher != null) { eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass())); } sendRedirect(request, response, targetUrl); } protected String determineTargetUrl(HttpServletRequest request) { // Don't attempt to obtain the url from the saved request if alwaysUsedefaultTargetUrl is set String targetUrl = alwaysUseDefaultTargetUrl ? null : targetUrlResolver.determineTargetUrl(getSavedRequest(request), request, SecurityContextHolder.getContext().getAuthentication()); if (targetUrl == null) { targetUrl = getDefaultTargetUrl(); } return targetUrl; } protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { SecurityContextHolder.getContext().setAuthentication(null); if (logger.isDebugEnabled()) { logger.debug("Updated SecurityContextHolder to contain null Authentication"); } String failureUrl = determineFailureUrl(request, failed); if (logger.isDebugEnabled()) { logger.debug("Authentication request failed: " + failed.toString()); } try { HttpSession session = request.getSession(false); if (session != null || allowSessionCreation) { request.getSession().setAttribute(SPRING_SECURITY_LAST_EXCEPTION_KEY, failed); } } catch (Exception ignored) { } onUnsuccessfulAuthentication(request, response, failed); rememberMeServices.loginFail(request, response); if (failureUrl == null) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed:" + failed.getMessage()); } else if (serverSideRedirect){ request.getRequestDispatcher(failureUrl).forward(request, response); } else { sendRedirect(request, response, failureUrl); } } protected String determineFailureUrl(HttpServletRequest request, AuthenticationException failed) { return exceptionMappings.getProperty(failed.getClass().getName(), authenticationFailureUrl); } public String getAuthenticationFailureUrl() { return authenticationFailureUrl; } public void setAuthenticationFailureUrl(String authenticationFailureUrl) { this.authenticationFailureUrl = authenticationFailureUrl; } protected AuthenticationManager getAuthenticationManager() { return authenticationManager; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } /** * Specifies the default filterProcessesUrl for the * implementation. * * @return the default filterProcessesUrl */ public abstract String getDefaultFilterProcessesUrl(); /** * Supplies the default target Url that will be used if no saved request is * found or the alwaysUseDefaultTargetUrl propert is set to true. * Override this method of you want to provide a customized default Url (for * example if you want different Urls depending on the authorities of the * user who has just logged in). * * @return the defaultTargetUrl property */ public String getDefaultTargetUrl() { return defaultTargetUrl; } public void setDefaultTargetUrl(String defaultTargetUrl) { Assert.isTrue(defaultTargetUrl.startsWith("/") | defaultTargetUrl.startsWith("http"), "defaultTarget must start with '/' or with 'http(s)'"); this.defaultTargetUrl = defaultTargetUrl; } protected Properties getExceptionMappings() { return new Properties(exceptionMappings); } public void setExceptionMappings(Properties exceptionMappings) { this.exceptionMappings = exceptionMappings; } public String getFilterProcessesUrl() { return filterProcessesUrl; } public void setFilterProcessesUrl(String filterProcessesUrl) { this.filterProcessesUrl = filterProcessesUrl; } public RememberMeServices getRememberMeServices() { return rememberMeServices; } public void setRememberMeServices(RememberMeServices rememberMeServices) { this.rememberMeServices = rememberMeServices; } boolean isAlwaysUseDefaultTargetUrl() { return alwaysUseDefaultTargetUrl; } public void setAlwaysUseDefaultTargetUrl(boolean alwaysUseDefaultTargetUrl) { this.alwaysUseDefaultTargetUrl = alwaysUseDefaultTargetUrl; } public void setContinueChainBeforeSuccessfulAuthentication(boolean continueChainBeforeSuccessfulAuthentication) { this.continueChainBeforeSuccessfulAuthentication = continueChainBeforeSuccessfulAuthentication; } public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setInvalidateSessionOnSuccessfulAuthentication(boolean invalidateSessionOnSuccessfulAuthentication) { this.invalidateSessionOnSuccessfulAuthentication = invalidateSessionOnSuccessfulAuthentication; } public void setMigrateInvalidatedSessionAttributes(boolean migrateInvalidatedSessionAttributes) { this.migrateInvalidatedSessionAttributes = migrateInvalidatedSessionAttributes; } public AuthenticationDetailsSource getAuthenticationDetailsSource() { // Required due to SEC-310 return authenticationDetailsSource; } public void setUseRelativeContext(boolean useRelativeContext) { this.useRelativeContext = useRelativeContext; } protected boolean getAllowSessionCreation() { return allowSessionCreation; } public void setAllowSessionCreation(boolean allowSessionCreation) { this.allowSessionCreation = allowSessionCreation; } /** * @return the targetUrlResolver */ protected TargetUrlResolver getTargetUrlResolver() { return targetUrlResolver; } /** * @param targetUrlResolver the targetUrlResolver to set */ public void setTargetUrlResolver(TargetUrlResolver targetUrlResolver) { this.targetUrlResolver = targetUrlResolver; } /** * Tells if we are to do a server side include of the error URL instead of a 302 redirect. * * @param serverSideRedirect */ public void setServerSideRedirect(boolean serverSideRedirect) { this.serverSideRedirect = serverSideRedirect; } /** * The session registry needs to be set if session fixation attack protection is in use (and concurrent * session control is enabled). */ public void setSessionRegistry(SessionRegistry sessionRegistry) { this.sessionRegistry = sessionRegistry; } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/SessionFixationProtectionFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/SessionFixat0000644000000000000000000001023711623517156030543 0ustar package org.springframework.security.ui; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationTrustResolver; import org.springframework.security.AuthenticationTrustResolverImpl; import org.springframework.security.concurrent.SessionRegistry; import org.springframework.security.context.HttpSessionContextIntegrationFilter; import org.springframework.security.context.SecurityContext; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.util.SessionUtils; /** * Detects that a user has been authenticated since the start of the request and starts a new session. *

* This is essentially a generalization of the functionality that was implemented for SEC-399. * Additionally, it will update the configured SessionRegistry if one is in use, thus preventing problems when used * with Spring Security's concurrent session control. * * @author Martin Algesten * @author Luke Taylor * @since 2.0 */ public class SessionFixationProtectionFilter extends SpringSecurityFilter { //~ Static fields/initializers ===================================================================================== static final String FILTER_APPLIED = "__spring_security_session_fixation_filter_applied"; //~ Instance fields ================================================================================================ private SessionRegistry sessionRegistry; /** * Indicates that the session attributes of the session to be invalidated * should be migrated to the new session. Defaults to true. */ private boolean migrateSessionAttributes = true; private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); protected void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { // Session fixation isn't a problem if there's no session if(request.getSession(false) == null || request.getAttribute(FILTER_APPLIED) != null || !request.isRequestedSessionIdValid()) { chain.doFilter(request, response); return; } request.setAttribute(FILTER_APPLIED, Boolean.TRUE); HttpSession session = request.getSession(); SecurityContext sessionSecurityContext = (SecurityContext) session.getAttribute(HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY); if (sessionSecurityContext == null && isAuthenticated()) { // The user has been authenticated during the current request, so do the session migration startNewSessionIfRequired(request, response); } chain.doFilter(request, response); } private boolean isAuthenticated() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); return authentication != null && !authenticationTrustResolver.isAnonymous(authentication); } public void setMigrateSessionAttributes(boolean migrateSessionAttributes) { this.migrateSessionAttributes = migrateSessionAttributes; } public void setSessionRegistry(SessionRegistry sessionRegistry) { this.sessionRegistry = sessionRegistry; } public int getOrder() { return FilterChainOrder.SESSION_FIXATION_FILTER; } /** * Called when the a user wasn't authenticated at the start of the request but has been during it *

* A new session will be created, the session attributes copied to it (if * migrateSessionAttributes is set) and the sessionRegistry updated with the new session information. */ protected void startNewSessionIfRequired(HttpServletRequest request, HttpServletResponse response) { SessionUtils.startNewSessionIfRequired(request, migrateSessionAttributes, sessionRegistry); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/savedrequest/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/savedrequest0000755000000000000000000000000011623517156030632 5ustar ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/savedrequest/Enumerator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/savedrequest0000644000000000000000000001063511623517156030641 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.savedrequest; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; /** *

Adapter that wraps an Enumeration around a Java 2 collection Iterator.

*

Constructors are provided to easily create such wrappers.

*

This class is based on code in Apache Tomcat.

* * @author Craig McClanahan * @author Andrey Grebnev * @version $Id$ */ public class Enumerator implements Enumeration { //~ Instance fields ================================================================================================ /** * The Iterator over which the Enumeration represented by this class actually operates. */ private Iterator iterator = null; //~ Constructors =================================================================================================== /** * Return an Enumeration over the values of the specified Collection. * * @param collection Collection whose values should be enumerated */ public Enumerator(Collection collection) { this(collection.iterator()); } /** * Return an Enumeration over the values of the specified Collection. * * @param collection Collection whose values should be enumerated * @param clone true to clone iterator */ public Enumerator(Collection collection, boolean clone) { this(collection.iterator(), clone); } /** * Return an Enumeration over the values returned by the specified * Iterator. * * @param iterator Iterator to be wrapped */ public Enumerator(Iterator iterator) { super(); this.iterator = iterator; } /** * Return an Enumeration over the values returned by the specified * Iterator. * * @param iterator Iterator to be wrapped * @param clone true to clone iterator */ public Enumerator(Iterator iterator, boolean clone) { super(); if (!clone) { this.iterator = iterator; } else { List list = new ArrayList(); while (iterator.hasNext()) { list.add(iterator.next()); } this.iterator = list.iterator(); } } /** * Return an Enumeration over the values of the specified Map. * * @param map Map whose values should be enumerated */ public Enumerator(Map map) { this(map.values().iterator()); } /** * Return an Enumeration over the values of the specified Map. * * @param map Map whose values should be enumerated * @param clone true to clone iterator */ public Enumerator(Map map, boolean clone) { this(map.values().iterator(), clone); } //~ Methods ======================================================================================================== /** * Tests if this enumeration contains more elements. * * @return true if and only if this enumeration object contains at least one more element to provide, * false otherwise */ public boolean hasMoreElements() { return (iterator.hasNext()); } /** * Returns the next element of this enumeration if this enumeration has at least one more element to * provide. * * @return the next element of this enumeration * * @exception NoSuchElementException if no more elements exist */ public Object nextElement() throws NoSuchElementException { return (iterator.next()); } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/savedrequest/SavedCookie.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/savedrequest0000644000000000000000000000413011623517156030632 0ustar package org.springframework.security.ui.savedrequest; import javax.servlet.http.Cookie; import java.io.Serializable; /** * Stores off the values of a cookie in a serializable holder * * @author Ray Krueger */ public class SavedCookie implements Serializable { private java.lang.String name; private java.lang.String value; private java.lang.String comment; private java.lang.String domain; private int maxAge; private java.lang.String path; private boolean secure; private int version; public SavedCookie(String name, String value, String comment, String domain, int maxAge, String path, boolean secure, int version) { this.name = name; this.value = value; this.comment = comment; this.domain = domain; this.maxAge = maxAge; this.path = path; this.secure = secure; this.version = version; } public SavedCookie(Cookie cookie) { this(cookie.getName(), cookie.getValue(), cookie.getComment(), cookie.getDomain(), cookie.getMaxAge(), cookie.getPath(), cookie.getSecure(), cookie.getVersion()); } public String getName() { return name; } public String getValue() { return value; } public String getComment() { return comment; } public String getDomain() { return domain; } public int getMaxAge() { return maxAge; } public String getPath() { return path; } public boolean isSecure() { return secure; } public int getVersion() { return version; } public Cookie getCookie() { Cookie c = new Cookie(getName(), getValue()); if (getComment() != null) c.setComment(getComment()); if (getDomain() != null) c.setDomain(getDomain()); if (getPath() != null) c.setPath(getPath()); c.setVersion(getVersion()); c.setMaxAge(getMaxAge()); c.setSecure(isSecure()); return c; } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/savedrequest/SavedRequest.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/savedrequest0000644000000000000000000002614011623517156030637 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.savedrequest; import org.springframework.security.util.PortResolver; import org.springframework.security.util.UrlUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TreeMap; /** * Represents central information from a HttpServletRequest.

This class is used by {@link * org.springframework.security.ui.AbstractProcessingFilter} and {@link org.springframework.security.wrapper.SavedRequestAwareWrapper} to * reproduce the request after successful authentication. An instance of this class is stored at the time of an * authentication exception by {@link org.springframework.security.ui.ExceptionTranslationFilter}.

*

IMPLEMENTATION NOTE: It is assumed that this object is accessed only from the context of a single * thread, so no synchronization around internal collection classes is performed.

*

This class is based on code in Apache Tomcat.

* * @author Craig McClanahan * @author Andrey Grebnev * @author Ben Alex * @version $Id$ */ public class SavedRequest implements java.io.Serializable { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(SavedRequest.class); //~ Instance fields ================================================================================================ private ArrayList cookies = new ArrayList(); private ArrayList locales = new ArrayList(); private Map headers = new TreeMap(String.CASE_INSENSITIVE_ORDER); private Map parameters = new TreeMap(String.CASE_INSENSITIVE_ORDER); private String contextPath; private String method; private String pathInfo; private String queryString; private String requestURI; private String requestURL; private String scheme; private String serverName; private String servletPath; private int serverPort; //~ Constructors =================================================================================================== public SavedRequest(HttpServletRequest request, PortResolver portResolver) { Assert.notNull(request, "Request required"); Assert.notNull(portResolver, "PortResolver required"); // Cookies Cookie[] cookies = request.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { this.addCookie(cookies[i]); } } // Headers Enumeration names = request.getHeaderNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); Enumeration values = request.getHeaders(name); while (values.hasMoreElements()) { String value = (String) values.nextElement(); this.addHeader(name, value); } } // Locales Enumeration locales = request.getLocales(); while (locales.hasMoreElements()) { Locale locale = (Locale) locales.nextElement(); this.addLocale(locale); } // Parameters Map parameters = request.getParameterMap(); Iterator paramNames = parameters.keySet().iterator(); while (paramNames.hasNext()) { String paramName = (String) paramNames.next(); Object o = parameters.get(paramName); if (o instanceof String[]) { String[] paramValues = (String[]) o; this.addParameter(paramName, paramValues); } else { if (logger.isWarnEnabled()) { logger.warn("ServletRequest.getParameterMap() returned non-String array"); } } } // Primitives this.method = request.getMethod(); this.pathInfo = request.getPathInfo(); this.queryString = request.getQueryString(); this.requestURI = request.getRequestURI(); this.serverPort = portResolver.getServerPort(request); this.requestURL = request.getRequestURL().toString(); this.scheme = request.getScheme(); this.serverName = request.getServerName(); this.contextPath = request.getContextPath(); this.servletPath = request.getServletPath(); } //~ Methods ======================================================================================================== private void addCookie(Cookie cookie) { cookies.add(new SavedCookie(cookie)); } private void addHeader(String name, String value) { ArrayList values = (ArrayList) headers.get(name); if (values == null) { values = new ArrayList(); headers.put(name, values); } values.add(value); } private void addLocale(Locale locale) { locales.add(locale); } private void addParameter(String name, String[] values) { parameters.put(name, values); } /** * Determines if the current request matches the SavedRequest. All URL arguments are * considered, but not method (POST/GET), cookies, locales, headers or parameters. * * @param request DOCUMENT ME! * @param portResolver DOCUMENT ME! * @return DOCUMENT ME! */ public boolean doesRequestMatch(HttpServletRequest request, PortResolver portResolver) { Assert.notNull(request, "Request required"); Assert.notNull(portResolver, "PortResolver required"); if (!propertyEquals("pathInfo", this.pathInfo, request.getPathInfo())) { return false; } if (!propertyEquals("queryString", this.queryString, request.getQueryString())) { return false; } if (!propertyEquals("requestURI", this.requestURI, request.getRequestURI())) { return false; } if (!propertyEquals("serverPort", new Integer(this.serverPort), new Integer(portResolver.getServerPort(request)))) { return false; } if (!propertyEquals("requestURL", this.requestURL, request.getRequestURL().toString())) { return false; } if (!propertyEquals("scheme", this.scheme, request.getScheme())) { return false; } if (!propertyEquals("serverName", this.serverName, request.getServerName())) { return false; } if (!propertyEquals("contextPath", this.contextPath, request.getContextPath())) { return false; } if (!propertyEquals("servletPath", this.servletPath, request.getServletPath())) { return false; } return true; } public String getContextPath() { return contextPath; } public List getCookies() { List cookieList = new ArrayList(cookies.size()); for (Iterator iterator = cookies.iterator(); iterator.hasNext();) { SavedCookie savedCookie = (SavedCookie) iterator.next(); cookieList.add(savedCookie.getCookie()); } return cookieList; } /** * Indicates the URL that the user agent used for this request. * * @return the full URL of this request */ public String getFullRequestUrl() { return UrlUtils.getFullRequestUrl(this); } public Iterator getHeaderNames() { return (headers.keySet().iterator()); } public Iterator getHeaderValues(String name) { ArrayList values = (ArrayList) headers.get(name); if (values == null) { return ((new ArrayList()).iterator()); } else { return (values.iterator()); } } public Iterator getLocales() { return (locales.iterator()); } public String getMethod() { return (this.method); } public Map getParameterMap() { return parameters; } public Iterator getParameterNames() { return (parameters.keySet().iterator()); } public String[] getParameterValues(String name) { return ((String[]) parameters.get(name)); } public String getPathInfo() { return pathInfo; } public String getQueryString() { return (this.queryString); } public String getRequestURI() { return (this.requestURI); } public String getRequestURL() { return requestURL; } /** * Obtains the web application-specific fragment of the URL. * * @return the URL, excluding any server name, context path or servlet path */ public String getRequestUrl() { return UrlUtils.getRequestUrl(this); } public String getScheme() { return scheme; } public String getServerName() { return serverName; } public int getServerPort() { return serverPort; } public String getServletPath() { return servletPath; } private boolean propertyEquals(String log, Object arg1, Object arg2) { if ((arg1 == null) && (arg2 == null)) { if (logger.isDebugEnabled()) { logger.debug(log + ": both null (property equals)"); } return true; } if (((arg1 == null) && (arg2 != null)) || ((arg1 != null) && (arg2 == null))) { if (logger.isDebugEnabled()) { logger.debug(log + ": arg1=" + arg1 + "; arg2=" + arg2 + " (property not equals)"); } return false; } if (arg1.equals(arg2)) { if (logger.isDebugEnabled()) { logger.debug(log + ": arg1=" + arg1 + "; arg2=" + arg2 + " (property equals)"); } return true; } else { if (logger.isDebugEnabled()) { logger.debug(log + ": arg1=" + arg1 + "; arg2=" + arg2 + " (property not equals)"); } return false; } } public String toString() { return "SavedRequest[" + getFullRequestUrl() + "]"; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/savedrequest/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/savedrequest0000644000000000000000000000024311623517156030633 0ustar Stores a HttpServletRequest so that it can subsequently be emulated by the SavedRequestAwareWrapper. ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/savedrequest/FastHttpDateFormat.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/savedrequest0000644000000000000000000001525611623517156030645 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.savedrequest; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.TimeZone; /** *

Utility class to generate HTTP dates.

*

This class is based on code in Apache Tomcat.

* * @author Remy Maucherat * @author Andrey Grebnev * @version $Id$ */ public class FastHttpDateFormat { //~ Static fields/initializers ===================================================================================== /** HTTP date format. */ protected static final SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); /** The set of SimpleDateFormat formats to use in getDateHeader(). */ protected static final SimpleDateFormat[] formats = { new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US), new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US), new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) }; /** GMT timezone - all HTTP dates are on GMT */ protected static final TimeZone gmtZone = TimeZone.getTimeZone("GMT"); static { format.setTimeZone(gmtZone); formats[0].setTimeZone(gmtZone); formats[1].setTimeZone(gmtZone); formats[2].setTimeZone(gmtZone); } /** Instant on which the currentDate object was generated. */ protected static long currentDateGenerated = 0L; /** Current formatted date. */ protected static String currentDate = null; /** Formatter cache. */ protected static final HashMap formatCache = new HashMap(); /** Parser cache. */ protected static final HashMap parseCache = new HashMap(); //~ Methods ======================================================================================================== /** * Formats a specified date to HTTP format. If local format is not null, it's used instead. * * @param value Date value to format * @param threadLocalformat The format to use (or null -- then HTTP format will be used) * * @return Formatted date */ public static final String formatDate(long value, DateFormat threadLocalformat) { String cachedDate = null; Long longValue = new Long(value); try { cachedDate = (String) formatCache.get(longValue); } catch (Exception e) {} if (cachedDate != null) { return cachedDate; } String newDate = null; Date dateValue = new Date(value); if (threadLocalformat != null) { newDate = threadLocalformat.format(dateValue); synchronized (formatCache) { updateCache(formatCache, longValue, newDate); } } else { synchronized (formatCache) { newDate = format.format(dateValue); updateCache(formatCache, longValue, newDate); } } return newDate; } /** * Gets the current date in HTTP format. * * @return Current date in HTTP format */ public static final String getCurrentDate() { long now = System.currentTimeMillis(); if ((now - currentDateGenerated) > 1000) { synchronized (format) { if ((now - currentDateGenerated) > 1000) { currentDateGenerated = now; currentDate = format.format(new Date(now)); } } } return currentDate; } /** * Parses date with given formatters. * * @param value The string to parse * @param formats Array of formats to use * * @return Parsed date (or null if no formatter mached) */ private static Long internalParseDate(String value, DateFormat[] formats) { Date date = null; for (int i = 0; (date == null) && (i < formats.length); i++) { try { date = formats[i].parse(value); } catch (ParseException e) { ; } } if (date == null) { return null; } return new Long(date.getTime()); } /** * Tries to parse the given date as an HTTP date. If local format list is not null, it's used * instead. * * @param value The string to parse * @param threadLocalformats Array of formats to use for parsing. If null, HTTP formats are used. * * @return Parsed date (or -1 if error occured) */ public static final long parseDate(String value, DateFormat[] threadLocalformats) { Long cachedDate = null; try { cachedDate = (Long) parseCache.get(value); } catch (Exception e) {} if (cachedDate != null) { return cachedDate.longValue(); } Long date = null; if (threadLocalformats != null) { date = internalParseDate(value, threadLocalformats); synchronized (parseCache) { updateCache(parseCache, value, date); } } else { synchronized (parseCache) { date = internalParseDate(value, formats); updateCache(parseCache, value, date); } } if (date == null) { return (-1L); } else { return date.longValue(); } } /** * Updates cache. * * @param cache Cache to be updated * @param key Key to be updated * @param value New value */ private static void updateCache(HashMap cache, Object key, Object value) { if (value == null) { return; } if (cache.size() > 1000) { cache.clear(); } cache.put(key, value); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/switchuser/0000755000000000000000000000000011623517156030376 5ustar ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/switchuser/SwitchUserAuthorityChanger.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/switchuser/S0000644000000000000000000000240311623517156030522 0ustar package org.springframework.security.ui.switchuser; import java.util.List; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; import org.springframework.security.userdetails.UserDetails; /** * Allows subclasses to modify the {@link GrantedAuthority} list that will be assigned to the principal * when they assume the identity of a different principal. * *

Configured against the {@link SwitchUserProcessingFilter}. * * @author Ben Alex * @version $Id$ * */ public interface SwitchUserAuthorityChanger { /** * Allow subclasses to add or remove authorities that will be granted when in switch user mode. * * @param targetUser the UserDetails representing the identity being switched to * @param currentAuthentication the current Authentication of the principal performing the switching * @param authoritiesToBeGranted all {@link GrantedAuthority} instances to be granted to the user, * excluding the special "switch user" authority that is used internally (guaranteed never null) * * @return the modified list of granted authorities. */ List modifyGrantedAuthorities(UserDetails targetUser, Authentication currentAuthentication, List authoritiesToBeGranted); } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/switchuser/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/switchuser/p0000644000000000000000000000013111623517156030553 0ustar Provides HTTP-based "switch user" (su) capabilities. ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/switchuser/SwitchUserGrantedAuthority.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/switchuser/S0000644000000000000000000000405211623517156030524 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.switchuser; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthorityImpl; /** * Custom GrantedAuthority used by {@link org.springframework.security.ui.switchuser.SwitchUserProcessingFilter}

Stores * the Authentication object of the original user to be used later when 'exiting' from a user switch.

* * @author Mark St.Godard * @version $Id$ * * @see org.springframework.security.ui.switchuser.SwitchUserProcessingFilter */ public class SwitchUserGrantedAuthority extends GrantedAuthorityImpl { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Authentication source; //~ Constructors =================================================================================================== public SwitchUserGrantedAuthority(String role, Authentication source) { super(role); this.source = source; } //~ Methods ======================================================================================================== /** * Returns the original user associated with a successful user switch. * * @return The original Authentication object of the switched user. */ public Authentication getSource() { return source; } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/switchuser/SwitchUserProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/switchuser/S0000644000000000000000000004715311623517156030535 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.switchuser; import org.springframework.security.AccountExpiredException; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationCredentialsNotFoundException; import org.springframework.security.AuthenticationException; import org.springframework.security.CredentialsExpiredException; import org.springframework.security.DisabledException; import org.springframework.security.GrantedAuthority; import org.springframework.security.LockedException; import org.springframework.security.util.RedirectUtils; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.event.authentication.AuthenticationSwitchUserEvent; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.ui.AuthenticationDetailsSource; import org.springframework.security.ui.WebAuthenticationDetailsSource; import org.springframework.security.ui.SpringSecurityFilter; import org.springframework.security.ui.FilterChainOrder; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.security.userdetails.UserDetailsChecker; import org.springframework.security.userdetails.checker.AccountStatusUserDetailsChecker; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Switch User processing filter responsible for user context switching. *

* This filter is similar to Unix 'su' however for Spring Security-managed web applications. * A common use-case for this feature is the ability to allow higher-authority users (e.g. ROLE_ADMIN) to switch to a * regular user (e.g. ROLE_USER). *

* This filter assumes that the user performing the switch will be required to be logged in as normal (i.e. * as a ROLE_ADMIN user). The user will then access a page/controller that enables the administrator to specify who they * wish to become (see switchUserUrl).
* Note: This URL will be required to have to appropriate security contraints configured so that only users of that * role can access (e.g. ROLE_ADMIN). *

* On successful switch, the user's SecurityContextHolder will be updated to reflect the * specified user and will also contain an additinal * {@link org.springframework.security.ui.switchuser.SwitchUserGrantedAuthority} which contains the original user. *

* To 'exit' from a user context, the user will then need to access a URL (see exitUserUrl) that * will switch back to the original user as identified by the ROLE_PREVIOUS_ADMINISTRATOR. *

* To configure the Switch User Processing Filter, create a bean definition for the Switch User processing * filter and add to the filterChainProxy. Note that the filter must come after the * FilterSecurityInteceptor in the chain, in order to apply the correct constraints to the switchUserUrl. * Example:

 * <bean id="switchUserProcessingFilter" class="org.springframework.security.ui.switchuser.SwitchUserProcessingFilter">
 *    <property name="userDetailsService" ref="userDetailsService" />
 *    <property name="switchUserUrl"><value>/j_spring_security_switch_user</value></property>
 *    <property name="exitUserUrl"><value>/j_spring_security_exit_user</value></property>
 *    <property name="targetUrl"><value>/index.jsp</value></property></bean>
 * 
* * @author Mark St.Godard * @version $Id$ * * @see org.springframework.security.ui.switchuser.SwitchUserGrantedAuthority */ public class SwitchUserProcessingFilter extends SpringSecurityFilter implements InitializingBean, ApplicationEventPublisherAware, MessageSourceAware { //~ Static fields/initializers ===================================================================================== public static final String SPRING_SECURITY_SWITCH_USERNAME_KEY = "j_username"; public static final String ROLE_PREVIOUS_ADMINISTRATOR = "ROLE_PREVIOUS_ADMINISTRATOR"; //~ Instance fields ================================================================================================ private ApplicationEventPublisher eventPublisher; private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private String exitUserUrl = "/j_spring_security_exit_user"; private String switchUserUrl = "/j_spring_security_switch_user"; private String targetUrl; private String switchFailureUrl; private SwitchUserAuthorityChanger switchUserAuthorityChanger; private UserDetailsService userDetailsService; private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); private boolean useRelativeContext; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(switchUserUrl, "switchUserUrl must be specified"); Assert.hasLength(exitUserUrl, "exitUserUrl must be specified"); Assert.hasLength(targetUrl, "targetUrl must be specified"); Assert.notNull(userDetailsService, "authenticationDao must be specified"); Assert.notNull(messages, "A message source must be set"); } /** * Attempt to exit from an already switched user. * * @param request The http servlet request * * @return The original Authentication object or null otherwise. * * @throws AuthenticationCredentialsNotFoundException If no Authentication associated with this * request. */ protected Authentication attemptExitUser(HttpServletRequest request) throws AuthenticationCredentialsNotFoundException { // need to check to see if the current user has a SwitchUserGrantedAuthority Authentication current = SecurityContextHolder.getContext().getAuthentication(); if (null == current) { throw new AuthenticationCredentialsNotFoundException(messages.getMessage( "SwitchUserProcessingFilter.noCurrentUser", "No current user associated with this request")); } // check to see if the current user did actual switch to another user // if so, get the original source user so we can switch back Authentication original = getSourceAuthentication(current); if (original == null) { logger.error("Could not find original user Authentication object!"); throw new AuthenticationCredentialsNotFoundException(messages.getMessage( "SwitchUserProcessingFilter.noOriginalAuthentication", "Could not find original Authentication object")); } // get the source user details UserDetails originalUser = null; Object obj = original.getPrincipal(); if ((obj != null) && obj instanceof UserDetails) { originalUser = (UserDetails) obj; } // publish event if (this.eventPublisher != null) { eventPublisher.publishEvent(new AuthenticationSwitchUserEvent(current, originalUser)); } return original; } /** * Attempt to switch to another user. If the user does not exist or is not active, return null. * * @return The new Authentication request if successfully switched to another user, null * otherwise. * * @throws UsernameNotFoundException If the target user is not found. * @throws LockedException if the account is locked. * @throws DisabledException If the target user is disabled. * @throws AccountExpiredException If the target user account is expired. * @throws CredentialsExpiredException If the target user credentials are expired. */ protected Authentication attemptSwitchUser(HttpServletRequest request) throws AuthenticationException { UsernamePasswordAuthenticationToken targetUserRequest = null; String username = request.getParameter(SPRING_SECURITY_SWITCH_USERNAME_KEY); if (username == null) { username = ""; } if (logger.isDebugEnabled()) { logger.debug("Attempt to switch to user [" + username + "]"); } UserDetails targetUser = userDetailsService.loadUserByUsername(username); userDetailsChecker.check(targetUser); // ok, create the switch user token targetUserRequest = createSwitchUserToken(request, targetUser); if (logger.isDebugEnabled()) { logger.debug("Switch User Token [" + targetUserRequest + "]"); } // publish event if (this.eventPublisher != null) { eventPublisher.publishEvent(new AuthenticationSwitchUserEvent( SecurityContextHolder.getContext().getAuthentication(), targetUser)); } return targetUserRequest; } /** * Create a switch user token that contains an additional GrantedAuthority that contains the * original Authentication object. * * @param request The http servlet request. * @param targetUser The target user * * @return The authentication token * * @see SwitchUserGrantedAuthority */ private UsernamePasswordAuthenticationToken createSwitchUserToken(HttpServletRequest request, UserDetails targetUser) { UsernamePasswordAuthenticationToken targetUserRequest; // grant an additional authority that contains the original Authentication object // which will be used to 'exit' from the current switched user. Authentication currentAuth = SecurityContextHolder.getContext().getAuthentication(); GrantedAuthority switchAuthority = new SwitchUserGrantedAuthority(ROLE_PREVIOUS_ADMINISTRATOR, currentAuth); // get the original authorities List orig = Arrays.asList(targetUser.getAuthorities()); // Allow subclasses to change the authorities to be granted if (switchUserAuthorityChanger != null) { orig = switchUserAuthorityChanger.modifyGrantedAuthorities(targetUser, currentAuth, orig); } // add the new switch user authority List newAuths = new ArrayList(orig); newAuths.add(switchAuthority); GrantedAuthority[] authorities = (GrantedAuthority[]) newAuths.toArray(new GrantedAuthority[newAuths.size()]); // create the new authentication token targetUserRequest = new UsernamePasswordAuthenticationToken(targetUser, targetUser.getPassword(), authorities); // set details targetUserRequest.setDetails(authenticationDetailsSource.buildDetails(request)); return targetUserRequest; } public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { // check for switch or exit request if (requiresSwitchUser(request)) { // if set, attempt switch and store original try { Authentication targetUser = attemptSwitchUser(request); // update the current context to the new target user SecurityContextHolder.getContext().setAuthentication(targetUser); // redirect to target url sendRedirect(request, response, targetUrl); } catch (AuthenticationException e) { redirectToFailureUrl(request, response, e); } return; } else if (requiresExitUser(request)) { // get the original authentication object (if exists) Authentication originalUser = attemptExitUser(request); // update the current context back to the original user SecurityContextHolder.getContext().setAuthentication(originalUser); // redirect to target url sendRedirect(request, response, targetUrl); return; } chain.doFilter(request, response); } private void redirectToFailureUrl(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { logger.debug("Switch User failed", failed); if (switchFailureUrl != null) { sendRedirect(request, response, switchFailureUrl); } else { response.getWriter().print("Switch user failed: " + failed.getMessage()); response.flushBuffer(); } } protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException { RedirectUtils.sendRedirect(request, response, url, useRelativeContext); } /** * Find the original Authentication object from the current user's granted authorities. A * successfully switched user should have a SwitchUserGrantedAuthority that contains the original * source user Authentication object. * * @param current The current Authentication object * * @return The source user Authentication object or null otherwise. */ private Authentication getSourceAuthentication(Authentication current) { Authentication original = null; // iterate over granted authorities and find the 'switch user' authority GrantedAuthority[] authorities = current.getAuthorities(); for (int i = 0; i < authorities.length; i++) { // check for switch user type of authority if (authorities[i] instanceof SwitchUserGrantedAuthority) { original = ((SwitchUserGrantedAuthority) authorities[i]).getSource(); logger.debug("Found original switch user granted authority [" + original + "]"); } } return original; } /** * Checks the request URI for the presence of exitUserUrl. * * @param request The http servlet request * * @return true if the request requires a exit user, false otherwise. * * @see SwitchUserProcessingFilter#exitUserUrl */ protected boolean requiresExitUser(HttpServletRequest request) { String uri = stripUri(request); return uri.endsWith(request.getContextPath() + exitUserUrl); } /** * Checks the request URI for the presence of switchUserUrl. * * @param request The http servlet request * * @return true if the request requires a switch, false otherwise. * * @see SwitchUserProcessingFilter#switchUserUrl */ protected boolean requiresSwitchUser(HttpServletRequest request) { String uri = stripUri(request); return uri.endsWith(request.getContextPath() + switchUserUrl); } public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) throws BeansException { this.eventPublisher = eventPublisher; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } /** * Set the URL to respond to exit user processing. * * @param exitUserUrl The exit user URL. */ public void setExitUserUrl(String exitUserUrl) { this.exitUserUrl = exitUserUrl; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } /** * Set the URL to respond to switch user processing. * * @param switchUserUrl The switch user URL. */ public void setSwitchUserUrl(String switchUserUrl) { this.switchUserUrl = switchUserUrl; } /** * Sets the URL to go to after a successful switch / exit user request. * * @param targetUrl The target url. */ public void setTargetUrl(String targetUrl) { this.targetUrl = targetUrl; } /** * Sets the authentication data access object. * * @param userDetailsService The authentication dao */ public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } /** * Analogous to the same property in {@link AbstractProcessingFilter}. If set, redirects will * be context-relative (they won't include the context path). * * @param useRelativeContext set to true to exclude the context path from redirect URLs. */ public void setUseRelativeContext(boolean useRelativeContext) { this.useRelativeContext = useRelativeContext; } /** * Sets the URL to which a user should be redirected if the swittch fails. For example, this might happen because * the account they are attempting to switch to is invalid (the user doesn't exist, account is locked etc). *

* If not set, an error essage wil be written to the response. * * @param switchFailureUrl the url to redirect to. */ public void setSwitchFailureUrl(String switchFailureUrl) { this.switchFailureUrl = switchFailureUrl; } /** * Strips any content after the ';' in the request URI * * @param request The http request * * @return The stripped uri */ private static String stripUri(HttpServletRequest request) { String uri = request.getRequestURI(); int idx = uri.indexOf(';'); if (idx > 0) { uri = uri.substring(0, idx); } return uri; } /** * @param switchUserAuthorityChanger to use to fine-tune the authorities granted to subclasses (may be null if * SwitchUserProcessingFilter shoudl not fine-tune the authorities) */ public void setSwitchUserAuthorityChanger(SwitchUserAuthorityChanger switchUserAuthorityChanger) { this.switchUserAuthorityChanger = switchUserAuthorityChanger; } public int getOrder() { return FilterChainOrder.SWITCH_USER_FILTER; } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/AuthenticationDetailsSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/Authenticati0000644000000000000000000000252411623517156030546 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui; /** * Provides a {@link org.springframework.security.Authentication#getDetails()} object for * a given web request. * * @author Ben Alex * @version $Id$ */ public interface AuthenticationDetailsSource { //~ Methods ======================================================================================================== /** * Called by a class when it wishes a new authentication details instance to be created. * * @param context the request object, which may be used by the authentication details object * * @return a fully-configured authentication details instance */ Object buildDetails(Object context); } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/AccessDeniedHandlerImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/AccessDenied0000644000000000000000000000750611623517156030443 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui; import org.springframework.security.AccessDeniedException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Base implementation of {@link AccessDeniedHandler}.

This implementation sends a 403 (SC_FORBIDDEN) HTTP error * code. In addition, if a {@link #errorPage} is defined, the implementation will perform a request dispatcher * "forward" to the specified error page view. Being a "forward", the SecurityContextHolder will remain * populated. This is of benefit if the view (or a tag library or macro) wishes to access the * SecurityContextHolder. The request scope will also be populated with the exception itself, available * from the key {@link #SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY}.

* * @author Ben Alex * @version $Id$ */ public class AccessDeniedHandlerImpl implements AccessDeniedHandler { //~ Static fields/initializers ===================================================================================== public static final String SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY = "SPRING_SECURITY_403_EXCEPTION"; protected static final Log logger = LogFactory.getLog(AccessDeniedHandlerImpl.class); //~ Instance fields ================================================================================================ private String errorPage; //~ Methods ======================================================================================================== public void handle(ServletRequest request, ServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { if (errorPage != null) { // Put exception into request scope (perhaps of use to a view) ((HttpServletRequest) request).setAttribute(SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY, accessDeniedException); // Perform RequestDispatcher "forward" RequestDispatcher rd = request.getRequestDispatcher(errorPage); rd.forward(request, response); } if (!response.isCommitted()) { // Send 403 (we do this after response has been written) ((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage()); } } /** * The error page to use. Must begin with a "/" and is interpreted relative to the current context root. * * @param errorPage the dispatcher path to display * * @throws IllegalArgumentException if the argument doesn't comply with the above limitations */ public void setErrorPage(String errorPage) { if ((errorPage != null) && !errorPage.startsWith("/")) { throw new IllegalArgumentException("errorPage must begin with '/'"); } this.errorPage = errorPage; } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/0000755000000000000000000000000011623517156027646 5ustar ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/PreAuthenticatedProcessingFilterEntryPoint.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/PreA0000644000000000000000000000435111623517156030423 0ustar package org.springframework.security.ui.preauth; import org.springframework.security.AuthenticationException; import org.springframework.security.ui.AuthenticationEntryPoint; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.Ordered; /** *

* In the pre-authenticated authentication case (unlike CAS, for example) the * user will already have been identified through some external mechanism and a * secure context established by the time the security-enforcement filter is * invoked. *

* Therefore this class isn't actually responsible for the commencement of * authentication, as it is in the case of other providers. It will be called if * the user is rejected by the AbstractPreAuthenticatedProcessingFilter, * resulting in a null authentication. *

* The commence method will always return an * HttpServletResponse.SC_FORBIDDEN (403 error). *

* This code is based on * {@link org.springframework.security.ui.x509.X509ProcessingFilterEntryPoint}. * * @see org.springframework.security.ui.ExceptionTranslationFilter * * @author Luke Taylor * @author Ruud Senden * @since 2.0 */ public class PreAuthenticatedProcessingFilterEntryPoint implements AuthenticationEntryPoint, Ordered { private static final Log logger = LogFactory.getLog(PreAuthenticatedProcessingFilterEntryPoint.class); private int order = Integer.MAX_VALUE; /** * Always returns a 403 error code to the client. */ public void commence(ServletRequest request, ServletResponse response, AuthenticationException arg2) throws IOException, ServletException { if (logger.isDebugEnabled()) { logger.debug("Pre-authenticated entry point called. Rejecting access"); } HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied"); } public int getOrder() { return order; } public void setOrder(int i) { order = i; } } ././@LongLink0000000000000000000000000000024000000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/PreA0000644000000000000000000000270011623517156030417 0ustar package org.springframework.security.ui.preauth; import javax.servlet.http.HttpServletRequest; import org.springframework.security.ui.WebAuthenticationDetails; import org.springframework.security.GrantedAuthoritiesContainerImpl; import org.springframework.security.GrantedAuthority; import org.springframework.security.MutableGrantedAuthoritiesContainer; /** * This WebAuthenticationDetails implementation allows for storing a list of * pre-authenticated Granted Authorities. * * @author Ruud Senden * @author Luke Taylor * @since 2.0 */ public class PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails extends WebAuthenticationDetails implements MutableGrantedAuthoritiesContainer { public static final long serialVersionUID = 1L; private MutableGrantedAuthoritiesContainer authoritiesContainer = new GrantedAuthoritiesContainerImpl(); public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(HttpServletRequest request) { super(request); } public GrantedAuthority[] getGrantedAuthorities() { return authoritiesContainer.getGrantedAuthorities(); } public void setGrantedAuthorities(GrantedAuthority[] authorities) { this.authoritiesContainer.setGrantedAuthorities(authorities); } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString() + "; "); sb.append(authoritiesContainer); return sb.toString(); } } ././@LongLink0000000000000000000000000000023500000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/PreAuthenticatedGrantedAuthoritiesAuthenticationDetails.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/PreA0000644000000000000000000000401011623517156030413 0ustar package org.springframework.security.ui.preauth; import java.util.Arrays; import org.springframework.security.GrantedAuthority; import org.springframework.security.MutableGrantedAuthoritiesContainer; import org.springframework.security.ui.AuthenticationDetails; import org.springframework.util.Assert; /** * This AuthenticationDetails implementation allows for storing a list of * pre-authenticated Granted Authorities. * * @author Ruud Senden * @since 2.0 */ public class PreAuthenticatedGrantedAuthoritiesAuthenticationDetails extends AuthenticationDetails implements MutableGrantedAuthoritiesContainer { public static final long serialVersionUID = 1L; private GrantedAuthority[] preAuthenticatedGrantedAuthorities = null; public PreAuthenticatedGrantedAuthoritiesAuthenticationDetails(Object context) { super(context); } /** * @return The String representation of this object. */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString() + "; "); sb.append("preAuthenticatedGrantedAuthorities: " + Arrays.asList(preAuthenticatedGrantedAuthorities)); return sb.toString(); } /** * * @see org.springframework.security.GrantedAuthoritiesContainer#getGrantedAuthorities() */ public GrantedAuthority[] getGrantedAuthorities() { Assert.notNull(preAuthenticatedGrantedAuthorities, "Pre-authenticated granted authorities have not been set"); GrantedAuthority[] result = new GrantedAuthority[preAuthenticatedGrantedAuthorities.length]; System.arraycopy(preAuthenticatedGrantedAuthorities, 0, result, 0, result.length); return result; } /** * @see org.springframework.security.MutableGrantedAuthoritiesContainer#setGrantedAuthorities() */ public void setGrantedAuthorities(GrantedAuthority[] aJ2eeBasedGrantedAuthorities) { this.preAuthenticatedGrantedAuthorities = new GrantedAuthority[aJ2eeBasedGrantedAuthorities.length]; System.arraycopy(aJ2eeBasedGrantedAuthorities, 0, preAuthenticatedGrantedAuthorities, 0, preAuthenticatedGrantedAuthorities.length); } } ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/AbstractPreAuthenticatedProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/Abst0000644000000000000000000001667011623517156030474 0ustar package org.springframework.security.ui.preauth; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.security.AuthenticationManager; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.event.authentication.InteractiveAuthenticationSuccessEvent; import org.springframework.security.ui.AuthenticationDetailsSource; import org.springframework.security.ui.WebAuthenticationDetailsSource; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.ui.SpringSecurityFilter; import org.springframework.security.context.SecurityContextHolder; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.util.Assert; /** * Base class for processing filters that handle pre-authenticated authentication requests. Subclasses must implement * the getPreAuthenticatedPrincipal() and getPreAuthenticatedCredentials() methods. *

* By default, the filter chain will proceed when an authentication attempt fails in order to allow other * authentication mechanisms to process the request. To reject the credentials immediately, set the * continueFilterChainOnUnsuccessfulAuthentication flag to false. The exception raised by the * AuthenticationManager will the be re-thrown. Note that this will not affect cases where the principal * returned by {@link #getPreAuthenticatedPrincipal} is null, when the chain will still proceed as normal. * * * @author Luke Taylor * @author Ruud Senden * @since 2.0 */ public abstract class AbstractPreAuthenticatedProcessingFilter extends SpringSecurityFilter implements InitializingBean, ApplicationEventPublisherAware { private ApplicationEventPublisher eventPublisher = null; private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); private AuthenticationManager authenticationManager = null; private boolean continueFilterChainOnUnsuccessfulAuthentication = true; /** * Check whether all required properties have been set. */ public void afterPropertiesSet() throws Exception { Assert.notNull(authenticationManager, "An AuthenticationManager must be set"); } /** * Try to authenticate a pre-authenticated user with Spring Security if the user has not yet been authenticated. */ public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { if (logger.isDebugEnabled()) { logger.debug("Checking secure context token: " + SecurityContextHolder.getContext().getAuthentication()); } if (SecurityContextHolder.getContext().getAuthentication() == null) { doAuthenticate(request, response); } filterChain.doFilter(request, response); } /** * Do the actual authentication for a pre-authenticated user. */ private void doAuthenticate(HttpServletRequest request, HttpServletResponse response) { Authentication authResult = null; Object principal = getPreAuthenticatedPrincipal(request); Object credentials = getPreAuthenticatedCredentials(request); if (principal == null) { if (logger.isDebugEnabled()) { logger.debug("No pre-authenticated principal found in request"); } return; } if (logger.isDebugEnabled()) { logger.debug("preAuthenticatedPrincipal = " + principal + ", trying to authenticate"); } try { PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(principal, credentials); authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); authResult = authenticationManager.authenticate(authRequest); successfulAuthentication(request, response, authResult); } catch (AuthenticationException failed) { unsuccessfulAuthentication(request, response, failed); if (!continueFilterChainOnUnsuccessfulAuthentication) { throw failed; } } } /** * Puts the Authentication instance returned by the * authentication manager into the secure context. */ protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) { if (logger.isDebugEnabled()) { logger.debug("Authentication success: " + authResult); } SecurityContextHolder.getContext().setAuthentication(authResult); // Fire event if (this.eventPublisher != null) { eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass())); } } /** * Ensures the authentication object in the secure context is set to null * when authentication fails. */ protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) { SecurityContextHolder.clearContext(); if (logger.isDebugEnabled()) { logger.debug("Cleared security context due to exception", failed); } request.getSession().setAttribute(AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY, failed); } /** * @param anApplicationEventPublisher * The ApplicationEventPublisher to use */ public void setApplicationEventPublisher(ApplicationEventPublisher anApplicationEventPublisher) { this.eventPublisher = anApplicationEventPublisher; } /** * @param authenticationDetailsSource * The AuthenticationDetailsSource to use */ public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } /** * @param authenticationManager * The AuthenticationManager to use */ public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } public void setContinueFilterChainOnUnsuccessfulAuthentication(boolean shouldContinue) { continueFilterChainOnUnsuccessfulAuthentication = shouldContinue; } /** * Override to extract the principal information from the current request */ protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request); /** * Override to extract the credentials (if applicable) from the current request. Some implementations * may return a dummy value. */ protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request); } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/header/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/head0000755000000000000000000000000011623517156030470 5ustar ././@LongLink0000000000000000000000000000023200000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/header/RequestHeaderPreAuthenticatedProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/head0000644000000000000000000000604211623517156030474 0ustar package org.springframework.security.ui.preauth.header; import javax.servlet.http.HttpServletRequest; import org.springframework.security.ui.FilterChainOrder; import org.springframework.security.ui.preauth.AbstractPreAuthenticatedProcessingFilter; import org.springframework.security.ui.preauth.PreAuthenticatedCredentialsNotFoundException; import org.springframework.util.Assert; /** * A simple pre-authenticated filter which obtains the username from a request header, for use with systems such as * CA Siteminder. *

* As with most pre-authenticated scenarios, it is essential that the external authentication system is set up * correctly as this filter does no authentication whatsoever. All the protection is assumed to be provided externally * and if this filter is included inappropriately in a configuration, it would be possible to assume the * identity of a user merely by setting the correct header name. This also means it should not be used in combination * with other Spring Security authentication mechanisms such as form login, as this would imply there was a means of * bypassing the external system which would be risky. *

* The property principalRequestHeader is the name of the request header that contains the username. It * defaults to "SM_USER" for compatibility with Siteminder. * * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class RequestHeaderPreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter { private String principalRequestHeader = "SM_USER"; private String credentialsRequestHeader; /** * Read and returns the header named by principalRequestHeader from the request. * * @throws PreAuthenticatedCredentialsNotFoundException if the header is missing */ protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) { String principal = request.getHeader(principalRequestHeader); if (principal == null) { throw new PreAuthenticatedCredentialsNotFoundException(principalRequestHeader + " header not found in request."); } return principal; } /** * Credentials aren't usually applicable, but if a credentialsRequestHeader is set, this * will be read and used as the credentials value. Otherwise a dummy value will be used. */ protected Object getPreAuthenticatedCredentials(HttpServletRequest request) { if (credentialsRequestHeader != null) { String credentials = request.getHeader(credentialsRequestHeader); return credentials; } return "N/A"; } public void setPrincipalRequestHeader(String principalRequestHeader) { Assert.hasText(principalRequestHeader, "principalRequestHeader must not be empty or null"); this.principalRequestHeader = principalRequestHeader; } public void setCredentialsRequestHeader(String credentialsRequestHeader) { Assert.hasText(credentialsRequestHeader, "credentialsRequestHeader must not be empty or null"); this.credentialsRequestHeader = credentialsRequestHeader; } public int getOrder() { return FilterChainOrder.PRE_AUTH_FILTER; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/j2ee/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/j2ee0000755000000000000000000000000011623517156030414 5ustar ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/j2ee/J2eePreAuthenticatedProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/j2ee0000644000000000000000000000250211623517156030415 0ustar package org.springframework.security.ui.preauth.j2ee; import javax.servlet.http.HttpServletRequest; import org.springframework.security.ui.preauth.AbstractPreAuthenticatedProcessingFilter; /** * This AbstractPreAuthenticatedProcessingFilter implementation is based on the * J2EE container-based authentication mechanism. It will use the J2EE user * principal name as the pre-authenticated principal. * * @author Ruud Senden * @since 2.0 */ public class J2eePreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter { /** * Return the J2EE user name. */ protected Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest) { Object principal = httpRequest.getUserPrincipal() == null ? null : httpRequest.getUserPrincipal().getName(); if (logger.isDebugEnabled()) { logger.debug("PreAuthenticated J2EE principal: " + principal); } return principal; } /** * For J2EE container-based authentication there is no generic way to * retrieve the credentials, as such this method returns a fixed dummy * value. */ protected Object getPreAuthenticatedCredentials(HttpServletRequest httpRequest) { return "N/A"; } public int getOrder() { return 0; } } ././@LongLink0000000000000000000000000000024200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/j2ee0000644000000000000000000000401711623517156030420 0ustar package org.springframework.security.ui.preauth.j2ee; import org.springframework.security.ui.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails; import org.springframework.security.authoritymapping.SimpleAttributes2GrantedAuthoritiesMapper; import java.util.ArrayList; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.InitializingBean; /** * Implementation of AuthenticationDetailsSource which converts the user's J2EE roles (as obtained by calling * {@link HttpServletRequest#isUserInRole(String)}) into GrantedAuthoritys and stores these in the authentication * details object (. * * @author Ruud Senden * @since 2.0 */ public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource extends AbstractPreAuthenticatedAuthenticationDetailsSource { /** * Public constructor which overrides the default AuthenticationDetails * class to be used. */ public J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource() { super.setClazz(PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.class); j2eeUserRoles2GrantedAuthoritiesMapper = new SimpleAttributes2GrantedAuthoritiesMapper(); } /** * Obtains the list of user roles based on the current user's J2EE roles. * * @param request The request against which isUserInRole will be called for each role name * returned by the MappableAttributesRetriever. * @return GrantedAuthority[] mapped from the user's J2EE roles. */ protected String[] getUserRoles(Object context, String[] mappableRoles) { ArrayList j2eeUserRolesList = new ArrayList(); for (int i = 0; i < mappableRoles.length; i++) { if (((HttpServletRequest)context).isUserInRole(mappableRoles[i])) { j2eeUserRolesList.add(mappableRoles[i]); } } return (String[]) j2eeUserRolesList.toArray(new String[j2eeUserRolesList.size()]); } } ././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/j2ee/WebXmlMappableAttributesRetriever.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/j2ee0000644000000000000000000000371711623517156030426 0ustar package org.springframework.security.ui.preauth.j2ee; import java.io.InputStream; import org.springframework.security.authoritymapping.XmlMappableAttributesRetriever; /** *

* This MappableAttributesRetriever implementation reads the list of defined J2EE * roles from a web.xml file. It's functionality is based on the * XmlMappableAttributesRetriever base class. *

* Example on how to configure this MappableAttributesRetriever in the Spring * configuration file: * *

 *
 *
 * <bean id="j2eeMappableRolesRetriever" class="org.springframework.security.ui.preauth.j2ee.WebXmlMappableAttributesRetriever">
 *     <property name="webXmlInputStream"><bean factory-bean="webXmlResource" factory-method="getInputStream"/></property>
 * </bean>
 * <bean id="webXmlResource" class="org.springframework.web.context.support.ServletContextResource">
 *     <constructor-arg><ref local="servletContext"/></constructor-arg>
 *     <constructor-arg><value>/WEB-INF/web.xml</value></constructor-arg>
 * </bean>
 * <bean id="servletContext" class="org.springframework.web.context.support.ServletContextFactoryBean"/>
 *
 * 
* * @author Ruud Senden * @since 2.0 */ public class WebXmlMappableAttributesRetriever extends XmlMappableAttributesRetriever { private static final String XPATH_EXPR = "/web-app/security-role/role-name/text()"; /** * Constructor setting the XPath expression to use */ public WebXmlMappableAttributesRetriever() { super.setXpathExpression(XPATH_EXPR); } /** * @param anInputStream * The InputStream to read the XML data from */ public void setWebXmlInputStream(InputStream anInputStream) { super.setXmlInputStream(anInputStream); } } ././@LongLink0000000000000000000000000000023600000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/j2ee/AbstractPreAuthenticatedAuthenticationDetailsSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/j2ee0000644000000000000000000000750611623517156030426 0ustar package org.springframework.security.ui.preauth.j2ee; import java.util.Arrays; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.security.GrantedAuthority; import org.springframework.security.MutableGrantedAuthoritiesContainer; import org.springframework.security.authoritymapping.Attributes2GrantedAuthoritiesMapper; import org.springframework.security.authoritymapping.MappableAttributesRetriever; import org.springframework.security.authoritymapping.SimpleAttributes2GrantedAuthoritiesMapper; import org.springframework.security.ui.AuthenticationDetailsSourceImpl; import org.springframework.util.Assert; /** * Base implementation for classes scenarios where the authentication details object is used * to store a list of authorities obtained from the context object (such as an HttpServletRequest) * passed to {@link #buildDetails(Object)}. *

* * * @author Luke Taylor * @since 2.0 */ public abstract class AbstractPreAuthenticatedAuthenticationDetailsSource extends AuthenticationDetailsSourceImpl { protected final Log logger = LogFactory.getLog(getClass()); protected String[] j2eeMappableRoles; protected Attributes2GrantedAuthoritiesMapper j2eeUserRoles2GrantedAuthoritiesMapper = new SimpleAttributes2GrantedAuthoritiesMapper(); public AbstractPreAuthenticatedAuthenticationDetailsSource() { } /** * Check that all required properties have been set. */ public void afterPropertiesSet() throws Exception { Assert.notNull(j2eeMappableRoles, "No mappable roles available"); Assert.notNull(j2eeUserRoles2GrantedAuthoritiesMapper, "Roles to granted authorities mapper not set"); } /** * Build the authentication details object. If the specified authentication * details class implements {@link MutableGrantedAuthoritiesContainer}, a * list of pre-authenticated Granted Authorities will be set based on the * roles for the current user. * * @see org.springframework.security.ui.AuthenticationDetailsSource#buildDetails(Object) */ public Object buildDetails(Object context) { Object result = super.buildDetails(context); if (result instanceof MutableGrantedAuthoritiesContainer) { String[] j2eeUserRoles = getUserRoles(context, j2eeMappableRoles); GrantedAuthority[] userGas = j2eeUserRoles2GrantedAuthoritiesMapper.getGrantedAuthorities(j2eeUserRoles); if (logger.isDebugEnabled()) { logger.debug("J2EE user roles [" + Arrays.asList(j2eeUserRoles) + "] mapped to Granted Authorities: [" + Arrays.asList(userGas) + "]"); } ((MutableGrantedAuthoritiesContainer) result).setGrantedAuthorities(userGas); } return result; } /** * Allows the roles of the current user to be determined from the context object * * @param context the context object (an HttpRequest, PortletRequest etc) * @param mappableRoles the possible roles as determined by the MappableAttributesRetriever * @return the subset of mappable roles which the current user has. */ protected abstract String[] getUserRoles(Object context, String[] mappableRoles); /** * @param aJ2eeMappableRolesRetriever * The MappableAttributesRetriever to use */ public void setMappableRolesRetriever(MappableAttributesRetriever aJ2eeMappableRolesRetriever) { this.j2eeMappableRoles = aJ2eeMappableRolesRetriever.getMappableAttributes(); } /** * @param mapper * The Attributes2GrantedAuthoritiesMapper to use */ public void setUserRoles2GrantedAuthoritiesMapper(Attributes2GrantedAuthoritiesMapper mapper) { j2eeUserRoles2GrantedAuthoritiesMapper = mapper; } }././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/x509/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/x5090000755000000000000000000000000011623517156030274 5ustar ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/x509/SubjectDnX509PrincipalExtractor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/x5090000644000000000000000000000661611623517156030307 0ustar package org.springframework.security.ui.preauth.x509; import org.springframework.security.BadCredentialsException; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.util.Assert; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.context.MessageSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.security.cert.X509Certificate; import java.util.regex.Pattern; import java.util.regex.Matcher; /** * Obtains the principal from a certificate using a regular expression match against the Subject (as returned by a call * to {@link X509Certificate#getSubjectDN()}). *

* The regular expression should contain a single group; for example the default expression "CN=(.?)," matches the * common name field. So "CN=Jimi Hendrix, OU=..." will give a user name of "Jimi Hendrix". *

* The matches are case insensitive. So "emailAddress=(.?)," will match "EMAILADDRESS=jimi@hendrix.org, CN=..." giving a * user name "jimi@hendrix.org" * * @author Luke Taylor * @version $Id$ */ public class SubjectDnX509PrincipalExtractor implements X509PrincipalExtractor { //~ Instance fields ================================================================================================ protected final Log logger = LogFactory.getLog(getClass()); protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private Pattern subjectDnPattern; public SubjectDnX509PrincipalExtractor() { setSubjectDnRegex("CN=(.*?),"); } public Object extractPrincipal(X509Certificate clientCert) { //String subjectDN = clientCert.getSubjectX500Principal().getName(); String subjectDN = clientCert.getSubjectDN().getName(); logger.debug("Subject DN is '" + subjectDN + "'"); Matcher matcher = subjectDnPattern.matcher(subjectDN); if (!matcher.find()) { throw new BadCredentialsException(messages.getMessage("DaoX509AuthoritiesPopulator.noMatching", new Object[] {subjectDN}, "No matching pattern was found in subject DN: {0}")); } if (matcher.groupCount() != 1) { throw new IllegalArgumentException("Regular expression must contain a single group "); } String username = matcher.group(1); logger.debug("Extracted Principal name is '" + username + "'"); return username; } /** * Sets the regular expression which will by used to extract the user name from the certificate's Subject * DN. *

* It should contain a single group; for example the default expression "CN=(.?)," matches the common * name field. So "CN=Jimi Hendrix, OU=..." will give a user name of "Jimi Hendrix". *

* The matches are case insensitive. So "emailAddress=(.?)," will match "EMAILADDRESS=jimi@hendrix.org, * CN=..." giving a user name "jimi@hendrix.org" * * @param subjectDnRegex the regular expression to find in the subject */ public void setSubjectDnRegex(String subjectDnRegex) { Assert.hasText(subjectDnRegex, "Regular expression may not be null or empty"); subjectDnPattern = Pattern.compile(subjectDnRegex, Pattern.CASE_INSENSITIVE); } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/x509/X509PrincipalExtractor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/x5090000644000000000000000000000064011623517156030276 0ustar package org.springframework.security.ui.preauth.x509; import java.security.cert.X509Certificate; /** * Obtains the principal from an X509Certificate for use within the framework. * * @author Luke Taylor * @version $Id$ */ public interface X509PrincipalExtractor { /** * Returns the principal (usually a String) for the given certificate. */ Object extractPrincipal(X509Certificate cert); } ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/x509/X509PreAuthenticatedProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/x5090000644000000000000000000000333511623517156030302 0ustar package org.springframework.security.ui.preauth.x509; import org.springframework.security.ui.preauth.AbstractPreAuthenticatedProcessingFilter; import org.springframework.security.ui.FilterChainOrder; import javax.servlet.http.HttpServletRequest; import java.security.cert.X509Certificate; /** * @author Luke Taylor * @version $Id$ */ public class X509PreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter { private X509PrincipalExtractor principalExtractor = new SubjectDnX509PrincipalExtractor(); protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) { X509Certificate cert = extractClientCertificate(request); if (cert == null) { return null; } return principalExtractor.extractPrincipal(cert); } protected Object getPreAuthenticatedCredentials(HttpServletRequest request) { return extractClientCertificate(request); } private X509Certificate extractClientCertificate(HttpServletRequest request) { X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); if (certs != null && certs.length > 0) { if (logger.isDebugEnabled()) { logger.debug("X.509 client authentication certificate:" + certs[0]); } return certs[0]; } if (logger.isDebugEnabled()) { logger.debug("No client certificate found in request."); } return null; } public void setPrincipalExtractor(X509PrincipalExtractor principalExtractor) { this.principalExtractor = principalExtractor; } public int getOrder() { return FilterChainOrder.X509_FILTER; } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/PreAuthenticatedCredentialsNotFoundException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/PreA0000644000000000000000000000044411623517156030422 0ustar package org.springframework.security.ui.preauth; import org.springframework.security.AuthenticationException; public class PreAuthenticatedCredentialsNotFoundException extends AuthenticationException { public PreAuthenticatedCredentialsNotFoundException(String msg) { super(msg); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/websphere/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/webs0000755000000000000000000000000011623517156030527 5ustar ././@LongLink0000000000000000000000000000024700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/websphere/WebSpherePreAuthenticatedWebAuthenticationDetailsSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/webs0000644000000000000000000000202211623517156030525 0ustar package org.springframework.security.ui.preauth.websphere; import org.springframework.security.ui.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails; /** * This AuthenticationDetailsSource implementation, when configured with a MutableGrantedAuthoritiesContainer, * will set the pre-authenticated granted authorities based on the WebSphere groups for the current WebSphere * user, mapped using the configured Attributes2GrantedAuthoritiesMapper. * * By default, this class is configured to build instances of the * PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails class. * * @author Ruud Senden */ public class WebSpherePreAuthenticatedWebAuthenticationDetailsSource extends WebSpherePreAuthenticatedAuthenticationDetailsSource { /** * Public constructor which overrides the default AuthenticationDetails * class to be used. */ public WebSpherePreAuthenticatedWebAuthenticationDetailsSource() { super(); super.setClazz(PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.class); } } ././@LongLink0000000000000000000000000000024400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/websphere/WebSpherePreAuthenticatedAuthenticationDetailsSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/webs0000644000000000000000000000711411623517156030534 0ustar package org.springframework.security.ui.preauth.websphere; import java.util.Arrays; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.GrantedAuthority; import org.springframework.security.MutableGrantedAuthoritiesContainer; import org.springframework.security.authoritymapping.Attributes2GrantedAuthoritiesMapper; import org.springframework.security.authoritymapping.SimpleAttributes2GrantedAuthoritiesMapper; import org.springframework.security.ui.AuthenticationDetailsSourceImpl; import org.springframework.security.ui.preauth.PreAuthenticatedGrantedAuthoritiesAuthenticationDetails; import org.springframework.util.Assert; /** * This AuthenticationDetailsSource implementation, when configured with a MutableGrantedAuthoritiesContainer, * will set the pre-authenticated granted authorities based on the WebSphere groups for the current WebSphere * user, mapped using the configured Attributes2GrantedAuthoritiesMapper. * * By default, this class is configured to build instances of the * PreAuthenticatedGrantedAuthoritiesAuthenticationDetails class. * * @author Ruud Senden */ public class WebSpherePreAuthenticatedAuthenticationDetailsSource extends AuthenticationDetailsSourceImpl implements InitializingBean { private static final Log LOG = LogFactory.getLog(WebSpherePreAuthenticatedAuthenticationDetailsSource.class); private Attributes2GrantedAuthoritiesMapper webSphereGroups2GrantedAuthoritiesMapper = new SimpleAttributes2GrantedAuthoritiesMapper(); /** * Public constructor which overrides the default AuthenticationDetails * class to be used. */ public WebSpherePreAuthenticatedAuthenticationDetailsSource() { super.setClazz(PreAuthenticatedGrantedAuthoritiesAuthenticationDetails.class); } /** * Check that all required properties have been set. */ public void afterPropertiesSet() throws Exception { Assert.notNull(webSphereGroups2GrantedAuthoritiesMapper, "WebSphere groups to granted authorities mapper not set"); } /** * Build the authentication details object. If the speficied authentication * details class implements the PreAuthenticatedGrantedAuthoritiesSetter, a * list of pre-authenticated Granted Authorities will be set based on the * WebSphere groups for the current user. * * @see org.springframework.security.ui.AuthenticationDetailsSource#buildDetails(Object) */ public Object buildDetails(Object context) { Object result = super.buildDetails(context); if (result instanceof MutableGrantedAuthoritiesContainer) { ((MutableGrantedAuthoritiesContainer) result) .setGrantedAuthorities(getWebSphereGroupsBasedGrantedAuthorities()); } return result; } /** * Get a list of Granted Authorities based on the current user's WebSphere groups. * * @return GrantedAuthority[] mapped from the user's WebSphere groups. */ private GrantedAuthority[] getWebSphereGroupsBasedGrantedAuthorities() { String[] webSphereGroups = WASSecurityHelper.getGroupsForCurrentUser(); GrantedAuthority[] userGas = webSphereGroups2GrantedAuthoritiesMapper.getGrantedAuthorities(webSphereGroups); if (LOG.isDebugEnabled()) { LOG.debug("WebSphere groups: " + Arrays.asList(webSphereGroups) + " mapped to Granted Authorities: " + Arrays.asList(userGas)); } return userGas; } /** * @param mapper * The Attributes2GrantedAuthoritiesMapper to use */ public void setWebSphereGroups2GrantedAuthoritiesMapper(Attributes2GrantedAuthoritiesMapper mapper) { webSphereGroups2GrantedAuthoritiesMapper = mapper; } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/websphere/WASSecurityHelper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/webs0000644000000000000000000002025711623517156030537 0ustar package org.springframework.security.ui.preauth.websphere; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.rmi.PortableRemoteObject; import javax.security.auth.Subject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * WebSphere Security helper class to allow retrieval of the current username and groups. *

* See Spring Security JIRA SEC-477. * * @author Ruud Senden * @author Stephane Manciot * @since 2.0 */ final class WASSecurityHelper { private static final Log logger = LogFactory.getLog(WASSecurityHelper.class); private static final String USER_REGISTRY = "UserRegistry"; private static Method getRunAsSubject = null; private static Method getGroupsForUser = null; private static Method getSecurityName = null; // SEC-803 private static Class wsCredentialClass = null; /** * Get the security name for the given subject. * * @param subject * The subject for which to retrieve the security name * @return String the security name for the given subject */ private static final String getSecurityName(final Subject subject) { if (logger.isDebugEnabled()) { logger.debug("Determining Websphere security name for subject " + subject); } String userSecurityName = null; if (subject != null) { // SEC-803 Object credential = subject.getPublicCredentials(getWSCredentialClass()).iterator().next(); if (credential != null) { userSecurityName = (String)invokeMethod(getSecurityNameMethod(),credential,null); } } if (logger.isDebugEnabled()) { logger.debug("Websphere security name is " + userSecurityName + " for subject " + subject); } return userSecurityName; } /** * Get the current RunAs subject. * * @return Subject the current RunAs subject */ private static final Subject getRunAsSubject() { logger.debug("Retrieving WebSphere RunAs subject"); // get Subject: WSSubject.getCallerSubject (); return (Subject) invokeMethod(getRunAsSubjectMethod(), null, new Object[] {}); } /** * Get the WebSphere group names for the given subject. * * @param subject * The subject for which to retrieve the WebSphere group names * @return the WebSphere group names for the given subject */ private static final String[] getWebSphereGroups(final Subject subject) { return getWebSphereGroups(getSecurityName(subject)); } /** * Get the WebSphere group names for the given security name. * * @param securityName * The securityname for which to retrieve the WebSphere group names * @return the WebSphere group names for the given security name */ private static final String[] getWebSphereGroups(final String securityName) { Context ic = null; try { // TODO: Cache UserRegistry object ic = new InitialContext(); Object objRef = ic.lookup(USER_REGISTRY); Object userReg = PortableRemoteObject.narrow(objRef, Class.forName ("com.ibm.websphere.security.UserRegistry")); if (logger.isDebugEnabled()) { logger.debug("Determining WebSphere groups for user " + securityName + " using WebSphere UserRegistry " + userReg); } final Collection groups = (Collection) invokeMethod(getGroupsForUserMethod(), userReg, new Object[]{ securityName }); if (logger.isDebugEnabled()) { logger.debug("Groups for user " + securityName + ": " + groups.toString()); } String[] result = new String[groups.size()]; return (String[]) groups.toArray(result); } catch (Exception e) { logger.error("Exception occured while looking up groups for user", e); throw new RuntimeException("Exception occured while looking up groups for user", e); } finally { try { ic.close(); } catch (NamingException e) { logger.debug("Exception occured while closing context", e); } } } /** * @return */ public static final String[] getGroupsForCurrentUser() { return getWebSphereGroups(getRunAsSubject()); } public static final String getCurrentUserName() { return getSecurityName(getRunAsSubject()); } private static final Object invokeMethod(Method method, Object instance, Object[] args) { try { return method.invoke(instance,args); } catch (IllegalArgumentException e) { logger.error("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+ Arrays.asList(args)+")",e); throw new RuntimeException("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e); } catch (IllegalAccessException e) { logger.error("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e); throw new RuntimeException("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e); } catch (InvocationTargetException e) { logger.error("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e); throw new RuntimeException("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e); } } private static final Method getMethod(String className, String methodName, String[] parameterTypeNames) { try { Class c = Class.forName(className); final int len = parameterTypeNames.length; Class[] parameterTypes = new Class[len]; for (int i = 0; i < len; i++) { parameterTypes[i] = Class.forName(parameterTypeNames[i]); } return c.getDeclaredMethod(methodName, parameterTypes); } catch (ClassNotFoundException e) { logger.error("Required class"+className+" not found"); throw new RuntimeException("Required class"+className+" not found",e); } catch (NoSuchMethodException e) { logger.error("Required method "+methodName+" with parameter types ("+ Arrays.asList(parameterTypeNames) +") not found on class "+className); throw new RuntimeException("Required class"+className+" not found",e); } } private static final Method getRunAsSubjectMethod() { if (getRunAsSubject == null) { getRunAsSubject = getMethod("com.ibm.websphere.security.auth.WSSubject", "getRunAsSubject", new String[] {}); } return getRunAsSubject; } private static final Method getGroupsForUserMethod() { if (getGroupsForUser == null) { getGroupsForUser = getMethod("com.ibm.websphere.security.UserRegistry", "getGroupsForUser", new String[] { "java.lang.String" }); } return getGroupsForUser; } private static final Method getSecurityNameMethod() { if (getSecurityName == null) { getSecurityName = getMethod("com.ibm.websphere.security.cred.WSCredential", "getSecurityName", new String[] {}); } return getSecurityName; } // SEC-803 private static final Class getWSCredentialClass() { if (wsCredentialClass == null) { wsCredentialClass = getClass("com.ibm.websphere.security.cred.WSCredential"); } return wsCredentialClass; } private static final Class getClass(String className) { try { return Class.forName(className); } catch (ClassNotFoundException e) { logger.error("Required class " + className + " not found"); throw new RuntimeException("Required class " + className + " not found",e); } } } ././@LongLink0000000000000000000000000000023600000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/websphere/WebSphere2SpringSecurityPropagationInterceptor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/webs0000644000000000000000000000771511623517156030543 0ustar package org.springframework.security.ui.preauth.websphere; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationManager; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.security.ui.AuthenticationDetailsSource; import org.springframework.util.Assert; /** * This method interceptor can be used in front of arbitrary Spring beans to make a Spring SecurityContext * available to the bean, based on the current WebSphere credentials. * * @author Ruud Senden * @since 1.0 */ public class WebSphere2SpringSecurityPropagationInterceptor implements MethodInterceptor { private static final Log LOG = LogFactory.getLog(WebSphere2SpringSecurityPropagationInterceptor.class); private AuthenticationManager authenticationManager = null; private AuthenticationDetailsSource authenticationDetailsSource = new WebSpherePreAuthenticatedAuthenticationDetailsSource(); /** * Authenticate with Spring Security based on WebSphere credentials before proceeding with method * invocation, and clean up the Spring Security Context after method invocation finishes. * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation) */ public Object invoke(MethodInvocation methodInvocation) throws Throwable { try { LOG.debug("Performing Spring Security authentication with WebSphere credentials"); authenticateSpringSecurityWithWASCredentials(this); LOG.debug("Proceeding with method invocation"); return methodInvocation.proceed(); } finally { LOG.debug("Clearing Spring Security security context"); clearSpringSecurityContext(); } } /** * Retrieve the current WebSphere credentials and authenticate them with Spring Security * using the pre-authenticated authentication provider. * @param aContext The context to use for building the authentication details. */ private final void authenticateSpringSecurityWithWASCredentials(Object aContext) { Assert.notNull(authenticationManager); Assert.notNull(authenticationDetailsSource); String userName = WASSecurityHelper.getCurrentUserName(); if (LOG.isDebugEnabled()) { LOG.debug("Creating authentication request for user "+userName); } PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(userName,null); authRequest.setDetails(authenticationDetailsSource.buildDetails(null)); if (LOG.isDebugEnabled()) { LOG.debug("Authentication request for user "+userName+": "+authRequest); } Authentication authResponse = authenticationManager.authenticate(authRequest); if (LOG.isDebugEnabled()) { LOG.debug("Authentication response for user "+userName+": "+authResponse); } SecurityContextHolder.getContext().setAuthentication(authResponse); } /** * Clear the Spring Security Context */ private final void clearSpringSecurityContext() { SecurityContextHolder.clearContext(); } /** * @return Returns the authenticationManager. */ public AuthenticationManager getAuthenticationManager() { return authenticationManager; } /** * @param authenticationManager The authenticationManager to set. */ public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } /** * @return Returns the authenticationDetailsSource. */ public AuthenticationDetailsSource getAuthenticationDetailsSource() { return authenticationDetailsSource; } /** * @param authenticationDetailsSource The authenticationDetailsSource to set. */ public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { this.authenticationDetailsSource = authenticationDetailsSource; } } ././@LongLink0000000000000000000000000000023100000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/websphere/WebSpherePreAuthenticatedProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/preauth/webs0000644000000000000000000000236011623517156030532 0ustar package org.springframework.security.ui.preauth.websphere; import javax.servlet.http.HttpServletRequest; import org.springframework.security.ui.preauth.AbstractPreAuthenticatedProcessingFilter; /** * This AbstractPreAuthenticatedProcessingFilter implementation is based on * WebSphere authentication. It will use the WebSphere RunAs user principal name * as the pre-authenticated principal. * * @author Ruud Senden * @since 2.0 */ public class WebSpherePreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter { /** * Return the WebSphere user name. */ protected Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest) { Object principal = WASSecurityHelper.getCurrentUserName(); if (logger.isDebugEnabled()) { logger.debug("PreAuthenticated WebSphere principal: " + principal); } return principal; } /** * For J2EE container-based authentication there is no generic way to * retrieve the credentials, as such this method returns a fixed dummy * value. */ protected Object getPreAuthenticatedCredentials(HttpServletRequest httpRequest) { return "N/A"; } public int getOrder() { return 0; } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/AuthenticationEntryPoint.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/Authenticati0000644000000000000000000000375511623517156030555 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui; import org.springframework.security.AuthenticationException; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Used by {@link ExceptionTranslationFilter} to commence an authentication * scheme. * * @author Ben Alex * @version $Id$ */ public interface AuthenticationEntryPoint { //~ Methods ======================================================================================================== /** * Commences an authentication scheme. *

* ExceptionTranslationFilter will populate the HttpSession attribute named * AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY with the requested target URL before * calling this method.

* *

Implementations should modify the headers on the ServletResponse as necessary to * commence the authentication process.

* * @param request that resulted in an AuthenticationException * @param response so that the user agent can begin authentication * @param authException that caused the invocation * */ void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) throws IOException, ServletException; } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/logout/0000755000000000000000000000000011623517156027507 5ustar ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/logout/SecurityContextLogoutHandler.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/logout/Secur0000644000000000000000000000536711623517156030526 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.logout; import org.springframework.security.Authentication; import org.springframework.security.context.SecurityContextHolder; import org.springframework.util.Assert; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Performs a logout by modifying the {@link org.springframework.security.context.SecurityContextHolder}. *

* Will also invalidate the {@link HttpSession} if {@link #isInvalidateHttpSession()} is true and the * session is not null. * * @author Ben Alex * @version $Id$ */ public class SecurityContextLogoutHandler implements LogoutHandler { private boolean invalidateHttpSession = true; //~ Methods ======================================================================================================== /** * Requires the request to be passed in. * * @param request from which to obtain a HTTP session (cannot be null) * @param response not used (can be null) * @param authentication not used (can be null) */ public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { Assert.notNull(request, "HttpServletRequest required"); if (invalidateHttpSession) { HttpSession session = request.getSession(false); if (session != null) { session.invalidate(); } } SecurityContextHolder.clearContext(); } public boolean isInvalidateHttpSession() { return invalidateHttpSession; } /** * Causes the {@link HttpSession} to be invalidated when this {@link LogoutHandler} is invoked. Defaults to true. * * @param invalidateHttpSession true if you wish the session to be invalidated (default) or false if it should * not be. */ public void setInvalidateHttpSession(boolean invalidateHttpSession) { this.invalidateHttpSession = invalidateHttpSession; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/logout/LogoutFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/logout/Logou0000644000000000000000000001521011623517156030516 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.logout; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.Authentication; import org.springframework.security.ui.SpringSecurityFilter; import org.springframework.security.ui.FilterChainOrder; import org.springframework.security.util.RedirectUtils; import org.springframework.security.util.UrlUtils; import org.springframework.security.context.SecurityContextHolder; import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** * Logs a principal out. *

* Polls a series of {@link LogoutHandler}s. The handlers should be specified in the order they are required. * Generally you will want to call logout handlers TokenBasedRememberMeServices and * SecurityContextLogoutHandler (in that order). *

*

* After logout, the URL specified by {@link #logoutSuccessUrl} will be shown. *

* * @author Ben Alex * @version $Id$ */ public class LogoutFilter extends SpringSecurityFilter { //~ Instance fields ================================================================================================ private String filterProcessesUrl = "/j_spring_security_logout"; private String logoutSuccessUrl; private LogoutHandler[] handlers; private boolean useRelativeContext; //~ Constructors =================================================================================================== public LogoutFilter(String logoutSuccessUrl, LogoutHandler[] handlers) { Assert.notEmpty(handlers, "LogoutHandlers are required"); this.logoutSuccessUrl = logoutSuccessUrl; Assert.isTrue(UrlUtils.isValidRedirectUrl(logoutSuccessUrl), logoutSuccessUrl + " isn't a valid redirect URL"); this.handlers = handlers; } //~ Methods ======================================================================================================== public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (requiresLogout(request, response)) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (logger.isDebugEnabled()) { logger.debug("Logging out user '" + auth + "' and redirecting to logout page"); } for (int i = 0; i < handlers.length; i++) { handlers[i].logout(request, response, auth); } String targetUrl = determineTargetUrl(request, response); sendRedirect(request, response, targetUrl); return; } chain.doFilter(request, response); } /** * Allow subclasses to modify when a logout should take place. * * @param request the request * @param response the response * * @return true if logout should occur, false otherwise */ protected boolean requiresLogout(HttpServletRequest request, HttpServletResponse response) { String uri = request.getRequestURI(); int pathParamIndex = uri.indexOf(';'); if (pathParamIndex > 0) { // strip everything from the first semi-colon uri = uri.substring(0, pathParamIndex); } int queryParamIndex = uri.indexOf('?'); if (queryParamIndex > 0) { // strip everything from the first question mark uri = uri.substring(0, queryParamIndex); } if ("".equals(request.getContextPath())) { return uri.endsWith(filterProcessesUrl); } return uri.endsWith(request.getContextPath() + filterProcessesUrl); } /** * Returns the target URL to redirect to after logout. *

* By default it will check for a logoutSuccessUrl parameter in * the request and use this. If that isn't present it will use the configured logoutSuccessUrl. If this * hasn't been set it will check the Referer header and use the URL from there. * */ protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) { String targetUrl = request.getParameter("logoutSuccessUrl"); if(!StringUtils.hasLength(targetUrl)) { targetUrl = getLogoutSuccessUrl(); } if (!StringUtils.hasLength(targetUrl)) { targetUrl = request.getHeader("Referer"); } if (!StringUtils.hasLength(targetUrl)) { targetUrl = "/"; } return targetUrl; } /** * Allow subclasses to modify the redirection message. * * @param request the request * @param response the response * @param url the URL to redirect to * * @throws IOException in the event of any failure */ protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException { RedirectUtils.sendRedirect(request, response, url, useRelativeContext); } public void setFilterProcessesUrl(String filterProcessesUrl) { Assert.hasText(filterProcessesUrl, "FilterProcessesUrl required"); Assert.isTrue(UrlUtils.isValidRedirectUrl(filterProcessesUrl), filterProcessesUrl + " isn't a valid redirect URL"); this.filterProcessesUrl = filterProcessesUrl; } protected String getLogoutSuccessUrl() { return logoutSuccessUrl; } protected String getFilterProcessesUrl() { return filterProcessesUrl; } public void setUseRelativeContext(boolean useRelativeContext) { this.useRelativeContext = useRelativeContext; } public int getOrder() { return FilterChainOrder.LOGOUT_FILTER; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/logout/LogoutHandler.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/logout/Logou0000644000000000000000000000277011623517156030525 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.logout; import org.springframework.security.Authentication; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Indicates a class that is able to participate in logout handling. * *

* Called by {@link LogoutFilter}. * * @author Ben Alex * @version $Id$ */ public interface LogoutHandler { //~ Methods ======================================================================================================== /** * Causes a logout to be completed. The method must complete successfully. * * @param request the HTTP request * @param response the HTTP resonse * @param authentication the current principal details */ void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication); } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/AccessDeniedHandler.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/AccessDenied0000644000000000000000000000340411623517156030434 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui; import org.springframework.security.AccessDeniedException; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Used by {@link ExceptionTranslationFilter} to handle an * AccessDeniedException. * * @author Ben Alex * @version $Id$ */ public interface AccessDeniedHandler { //~ Methods ======================================================================================================== /** * Handles an access denied failure. * * @param request that resulted in an AccessDeniedException * @param response so that the user agent can be advised of the failure * @param accessDeniedException that caused the invocation * * @throws IOException in the event of an IOException * @throws ServletException in the event of a ServletException */ void handle(ServletRequest request, ServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException; } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/AuthenticationDetails.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/Authenticati0000644000000000000000000000420011623517156030537 0ustar package org.springframework.security.ui; import java.io.Serializable; /** * A holder of the context as a string. * * @author Ruud Senden * @since 2.0 */ public class AuthenticationDetails implements Serializable { //~ Instance fields ================================================================================================ private String context; //~ Constructors =================================================================================================== /** * Constructor. * * @param context that the authentication request is initiated from */ public AuthenticationDetails(Object context) { this.context = context==null?"":context.toString(); doPopulateAdditionalInformation(context); } protected AuthenticationDetails() { throw new IllegalArgumentException("Cannot use default constructor"); } //~ Methods ======================================================================================================== /** * Provided so that subclasses can populate additional information. * * @param request that the authentication request was received from */ protected void doPopulateAdditionalInformation(Object context) {} public boolean equals(Object obj) { if (obj instanceof AuthenticationDetails) { AuthenticationDetails rhs = (AuthenticationDetails) obj; if ((context == null) && (rhs.getContext() != null)) { return false; } if ((context != null) && (rhs.getContext() == null)) { return false; } if (context != null) { if (!context.equals(rhs.getContext())) { return false; } } return true; } return false; } /** * Indicates the context. * * @return the address */ public String getContext() { return context; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString() + ": "); sb.append("Context: " + this.getContext()); return sb.toString(); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/package.html0000644000000000000000000000027311623517156030461 0ustar Authentication processing mechanisms, which respond to the submission of authentication credentials using various protocols (eg BASIC, CAS, form login etc). spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/digestauth/0000755000000000000000000000000011623517156030337 5ustar ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/digestauth/DigestProcessingFilterEntryPoint.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/digestauth/D0000644000000000000000000001220011623517156030440 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.digestauth; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.springframework.security.AuthenticationException; import org.springframework.security.ui.AuthenticationEntryPoint; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.Ordered; /** * Used by the SecurityEnforcementFilter to commence authentication via the {@link * DigestProcessingFilter}.

The nonce sent back to the user agent will be valid for the period indicated by * {@link #setNonceValiditySeconds(int)}. By default this is 300 seconds. Shorter times should be used if replay * attacks are a major concern. Larger values can be used if performance is a greater concern. This class correctly * presents the stale=true header when the nonce has expierd, so properly implemented user agents will * automatically renegotiate with a new nonce value (ie without presenting a new password dialog box to the user).

* * @author Ben Alex * @version $Id$ */ public class DigestProcessingFilterEntryPoint implements AuthenticationEntryPoint, InitializingBean, Ordered { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(DigestProcessingFilterEntryPoint.class); //~ Instance fields ================================================================================================ private String key; private String realmName; private int nonceValiditySeconds = 300; private int order = Integer.MAX_VALUE; // ~ default //~ Methods ======================================================================================================== public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } public void afterPropertiesSet() throws Exception { if ((realmName == null) || "".equals(realmName)) { throw new IllegalArgumentException("realmName must be specified"); } if ((key == null) || "".equals(key)) { throw new IllegalArgumentException("key must be specified"); } } public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; // compute a nonce (do not use remote IP address due to proxy farms) // format of nonce is: // base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) long expiryTime = System.currentTimeMillis() + (nonceValiditySeconds * 1000); String signatureValue = new String(DigestUtils.md5Hex(expiryTime + ":" + key)); String nonceValue = expiryTime + ":" + signatureValue; String nonceValueBase64 = new String(Base64.encodeBase64(nonceValue.getBytes())); // qop is quality of protection, as defined by RFC 2617. // we do not use opaque due to IE violation of RFC 2617 in not // representing opaque on subsequent requests in same session. String authenticateHeader = "Digest realm=\"" + realmName + "\", " + "qop=\"auth\", nonce=\"" + nonceValueBase64 + "\""; if (authException instanceof NonceExpiredException) { authenticateHeader = authenticateHeader + ", stale=\"true\""; } if (logger.isDebugEnabled()) { logger.debug("WWW-Authenticate header sent to user agent: " + authenticateHeader); } httpResponse.addHeader("WWW-Authenticate", authenticateHeader); httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); } public String getKey() { return key; } public int getNonceValiditySeconds() { return nonceValiditySeconds; } public String getRealmName() { return realmName; } public void setKey(String key) { this.key = key; } public void setNonceValiditySeconds(int nonceValiditySeconds) { this.nonceValiditySeconds = nonceValiditySeconds; } public void setRealmName(String realmName) { this.realmName = realmName; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/digestauth/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/digestauth/p0000644000000000000000000000012111623517156030513 0ustar Authenticates HTTP Digest authentication requests. ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/digestauth/NonceExpiredException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/digestauth/N0000644000000000000000000000303511623517156030460 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.digestauth; import org.springframework.security.AuthenticationException; /** * Thrown if an authentication request is rejected because the digest nonce has expired. * * @author Ben Alex * @version $Id$ */ public class NonceExpiredException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs a NonceExpiredException with the specified * message. * * @param msg the detail message */ public NonceExpiredException(String msg) { super(msg); } /** * Constructs a NonceExpiredException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public NonceExpiredException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/digestauth/DigestProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/digestauth/D0000644000000000000000000004774211623517156030463 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.digestauth; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationServiceException; import org.springframework.security.BadCredentialsException; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.providers.dao.UserCache; import org.springframework.security.providers.dao.cache.NullUserCache; import org.springframework.security.ui.AuthenticationDetailsSource; import org.springframework.security.ui.WebAuthenticationDetailsSource; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.security.util.StringSplitUtils; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import java.io.IOException; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Processes a HTTP request's Digest authorization headers, putting the result into the * SecurityContextHolder.

For a detailed background on what this filter is designed to process, * refer to RFC 2617 (which superseded RFC 2069, although this * filter support clients that implement either RFC 2617 or RFC 2069).

*

This filter can be used to provide Digest authentication services to both remoting protocol clients (such as * Hessian and SOAP) as well as standard user agents (such as Internet Explorer and FireFox).

*

This Digest implementation has been designed to avoid needing to store session state between invocations. * All session management information is stored in the "nonce" that is sent to the client by the {@link * DigestProcessingFilterEntryPoint}.

*

If authentication is successful, the resulting {@link org.springframework.security.Authentication Authentication} * object will be placed into the SecurityContextHolder.

*

If authentication fails, an {@link org.springframework.security.ui.AuthenticationEntryPoint AuthenticationEntryPoint} * implementation is called. This must always be {@link DigestProcessingFilterEntryPoint}, which will prompt the user * to authenticate again via Digest authentication.

*

Note there are limitations to Digest authentication, although it is a more comprehensive and secure solution * than Basic authentication. Please see RFC 2617 section 4 for a full discussion on the advantages of Digest * authentication over Basic authentication, including commentary on the limitations that it still imposes.

*/ public class DigestProcessingFilter implements Filter, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(DigestProcessingFilter.class); //~ Instance fields ================================================================================================ private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); private DigestProcessingFilterEntryPoint authenticationEntryPoint; protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private UserCache userCache = new NullUserCache(); private UserDetailsService userDetailsService; private boolean passwordAlreadyEncoded = false; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(userDetailsService, "A UserDetailsService is required"); Assert.notNull(authenticationEntryPoint, "A DigestProcessingFilterEntryPoint is required"); } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { throw new ServletException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("Can only process HttpServletResponse"); } HttpServletRequest httpRequest = (HttpServletRequest) request; String header = httpRequest.getHeader("Authorization"); if (logger.isDebugEnabled()) { logger.debug("Authorization header received from user agent: " + header); } if ((header != null) && header.startsWith("Digest ")) { String section212response = header.substring(7); String[] headerEntries = StringSplitUtils.splitIgnoringQuotes(section212response, ','); Map headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\""); String username = (String) headerMap.get("username"); String realm = (String) headerMap.get("realm"); String nonce = (String) headerMap.get("nonce"); String uri = (String) headerMap.get("uri"); String responseDigest = (String) headerMap.get("response"); String qop = (String) headerMap.get("qop"); // RFC 2617 extension String nc = (String) headerMap.get("nc"); // RFC 2617 extension String cnonce = (String) headerMap.get("cnonce"); // RFC 2617 extension // Check all required parameters were supplied (ie RFC 2069) if ((username == null) || (realm == null) || (nonce == null) || (uri == null) || (response == null)) { if (logger.isDebugEnabled()) { logger.debug("extracted username: '" + username + "'; realm: '" + username + "'; nonce: '" + username + "'; uri: '" + username + "'; response: '" + username + "'"); } fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.missingMandatory", new Object[]{section212response}, "Missing mandatory digest value; received header {0}"))); return; } // Check all required parameters for an "auth" qop were supplied (ie RFC 2617) if ("auth".equals(qop)) { if ((nc == null) || (cnonce == null)) { if (logger.isDebugEnabled()) { logger.debug("extracted nc: '" + nc + "'; cnonce: '" + cnonce + "'"); } fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.missingAuth", new Object[]{section212response}, "Missing mandatory digest value; received header {0}"))); return; } } // Check realm name equals what we expected if (!this.getAuthenticationEntryPoint().getRealmName().equals(realm)) { fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.incorrectRealm", new Object[]{realm, this.getAuthenticationEntryPoint().getRealmName()}, "Response realm name '{0}' does not match system realm name of '{1}'"))); return; } // Check nonce was a Base64 encoded (as sent by DigestProcessingFilterEntryPoint) if (!Base64.isArrayByteBase64(nonce.getBytes())) { fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.nonceEncoding", new Object[]{nonce}, "Nonce is not encoded in Base64; received nonce {0}"))); return; } // Decode nonce from Base64 // format of nonce is: // base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) String nonceAsPlainText = new String(Base64.decodeBase64(nonce.getBytes())); String[] nonceTokens = StringUtils.delimitedListToStringArray(nonceAsPlainText, ":"); if (nonceTokens.length != 2) { fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.nonceNotTwoTokens", new Object[]{nonceAsPlainText}, "Nonce should have yielded two tokens but was {0}"))); return; } // Extract expiry time from nonce long nonceExpiryTime; try { nonceExpiryTime = new Long(nonceTokens[0]).longValue(); } catch (NumberFormatException nfe) { fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.nonceNotNumeric", new Object[]{nonceAsPlainText}, "Nonce token should have yielded a numeric first token, but was {0}"))); return; } // Check signature of nonce matches this expiry time String expectedNonceSignature = DigestUtils.md5Hex(nonceExpiryTime + ":" + this.getAuthenticationEntryPoint().getKey()); if (!expectedNonceSignature.equals(nonceTokens[1])) { fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.nonceCompromised", new Object[]{nonceAsPlainText}, "Nonce token compromised {0}"))); return; } // Lookup password for presented username // NB: DAO-provided password MUST be clear text - not encoded/salted // (unless this instance's passwordAlreadyEncoded property is 'false') boolean loadedFromDao = false; UserDetails user = userCache.getUserFromCache(username); if (user == null) { loadedFromDao = true; try { user = userDetailsService.loadUserByUsername(username); } catch (UsernameNotFoundException notFound) { fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.usernameNotFound", new Object[]{username}, "Username {0} not found"))); return; } if (user == null) { throw new AuthenticationServiceException( "AuthenticationDao returned null, which is an interface contract violation"); } userCache.putUserInCache(user); } // Compute the expected response-digest (will be in hex form) String serverDigestMd5; // Don't catch IllegalArgumentException (already checked validity) serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username, realm, user.getPassword(), ((HttpServletRequest) request).getMethod(), uri, qop, nonce, nc, cnonce); // If digest is incorrect, try refreshing from backend and recomputing if (!serverDigestMd5.equals(responseDigest) && !loadedFromDao) { if (logger.isDebugEnabled()) { logger.debug( "Digest comparison failure; trying to refresh user from DAO in case password had changed"); } try { user = userDetailsService.loadUserByUsername(username); } catch (UsernameNotFoundException notFound) { // Would very rarely happen, as user existed earlier fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.usernameNotFound", new Object[]{username}, "Username {0} not found"))); } userCache.putUserInCache(user); // Don't catch IllegalArgumentException (already checked validity) serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username, realm, user.getPassword(), ((HttpServletRequest) request).getMethod(), uri, qop, nonce, nc, cnonce); } // If digest is still incorrect, definitely reject authentication attempt if (!serverDigestMd5.equals(responseDigest)) { if (logger.isDebugEnabled()) { logger.debug("Expected response: '" + serverDigestMd5 + "' but received: '" + responseDigest + "'; is AuthenticationDao returning clear text passwords?"); } fail(request, response, new BadCredentialsException(messages.getMessage("DigestProcessingFilter.incorrectResponse", "Incorrect response"))); return; } // To get this far, the digest must have been valid // Check the nonce has not expired // We do this last so we can direct the user agent its nonce is stale // but the request was otherwise appearing to be valid if (nonceExpiryTime < System.currentTimeMillis()) { fail(request, response, new NonceExpiredException(messages.getMessage("DigestProcessingFilter.nonceExpired", "Nonce has expired/timed out"))); return; } if (logger.isDebugEnabled()) { logger.debug("Authentication success for user: '" + username + "' with response: '" + responseDigest + "'"); } UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(user, user.getPassword()); authRequest.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request)); SecurityContextHolder.getContext().setAuthentication(authRequest); } chain.doFilter(request, response); } public static String encodePasswordInA1Format(String username, String realm, String password) { String a1 = username + ":" + realm + ":" + password; String a1Md5 = new String(DigestUtils.md5Hex(a1)); return a1Md5; } private void fail(ServletRequest request, ServletResponse response, AuthenticationException failed) throws IOException, ServletException { SecurityContextHolder.getContext().setAuthentication(null); if (logger.isDebugEnabled()) { logger.debug(failed); } authenticationEntryPoint.commence(request, response, failed); } /** * Computes the response portion of a Digest authentication header. Both the server and user * agent should compute the response independently. Provided as a static method to simplify the * coding of user agents. * * @param passwordAlreadyEncoded true if the password argument is already encoded in the correct format. False if * it is plain text. * @param username the user's login name. * @param realm the name of the realm. * @param password the user's password in plaintext or ready-encoded. * @param httpMethod the HTTP request method (GET, POST etc.) * @param uri the request URI. * @param qop the qop directive, or null if not set. * @param nonce the nonce supplied by the server * @param nc the "nonce-count" as defined in RFC 2617. * @param cnonce opaque string supplied by the client when qop is set. * @return the MD5 of the digest authentication response, encoded in hex * @throws IllegalArgumentException if the supplied qop value is unsupported. */ public static String generateDigest(boolean passwordAlreadyEncoded, String username, String realm, String password, String httpMethod, String uri, String qop, String nonce, String nc, String cnonce) throws IllegalArgumentException { String a1Md5 = null; String a2 = httpMethod + ":" + uri; String a2Md5 = new String(DigestUtils.md5Hex(a2)); if (passwordAlreadyEncoded) { a1Md5 = password; } else { a1Md5 = encodePasswordInA1Format(username, realm, password); } String digest; if (qop == null) { // as per RFC 2069 compliant clients (also reaffirmed by RFC 2617) digest = a1Md5 + ":" + nonce + ":" + a2Md5; } else if ("auth".equals(qop)) { // As per RFC 2617 compliant clients digest = a1Md5 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + a2Md5; } else { throw new IllegalArgumentException("This method does not support a qop: '" + qop + "'"); } String digestMd5 = new String(DigestUtils.md5Hex(digest)); return digestMd5; } public DigestProcessingFilterEntryPoint getAuthenticationEntryPoint() { return authenticationEntryPoint; } public UserCache getUserCache() { return userCache; } public UserDetailsService getUserDetailsService() { return userDetailsService; } public void init(FilterConfig ignored) throws ServletException { } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } public void setAuthenticationEntryPoint(DigestProcessingFilterEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setPasswordAlreadyEncoded(boolean passwordAlreadyEncoded) { this.passwordAlreadyEncoded = passwordAlreadyEncoded; } public void setUserCache(UserCache userCache) { this.userCache = userCache; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/TargetUrlResolverImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/TargetUrlRes0000644000000000000000000001000611623520660030473 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import javax.servlet.http.HttpServletRequest; import org.springframework.security.Authentication; import org.springframework.security.ui.savedrequest.SavedRequest; import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** * Default implementation for {@link TargetUrlResolver} *

* Returns a target URL based from the contents of the configured targetUrlParameter if present on * the current request. Failing that, the SavedRequest in the session will be used. * * @author Martino Piccinato * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class TargetUrlResolverImpl implements TargetUrlResolver { public static String DEFAULT_TARGET_PARAMETER = "spring-security-redirect"; /* SEC-213 */ private String targetUrlParameter = DEFAULT_TARGET_PARAMETER; /** * If true, will only use SavedRequest to determine the target URL on successful * authentication if the request that caused the authentication request was a GET. * It will then return null for a POST/PUT request. * Defaults to false. */ private boolean justUseSavedRequestOnGet = false; /* (non-Javadoc) * @see org.acegisecurity.ui.TargetUrlResolver#determineTargetUrl(org.acegisecurity.ui.savedrequest.SavedRequest, javax.servlet.http.HttpServletRequest, org.acegisecurity.Authentication) */ public String determineTargetUrl(SavedRequest savedRequest, HttpServletRequest currentRequest, Authentication auth) { String targetUrl = currentRequest.getParameter(targetUrlParameter); if (StringUtils.hasText(targetUrl)) { try { return URLDecoder.decode(targetUrl, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new IllegalStateException("UTF-8 not supported. Shouldn't be possible"); } } if (savedRequest != null) { if (!justUseSavedRequestOnGet || savedRequest.getMethod().equals("GET")) { targetUrl = savedRequest.getFullRequestUrl(); } } return targetUrl; } /** * @return true if just GET request will be used * to determine target URLs, false otherwise. */ protected boolean isJustUseSavedRequestOnGet() { return justUseSavedRequestOnGet; } /** * @param justUseSavedRequestOnGet set to true if * just GET request will be used to determine target URLs, * false otherwise. */ public void setJustUseSavedRequestOnGet(boolean justUseSavedRequestOnGet) { this.justUseSavedRequestOnGet = justUseSavedRequestOnGet; } /** * Before checking the SavedRequest, the current request will be checked for this parameter * and the value used as the target URL if resent. * * @param targetUrlParameter the name of the parameter containing the encoded target URL. Defaults * to "redirect". */ public void setTargetUrlParameter(String targetUrlParameter) { Assert.hasText("targetUrlParameter cannot be null or empty"); this.targetUrlParameter = targetUrlParameter; } } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/WebAuthenticationDetailsSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/WebAuthentic0000644000000000000000000000522111623517156030503 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import javax.servlet.http.HttpServletRequest; /** * Implementation of {@link AuthenticationDetailsSource} which builds the details object from * an HttpServletRequest object. *

* By default will create an instance of WebAuthenticationDetails. Any object that accepts a * HttpServletRequest as its sole constructor can be used instead of this default. * * @author Ben Alex * @version $Id$ */ public class WebAuthenticationDetailsSource implements AuthenticationDetailsSource { //~ Instance fields ================================================================================================ private Class clazz = WebAuthenticationDetails.class; //~ Methods ======================================================================================================== /** * @param context the HttpServletRequest object. */ public Object buildDetails(Object context) { Assert.isInstanceOf(HttpServletRequest.class, context); try { Constructor constructor = clazz.getConstructor(new Class[] {HttpServletRequest.class}); return constructor.newInstance(new Object[] {context}); } catch (NoSuchMethodException ex) { ReflectionUtils.handleReflectionException(ex); } catch (InvocationTargetException ex) { ReflectionUtils.handleReflectionException(ex); } catch (InstantiationException ex) { ReflectionUtils.handleReflectionException(ex); } catch (IllegalAccessException ex) { ReflectionUtils.handleReflectionException(ex); } return null; } public void setClazz(Class clazz) { Assert.notNull(clazz, "Class required"); this.clazz = clazz; } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/WebAuthenticationDetails.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/WebAuthentic0000644000000000000000000001037611623517156030512 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui; import org.springframework.security.concurrent.SessionIdentifierAware; import java.io.Serializable; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * A holder of selected HTTP details related to a web authentication request. * * @author Ben Alex * @version $Id$ */ public class WebAuthenticationDetails implements SessionIdentifierAware, Serializable { //~ Instance fields ================================================================================================ private String remoteAddress; private String sessionId; //~ Constructors =================================================================================================== /** * Records the remote address and will also set the session Id if a session * already exists (it won't create one). * * @param request that the authentication request was received from */ public WebAuthenticationDetails(HttpServletRequest request) { this.remoteAddress = request.getRemoteAddr(); HttpSession session = request.getSession(false); this.sessionId = (session != null) ? session.getId() : null; doPopulateAdditionalInformation(request); } //~ Methods ======================================================================================================== /** * Provided so that subclasses can populate additional information. * * @param request that the authentication request was received from */ protected void doPopulateAdditionalInformation(HttpServletRequest request) {} public boolean equals(Object obj) { if (obj instanceof WebAuthenticationDetails) { WebAuthenticationDetails rhs = (WebAuthenticationDetails) obj; if ((remoteAddress == null) && (rhs.getRemoteAddress() != null)) { return false; } if ((remoteAddress != null) && (rhs.getRemoteAddress() == null)) { return false; } if (remoteAddress != null) { if (!remoteAddress.equals(rhs.getRemoteAddress())) { return false; } } if ((sessionId == null) && (rhs.getSessionId() != null)) { return false; } if ((sessionId != null) && (rhs.getSessionId() == null)) { return false; } if (sessionId != null) { if (!sessionId.equals(rhs.getSessionId())) { return false; } } return true; } return false; } /** * Indicates the TCP/IP address the authentication request was received from. * * @return the address */ public String getRemoteAddress() { return remoteAddress; } /** * Indicates the HttpSession id the authentication request was received from. * * @return the session ID */ public String getSessionId() { return sessionId; } public int hashCode() { int code = 7654; if (this.remoteAddress != null) { code = code * (this.remoteAddress.hashCode() % 7); } if (this.sessionId != null) { code = code * (this.sessionId.hashCode() % 7); } return code; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString() + ": "); sb.append("RemoteIpAddress: " + this.getRemoteAddress() + "; "); sb.append("SessionId: " + this.getSessionId()); return sb.toString(); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/x509/0000755000000000000000000000000011623517156026703 5ustar ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/x509/X509ProcessingFilterEntryPoint.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/x509/X509Pro0000644000000000000000000000560211623517156027757 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.x509; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.springframework.security.AuthenticationException; import org.springframework.security.ui.AuthenticationEntryPoint; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * In the X.509 authentication case (unlike CAS, for example) the certificate * will already have been extracted from the request and a secure context * established by the time the security-enforcement filter is invoked. *

* Therefore this class isn't actually responsible for the commencement of * authentication, as it is in the case of other providers. It will be called if * the certificate was rejected by Spring Security's X509AuthenticationProvider, resulting * in a null authentication. *

* The commence method will always return an * HttpServletResponse.SC_FORBIDDEN (403 error). * * @author Luke Taylor * @deprecated Use the preauth package instead * @version $Id$ * * @see org.springframework.security.ui.ExceptionTranslationFilter */ public class X509ProcessingFilterEntryPoint implements AuthenticationEntryPoint { // ~ Static fields/initializers // ===================================================================================== private static final Log logger = LogFactory.getLog(X509ProcessingFilterEntryPoint.class); // ~ Methods // ======================================================================================================== /** * Returns a 403 error code to the client. * * @param request DOCUMENT ME! * @param response DOCUMENT ME! * @param authException DOCUMENT ME! * * @throws IOException DOCUMENT ME! * @throws ServletException DOCUMENT ME! */ public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) throws IOException, ServletException { if (logger.isDebugEnabled()) { logger.debug("X509 entry point called. Rejecting access"); } HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied"); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/x509/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/x509/package0000644000000000000000000000030411623517156030216 0ustar This package is now deprecated and will be removed in a future version. Use the X.509 authentication support in org.springframework.security.ui.preauth.x509 instead. ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/x509/X509ProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/x509/X509Pro0000644000000000000000000002150611623517156027760 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.x509; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationManager; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.event.authentication.InteractiveAuthenticationSuccessEvent; import org.springframework.security.providers.x509.X509AuthenticationToken; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.ui.AuthenticationDetailsSource; import org.springframework.security.ui.WebAuthenticationDetailsSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.util.Assert; import java.io.IOException; import java.security.cert.X509Certificate; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.Filter; import javax.servlet.ServletRequest; import javax.servlet.ServletException; import javax.servlet.FilterChain; import javax.servlet.ServletResponse; import javax.servlet.FilterConfig; /** * Processes the X.509 certificate submitted by a client browser when HTTPS is used with client-authentication * enabled.

An {@link X509AuthenticationToken} is created with the certificate as the credentials.

*

The configured authentication manager is expected to supply a provider which can handle this token (usually * an instance of {@link org.springframework.security.providers.x509.X509AuthenticationProvider}).

*

If authentication is successful, an {@link * org.springframework.security.event.authentication.InteractiveAuthenticationSuccessEvent} will be published to the application * context. No events will be published if authentication was unsuccessful, because this would generally be recorded * via an AuthenticationManager-specific application event.

* * @author Luke Taylor * @deprecated Use X509PreAuthenticatedProcessingFilter from the preauth.x509 package instead * @version $Id$ */ public class X509ProcessingFilter implements Filter, InitializingBean, ApplicationEventPublisherAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(X509ProcessingFilter.class); //~ Instance fields ================================================================================================ private ApplicationEventPublisher eventPublisher; private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); private AuthenticationManager authenticationManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(authenticationManager, "An AuthenticationManager must be set"); } public void destroy() {} /** * This method first checks for an existing, non-null authentication in the secure context. If one is found * it does nothing.

If no authentication object exists, it attempts to obtain the client authentication * certificate from the request. If there is no certificate present then authentication is skipped. Otherwise a * new authentication request containing the certificate will be passed to the configured {@link * AuthenticationManager}.

*

If authentication is successful the returned token will be stored in the secure context. Otherwise * it will be set to null. In either case, the request proceeds through the filter chain.

* * @param request DOCUMENT ME! * @param response DOCUMENT ME! * @param filterChain DOCUMENT ME! * * @throws IOException DOCUMENT ME! * @throws javax.servlet.ServletException DOCUMENT ME! */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { throw new ServletException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("Can only process HttpServletResponse"); } HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; if (logger.isDebugEnabled()) { logger.debug("Checking secure context token: " + SecurityContextHolder.getContext().getAuthentication()); } if (SecurityContextHolder.getContext().getAuthentication() == null) { Authentication authResult = null; X509Certificate clientCertificate = extractClientCertificate(httpRequest); try { X509AuthenticationToken authRequest = new X509AuthenticationToken(clientCertificate); authRequest.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request)); authResult = authenticationManager.authenticate(authRequest); successfulAuthentication(httpRequest, httpResponse, authResult); } catch (AuthenticationException failed) { unsuccessfulAuthentication(httpRequest, httpResponse, failed); } } filterChain.doFilter(request, response); } private X509Certificate extractClientCertificate(HttpServletRequest request) { X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); if ((certs != null) && (certs.length > 0)) { return certs[0]; } if (logger.isDebugEnabled()) { logger.debug("No client certificate found in request."); } return null; } public void init(FilterConfig ignored) throws ServletException {} public void setApplicationEventPublisher(ApplicationEventPublisher context) { this.eventPublisher = context; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } /** * Puts the Authentication instance returned by the authentication manager into the secure * context. * * @param request DOCUMENT ME! * @param response DOCUMENT ME! * @param authResult DOCUMENT ME! * * @throws IOException DOCUMENT ME! */ protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException { if (logger.isDebugEnabled()) { logger.debug("Authentication success: " + authResult); } SecurityContextHolder.getContext().setAuthentication(authResult); // Fire event if (this.eventPublisher != null) { eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass())); } } /** * Ensures the authentication object in the secure context is set to null when authentication fails. * * @param request DOCUMENT ME! * @param response DOCUMENT ME! * @param failed DOCUMENT ME! */ protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) { SecurityContextHolder.getContext().setAuthentication(null); if (logger.isDebugEnabled()) { logger.debug("Updated SecurityContextHolder to contain null Authentication"); } request.getSession().setAttribute(AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY, failed); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/webapp/0000755000000000000000000000000011623517156027454 5ustar ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/webapp/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/webapp/packa0000644000000000000000000000013411623517156030454 0ustar Authenticates users via HTTP properties, headers and session. ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/webapp/AuthenticationProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/webapp/Authe0000644000000000000000000001467111623517156030456 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.webapp; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.ui.FilterChainOrder; import org.springframework.security.util.TextUtils; import org.springframework.util.Assert; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * Processes an authentication form. *

Login forms must present two parameters to this filter: a username and * password. The default parameter names to use are contained in the * static fields {@link #SPRING_SECURITY_FORM_USERNAME_KEY} and {@link #SPRING_SECURITY_FORM_PASSWORD_KEY}. * The parameter names can also be changed by setting the usernameParameter and passwordParameter * properties. * * @author Ben Alex * @author Colin Sampaleanu * @version $Id$ */ public class AuthenticationProcessingFilter extends AbstractProcessingFilter { //~ Static fields/initializers ===================================================================================== public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username"; public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password"; public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME"; private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY; private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY; //~ Methods ======================================================================================================== public Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException { String username = obtainUsername(request); String password = obtainPassword(request); if (username == null) { username = ""; } if (password == null) { password = ""; } username = username.trim(); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); // Place the last username attempted into HttpSession for views HttpSession session = request.getSession(false); if (session != null || getAllowSessionCreation()) { request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, TextUtils.escapeEntities(username)); } // Allow subclasses to set the "details" property setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } /** * This filter by default responds to /j_spring_security_check. * * @return the default */ public String getDefaultFilterProcessesUrl() { return "/j_spring_security_check"; } /** * Enables subclasses to override the composition of the password, such as by including additional values * and a separator.

This might be used for example if a postcode/zipcode was required in addition to the * password. A delimiter such as a pipe (|) should be used to separate the password and extended value(s). The * AuthenticationDao will need to generate the expected password in a corresponding manner.

* * @param request so that request attributes can be retrieved * * @return the password that will be presented in the Authentication request token to the * AuthenticationManager */ protected String obtainPassword(HttpServletRequest request) { return request.getParameter(passwordParameter); } /** * Enables subclasses to override the composition of the username, such as by including additional values * and a separator. * * @param request so that request attributes can be retrieved * * @return the username that will be presented in the Authentication request token to the * AuthenticationManager */ protected String obtainUsername(HttpServletRequest request) { return request.getParameter(usernameParameter); } /** * Provided so that subclasses may configure what is put into the authentication request's details * property. * * @param request that an authentication request is being created for * @param authRequest the authentication request object that should have its details set */ protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); } /** * Sets the parameter name which will be used to obtain the username from the login request. * * @param usernameParameter the parameter name. Defaults to "j_username". */ public void setUsernameParameter(String usernameParameter) { Assert.hasText(usernameParameter, "Username parameter must not be empty or null"); this.usernameParameter = usernameParameter; } /** * Sets the parameter name which will be used to obtain the password from the login request.. * * @param passwordParameter the parameter name. Defaults to "j_password". */ public void setPasswordParameter(String passwordParameter) { Assert.hasText(passwordParameter, "Password parameter must not be empty or null"); this.passwordParameter = passwordParameter; } public int getOrder() { return FilterChainOrder.AUTHENTICATION_PROCESSING_FILTER; } String getUsernameParameter() { return usernameParameter; } String getPasswordParameter() { return passwordParameter; } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/webapp/DefaultLoginPageGeneratingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/webapp/Defau0000644000000000000000000001657611623517156030442 0ustar package org.springframework.security.ui.webapp; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.beans.BeanWrapperImpl; import org.springframework.security.AuthenticationException; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.ui.FilterChainOrder; import org.springframework.security.ui.SpringSecurityFilter; import org.springframework.security.ui.rememberme.AbstractRememberMeServices; /** * For internal use with namespace configuration in the case where a user doesn't configure a login page. * The configuration code will insert this filter in the chain instead. * * Will only work if a redirect is used to the login page. * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class DefaultLoginPageGeneratingFilter extends SpringSecurityFilter { public static final String DEFAULT_LOGIN_PAGE_URL = "/spring_security_login"; public static final String ERROR_PARAMETER_NAME = "login_error"; boolean formLoginEnabled; boolean openIdEnabled; private String authenticationUrl; private String usernameParameter; private String passwordParameter; private String rememberMeParameter; private String openIDauthenticationUrl; private String openIDusernameParameter; private String openIDrememberMeParameter; public DefaultLoginPageGeneratingFilter(AbstractProcessingFilter filter) { if (filter instanceof AuthenticationProcessingFilter) { init((AuthenticationProcessingFilter)filter, null); } else { init(null, filter); } } public DefaultLoginPageGeneratingFilter(AuthenticationProcessingFilter authFilter, AbstractProcessingFilter openIDFilter) { init(authFilter, openIDFilter); } private void init(AuthenticationProcessingFilter authFilter, AbstractProcessingFilter openIDFilter) { if (authFilter != null) { formLoginEnabled = true; authenticationUrl = authFilter.getDefaultFilterProcessesUrl(); usernameParameter = authFilter.getUsernameParameter(); passwordParameter = authFilter.getPasswordParameter(); if (authFilter.getRememberMeServices() instanceof AbstractRememberMeServices) { rememberMeParameter = ((AbstractRememberMeServices)authFilter.getRememberMeServices()).getParameter(); } } if (openIDFilter != null) { openIdEnabled = true; openIDauthenticationUrl = openIDFilter.getDefaultFilterProcessesUrl(); openIDusernameParameter = (String) (new BeanWrapperImpl(openIDFilter)).getPropertyValue("claimedIdentityFieldName"); if (openIDFilter.getRememberMeServices() instanceof AbstractRememberMeServices) { openIDrememberMeParameter = ((AbstractRememberMeServices)openIDFilter.getRememberMeServices()).getParameter(); } } } protected void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (isLoginUrlRequest(request)) { String loginPageHtml = generateLoginPageHtml(request); response.setContentType("text/html;charset=UTF-8"); response.setContentLength(loginPageHtml.length()); response.getOutputStream().print(loginPageHtml); return; } chain.doFilter(request, response); } private String generateLoginPageHtml(HttpServletRequest request) { boolean loginError = request.getParameter(ERROR_PARAMETER_NAME) != null; String errorMsg = "none"; String lastUser = ""; if (loginError) { HttpSession session = request.getSession(false); if(session != null) { lastUser = (String) session.getAttribute(AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY); AuthenticationException ex = (AuthenticationException) session.getAttribute(AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY); errorMsg = ex != null ? ex.getMessage() : "none"; if (lastUser == null) { lastUser = ""; } } } StringBuffer sb = new StringBuffer(); sb.append("Login Page"); if (formLoginEnabled) { sb.append("\n"); } if (loginError) { sb.append("

Your login attempt was not successful, try again.

Reason: "); sb.append(errorMsg); sb.append("

"); } if (formLoginEnabled) { sb.append("

Login with Username and Password

"); sb.append("
\n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); if (rememberMeParameter != null) { sb.append(" \n"); } sb.append(" \n"); sb.append(" \n"); sb.append("
User:
Password:
Remember me on this computer.
\n"); sb.append("
"); } if(openIdEnabled) { sb.append("

Login with OpenID Identity

"); sb.append("
\n"); sb.append(" \n"); sb.append(" \n"); if (rememberMeParameter != null) { sb.append(" \n"); } sb.append(" \n"); sb.append(" \n"); sb.append("
Identity:
Remember me on this computer.
\n"); sb.append("
"); } sb.append(""); return sb.toString(); } public int getOrder() { return FilterChainOrder.LOGIN_PAGE_FILTER; } private boolean isLoginUrlRequest(HttpServletRequest request) { String uri = request.getRequestURI(); int pathParamIndex = uri.indexOf(';'); if (pathParamIndex > 0) { // strip everything after the first semi-colon uri = uri.substring(0, pathParamIndex); } if ("".equals(request.getContextPath())) { return uri.endsWith(DEFAULT_LOGIN_PAGE_URL); } return uri.endsWith(request.getContextPath() + DEFAULT_LOGIN_PAGE_URL); } } ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/webapp/AuthenticationProcessingFilterEntryPoint.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/webapp/Authe0000644000000000000000000002246111623517156030452 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.webapp; import org.springframework.security.AuthenticationException; import org.springframework.security.ui.AuthenticationEntryPoint; import org.springframework.security.util.PortMapper; import org.springframework.security.util.PortMapperImpl; import org.springframework.security.util.PortResolver; import org.springframework.security.util.PortResolverImpl; import org.springframework.security.util.RedirectUrlBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** *

* Used by the SecurityEnforcementFilter to commence * authentication via the {@link AuthenticationProcessingFilter}. This object * holds the location of the login form, relative to the web app context path, * and is used to commence a redirect to that form. *

* By setting the forceHttps property to true, you may configure the * class to force the protocol used for the login form to be HTTPS, * even if the original intercepted request for a resource used the * HTTP protocol. When this happens, after a successful login * (via HTTPS), the original resource will still be accessed as HTTP, via the * original request URL. For the forced HTTPS feature to work, the {@link * PortMapper} is consulted to determine the HTTP:HTTPS pairs. * * @author Ben Alex * @author colin sampaleanu * @author Omri Spector * @version $Id$ */ public class AuthenticationProcessingFilterEntryPoint implements AuthenticationEntryPoint, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AuthenticationProcessingFilterEntryPoint.class); //~ Instance fields ================================================================================================ private PortMapper portMapper = new PortMapperImpl(); private PortResolver portResolver = new PortResolverImpl(); private String loginFormUrl; private boolean forceHttps = false; private boolean serverSideRedirect = false; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(loginFormUrl, "loginFormUrl must be specified"); Assert.notNull(portMapper, "portMapper must be specified"); Assert.notNull(portResolver, "portResolver must be specified"); } /** * Allows subclasses to modify the login form URL that should be applicable for a given request. * * @param request the request * @param response the response * @param exception the exception * @return the URL (cannot be null or empty; defaults to {@link #getLoginFormUrl()}) */ protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) { return getLoginFormUrl(); } /** * Performs the redirect (or forward) to the login form URL. */ public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; String redirectUrl = null; if (serverSideRedirect) { if (forceHttps && "http".equals(request.getScheme())) { redirectUrl = buildHttpsRedirectUrlForRequest(httpRequest); } if (redirectUrl == null) { String loginForm = determineUrlToUseForThisRequest(httpRequest, httpResponse, authException); if (logger.isDebugEnabled()) { logger.debug("Server side forward to: " + loginForm); } RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(loginForm); dispatcher.forward(request, response); return; } } else { // redirect to login page. Use https if forceHttps true redirectUrl = buildRedirectUrlToLoginPage(httpRequest, httpResponse, authException); } httpResponse.sendRedirect(httpResponse.encodeRedirectURL(redirectUrl)); } protected String buildRedirectUrlToLoginPage(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) { String loginForm = determineUrlToUseForThisRequest(request, response, authException); int serverPort = portResolver.getServerPort(request); String scheme = request.getScheme(); RedirectUrlBuilder urlBuilder = new RedirectUrlBuilder(); urlBuilder.setScheme(scheme); urlBuilder.setServerName(request.getServerName()); urlBuilder.setPort(serverPort); urlBuilder.setContextPath(request.getContextPath()); urlBuilder.setPathInfo(loginForm); if (forceHttps && "http".equals(scheme)) { Integer httpsPort = portMapper.lookupHttpsPort(new Integer(serverPort)); if (httpsPort != null) { // Overwrite scheme and port in the redirect URL urlBuilder.setScheme("https"); urlBuilder.setPort(httpsPort.intValue()); } else { logger.warn("Unable to redirect to HTTPS as no port mapping found for HTTP port " + serverPort); } } return urlBuilder.getUrl(); } /** * Builds a URL to redirect the supplied request to HTTPS. */ protected String buildHttpsRedirectUrlForRequest(HttpServletRequest request) throws IOException, ServletException { int serverPort = portResolver.getServerPort(request); Integer httpsPort = portMapper.lookupHttpsPort(new Integer(serverPort)); if (httpsPort != null) { RedirectUrlBuilder urlBuilder = new RedirectUrlBuilder(); urlBuilder.setScheme("https"); urlBuilder.setServerName(request.getServerName()); urlBuilder.setPort(httpsPort.intValue()); urlBuilder.setContextPath(request.getContextPath()); urlBuilder.setServletPath(request.getServletPath()); urlBuilder.setPathInfo(request.getPathInfo()); urlBuilder.setQuery(request.getQueryString()); return urlBuilder.getUrl(); } // Fall through to server-side forward with warning message logger.warn("Unable to redirect to HTTPS as no port mapping found for HTTP port " + serverPort); return null; } /** * Set to true to force login form access to be via https. If this value is true (the default is false), * and the incoming request for the protected resource which triggered the interceptor was not already * https, then the client will first be redirected to an https URL, even if serverSideRedirect * is set to true. */ public void setForceHttps(boolean forceHttps) { this.forceHttps = forceHttps; } protected boolean isForceHttps() { return forceHttps; } /** * The URL where the AuthenticationProcessingFilter login * page can be found. Should be relative to the web-app context path, and * include a leading / */ public void setLoginFormUrl(String loginFormUrl) { this.loginFormUrl = loginFormUrl; } public String getLoginFormUrl() { return loginFormUrl; } public void setPortMapper(PortMapper portMapper) { this.portMapper = portMapper; } protected PortMapper getPortMapper() { return portMapper; } public void setPortResolver(PortResolver portResolver) { this.portResolver = portResolver; } protected PortResolver getPortResolver() { return portResolver; } /** * Tells if we are to do a server side include of the loginFormUrl instead of a 302 redirect. * * @param serverSideRedirect */ public void setServerSideRedirect(boolean serverSideRedirect) { this.serverSideRedirect = serverSideRedirect; } protected boolean isServerSideRedirect() { return serverSideRedirect; } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/TargetUrlResolver.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/TargetUrlRes0000644000000000000000000000261711623517156030512 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui; import javax.servlet.http.HttpServletRequest; import org.springframework.security.Authentication; import org.springframework.security.ui.savedrequest.SavedRequest; /** * Used by {@link AbstractProcessingFilter} to determine target URL in case of * successful authentication. * * @author Martino Piccinato * @version $Id$ * @since 2.0 * */ public interface TargetUrlResolver { /** * @param savedRequest The request that initiated the authentication process * @param currentRequest the current request * @param auth The authentication token generated after successful authentication * @return The URL to be used */ public String determineTargetUrl(SavedRequest savedRequest, HttpServletRequest currentRequest, Authentication auth); } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/FilterChainOrder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/FilterChainO0000644000000000000000000001100011623517156030420 0ustar package org.springframework.security.ui; import org.springframework.util.Assert; import java.util.Map; import java.util.LinkedHashMap; /** * Stores the default order numbers of all Spring Security filters for use in configuration. * * @author Luke Taylor * @version $Id$ */ public abstract class FilterChainOrder { /** * The first position at which a Spring Security filter will be found. Any filter with an order less than this will * be guaranteed to be placed before the Spring Security filters in the stack. */ public static final int FILTER_CHAIN_FIRST = 0; private static final int INTERVAL = 100; private static int i = 1; public static final int CHANNEL_FILTER = FILTER_CHAIN_FIRST; public static final int CONCURRENT_SESSION_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int HTTP_SESSION_CONTEXT_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int LOGOUT_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int X509_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int PRE_AUTH_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int CAS_PROCESSING_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int AUTHENTICATION_PROCESSING_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int OPENID_PROCESSING_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int LOGIN_PAGE_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int BASIC_PROCESSING_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int SERVLET_API_SUPPORT_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int REMEMBER_ME_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int ANONYMOUS_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int EXCEPTION_TRANSLATION_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int NTLM_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int SESSION_FIXATION_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int FILTER_SECURITY_INTERCEPTOR = FILTER_CHAIN_FIRST + INTERVAL * i++; public static final int SWITCH_USER_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++; private static final Map filterNameToOrder = new LinkedHashMap(); static { filterNameToOrder.put("FIRST", new Integer(Integer.MIN_VALUE)); filterNameToOrder.put("CHANNEL_FILTER", new Integer(CHANNEL_FILTER)); filterNameToOrder.put("CONCURRENT_SESSION_FILTER", new Integer(CONCURRENT_SESSION_FILTER)); filterNameToOrder.put("LOGOUT_FILTER", new Integer(LOGOUT_FILTER)); filterNameToOrder.put("X509_FILTER", new Integer(X509_FILTER)); filterNameToOrder.put("PRE_AUTH_FILTER", new Integer(PRE_AUTH_FILTER)); filterNameToOrder.put("CAS_PROCESSING_FILTER", new Integer(CAS_PROCESSING_FILTER)); filterNameToOrder.put("AUTHENTICATION_PROCESSING_FILTER", new Integer(AUTHENTICATION_PROCESSING_FILTER)); filterNameToOrder.put("OPENID_PROCESSING_FILTER", new Integer(OPENID_PROCESSING_FILTER)); filterNameToOrder.put("BASIC_PROCESSING_FILTER", new Integer(BASIC_PROCESSING_FILTER)); filterNameToOrder.put("SERVLET_API_SUPPORT_FILTER", new Integer(SERVLET_API_SUPPORT_FILTER)); filterNameToOrder.put("REMEMBER_ME_FILTER", new Integer(REMEMBER_ME_FILTER)); filterNameToOrder.put("ANONYMOUS_FILTER", new Integer(ANONYMOUS_FILTER)); filterNameToOrder.put("EXCEPTION_TRANSLATION_FILTER", new Integer(EXCEPTION_TRANSLATION_FILTER)); filterNameToOrder.put("NTLM_FILTER", new Integer(NTLM_FILTER)); filterNameToOrder.put("SESSION_CONTEXT_INTEGRATION_FILTER", new Integer(HTTP_SESSION_CONTEXT_FILTER)); filterNameToOrder.put("FILTER_SECURITY_INTERCEPTOR", new Integer(FILTER_SECURITY_INTERCEPTOR)); filterNameToOrder.put("SWITCH_USER_FILTER", new Integer(SWITCH_USER_FILTER)); filterNameToOrder.put("LAST", new Integer(Integer.MAX_VALUE)); } /** Allows filters to be used by name in the XSD file without explicit reference to Java constants */ public static int getOrder(String filterName) { Integer order = (Integer) filterNameToOrder.get(filterName); Assert.notNull(order, "Unable to match filter name " + filterName); return order.intValue(); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/session/0000755000000000000000000000000011623517156027661 5ustar ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/session/HttpSessionDestroyedEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/session/Http0000644000000000000000000000214711623517156030527 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.session; import javax.servlet.http.HttpSession; /** * Published by the {@link HttpSessionEventPublisher} when a HttpSession is created in the container * * @author Ray Krueger */ public class HttpSessionDestroyedEvent extends HttpSessionApplicationEvent { //~ Constructors =================================================================================================== public HttpSessionDestroyedEvent(HttpSession o) { super(o); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/session/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/session/pack0000644000000000000000000000011011623517156030512 0ustar HttpSession events and publisher classes. ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/session/HttpSessionApplicationEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/session/Http0000644000000000000000000000314011623517156030521 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.session; import org.springframework.context.ApplicationEvent; import javax.servlet.http.HttpSession; /** * Parent class for published HttpSession events * * @author Ray Krueger */ public abstract class HttpSessionApplicationEvent extends ApplicationEvent { //~ Constructors =================================================================================================== /** * Base constructor for all subclasses must have an HttpSession * * @param httpSession The session to carry as the event source. */ public HttpSessionApplicationEvent(HttpSession httpSession) { super(httpSession); } //~ Methods ======================================================================================================== /** * Get the HttpSession that is the cause of the event * * @return HttpSession instance */ public HttpSession getSession() { return (HttpSession) getSource(); } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/session/HttpSessionCreatedEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/session/Http0000644000000000000000000000214511623517156030525 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.session; import javax.servlet.http.HttpSession; /** * Published by the {@link HttpSessionEventPublisher} when a HttpSession is destroyed by the container * * @author Ray Krueger */ public class HttpSessionCreatedEvent extends HttpSessionApplicationEvent { //~ Constructors =================================================================================================== public HttpSessionCreatedEvent(HttpSession o) { super(o); } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/session/HttpSessionEventPublisher.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/session/Http0000644000000000000000000000636711623517156030537 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.session; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import javax.servlet.ServletContext; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; /** * Declared in web.xml as *

 * <listener>
 *     <listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
 * </listener>
 * 
* * Publishes HttpSessionApplicationEvents to the Spring Root WebApplicationContext. Maps * javax.servlet.http.HttpSessionListener.sessionCreated() to {@link HttpSessionCreatedEvent}. Maps * javax.servlet.http.HttpSessionListener.sessionDestroyed() to {@link HttpSessionDestroyedEvent}. * * @author Ray Krueger */ public class HttpSessionEventPublisher implements HttpSessionListener { //~ Static fields/initializers ===================================================================================== private static final Log log = LogFactory.getLog(HttpSessionEventPublisher.class); //~ Instance fields ================================================================================================ //~ Methods ======================================================================================================== ApplicationContext getContext(ServletContext servletContext) { return WebApplicationContextUtils.getWebApplicationContext(servletContext); } /** * Handles the HttpSessionEvent by publishing a {@link HttpSessionCreatedEvent} to the application * appContext. * * @param event HttpSessionEvent passed in by the container */ public void sessionCreated(HttpSessionEvent event) { HttpSessionCreatedEvent e = new HttpSessionCreatedEvent(event.getSession()); if (log.isDebugEnabled()) { log.debug("Publishing event: " + e); } getContext(event.getSession().getServletContext()).publishEvent(e); } /** * Handles the HttpSessionEvent by publishing a {@link HttpSessionDestroyedEvent} to the application * appContext. * * @param event The HttpSessionEvent pass in by the container */ public void sessionDestroyed(HttpSessionEvent event) { HttpSessionDestroyedEvent e = new HttpSessionDestroyedEvent(event.getSession()); if (log.isDebugEnabled()) { log.debug("Publishing event: " + e); } getContext(event.getSession().getServletContext()).publishEvent(e); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/basicauth/0000755000000000000000000000000011623517156030141 5ustar ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/basicauth/BasicProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/basicauth/Ba0000644000000000000000000002630311623517156030412 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.basicauth; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.codec.binary.Base64; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationManager; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; import org.springframework.security.ui.AuthenticationDetailsSource; import org.springframework.security.ui.WebAuthenticationDetailsSource; import org.springframework.security.ui.AuthenticationEntryPoint; import org.springframework.security.ui.FilterChainOrder; import org.springframework.security.ui.SpringSecurityFilter; import org.springframework.security.ui.rememberme.NullRememberMeServices; import org.springframework.security.ui.rememberme.RememberMeServices; import org.springframework.util.Assert; /** * Processes a HTTP request's BASIC authorization headers, putting the result into the * SecurityContextHolder. * *

* For a detailed background on what this filter is designed to process, refer to * RFC 1945, Section 11.1. Any realm name presented in * the HTTP request is ignored. * *

* In summary, this filter is responsible for processing any request that has a HTTP request header of * Authorization with an authentication scheme of Basic and a Base64-encoded * username:password token. For example, to authenticate user "Aladdin" with password "open sesame" the * following header would be presented: *

 *
 * Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
 * 
* *

* This filter can be used to provide BASIC authentication services to both remoting protocol clients (such as * Hessian and SOAP) as well as standard user agents (such as Internet Explorer and Netscape). *

* If authentication is successful, the resulting {@link Authentication} object will be placed into the * SecurityContextHolder. * *

* If authentication fails and ignoreFailure is false (the default), an {@link * AuthenticationEntryPoint} implementation is called (unless the ignoreFailure property is set to * true). Usually this should be {@link BasicProcessingFilterEntryPoint}, which will prompt the user to * authenticate again via BASIC authentication. * *

* Basic authentication is an attractive protocol because it is simple and widely deployed. However, it still * transmits a password in clear text and as such is undesirable in many situations. Digest authentication is also * provided by Spring Security and should be used instead of Basic authentication wherever possible. See {@link * org.springframework.security.ui.digestauth.DigestProcessingFilter}. *

* Note that if a {@link RememberMeServices} is set, this filter will automatically send back remember-me * details to the client. Therefore, subsequent requests will not need to present a BASIC authentication header as * they will be authenticated using the remember-me mechanism. * * @author Ben Alex * @version $Id$ */ public class BasicProcessingFilter extends SpringSecurityFilter implements InitializingBean { //~ Instance fields ================================================================================================ private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); private AuthenticationEntryPoint authenticationEntryPoint; private AuthenticationManager authenticationManager; private RememberMeServices rememberMeServices = new NullRememberMeServices(); private boolean ignoreFailure = false; private String credentialsCharset = "UTF-8"; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.authenticationManager, "An AuthenticationManager is required"); if(!isIgnoreFailure()) { Assert.notNull(this.authenticationEntryPoint, "An AuthenticationEntryPoint is required"); } } public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { String header = request.getHeader("Authorization"); if (logger.isDebugEnabled()) { logger.debug("Authorization header: " + header); } if ((header != null) && header.startsWith("Basic ")) { byte[] base64Token = header.substring(6).getBytes("UTF-8"); String token = new String(Base64.decodeBase64(base64Token), getCredentialsCharset(request)); String username = ""; String password = ""; int delim = token.indexOf(":"); if (delim != -1) { username = token.substring(0, delim); password = token.substring(delim + 1); } if (authenticationIsRequired(username)) { UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); Authentication authResult; try { authResult = authenticationManager.authenticate(authRequest); } catch (AuthenticationException failed) { // Authentication failed if (logger.isDebugEnabled()) { logger.debug("Authentication request for user: " + username + " failed: " + failed.toString()); } SecurityContextHolder.getContext().setAuthentication(null); rememberMeServices.loginFail(request, response); onUnsuccessfulAuthentication(request, response, failed); if (ignoreFailure) { chain.doFilter(request, response); } else { authenticationEntryPoint.commence(request, response, failed); } return; } // Authentication success if (logger.isDebugEnabled()) { logger.debug("Authentication success: " + authResult.toString()); } SecurityContextHolder.getContext().setAuthentication(authResult); rememberMeServices.loginSuccess(request, response, authResult); onSuccessfulAuthentication(request, response, authResult); } } chain.doFilter(request, response); } private boolean authenticationIsRequired(String username) { // Only reauthenticate if username doesn't match SecurityContextHolder and user isn't authenticated // (see SEC-53) Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication(); if(existingAuth == null || !existingAuth.isAuthenticated()) { return true; } // Limit username comparison to providers which use usernames (ie UsernamePasswordAuthenticationToken) // (see SEC-348) if (existingAuth instanceof UsernamePasswordAuthenticationToken && !existingAuth.getName().equals(username)) { return true; } // Handle unusual condition where an AnonymousAuthenticationToken is already present // This shouldn't happen very often, as BasicProcessingFitler is meant to be earlier in the filter // chain than AnonymousProcessingFilter. Nevertheless, presence of both an AnonymousAuthenticationToken // together with a BASIC authentication request header should indicate reauthentication using the // BASIC protocol is desirable. This behaviour is also consistent with that provided by form and digest, // both of which force re-authentication if the respective header is detected (and in doing so replace // any existing AnonymousAuthenticationToken). See SEC-610. if (existingAuth instanceof AnonymousAuthenticationToken) { return true; } return false; } protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException { } protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { } protected AuthenticationEntryPoint getAuthenticationEntryPoint() { return authenticationEntryPoint; } public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; } protected AuthenticationManager getAuthenticationManager() { return authenticationManager; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } protected boolean isIgnoreFailure() { return ignoreFailure; } public void setIgnoreFailure(boolean ignoreFailure) { this.ignoreFailure = ignoreFailure; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } public void setRememberMeServices(RememberMeServices rememberMeServices) { Assert.notNull(rememberMeServices, "rememberMeServices cannot be null"); this.rememberMeServices = rememberMeServices; } public void setCredentialsCharset(String credentialsCharset) { Assert.hasText(credentialsCharset, "credentialsCharset cannot be null or empty"); this.credentialsCharset = credentialsCharset; } protected String getCredentialsCharset(HttpServletRequest httpRequest) { return credentialsCharset; } public int getOrder() { return FilterChainOrder.BASIC_PROCESSING_FILTER; } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/basicauth/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/basicauth/pa0000644000000000000000000000012011623517156030455 0ustar Authenticates HTTP BASIC authentication requests. ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/basicauth/BasicProcessingFilterEntryPoint.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/basicauth/Ba0000644000000000000000000000533411623517156030413 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui.basicauth; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.springframework.security.AuthenticationException; import org.springframework.security.ui.AuthenticationEntryPoint; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Used by the SecurityEnforcementFilter to commence authentication via the {@link * BasicProcessingFilter}.

Once a user agent is authenticated using BASIC authentication, logout requires that * the browser be closed or an unauthorized (401) header be sent. The simplest way of achieving the latter is to call * the {@link #commence(ServletRequest, ServletResponse, AuthenticationException)} method below. This will indicate to * the browser its credentials are no longer authorized, causing it to prompt the user to login again.

* * @author Ben Alex * @version $Id$ */ public class BasicProcessingFilterEntryPoint implements AuthenticationEntryPoint, InitializingBean { //~ Instance fields ================================================================================================ private String realmName; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasText(realmName, "realmName must be specified"); } public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.addHeader("WWW-Authenticate", "Basic realm=\"" + realmName + "\""); httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); } public String getRealmName() { return realmName; } public void setRealmName(String realmName) { this.realmName = realmName; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/ExceptionTranslationFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ui/ExceptionTra0000644000000000000000000002604211623517156030532 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ui; import org.springframework.security.AccessDeniedException; import org.springframework.security.SpringSecurityException; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationTrustResolver; import org.springframework.security.AuthenticationTrustResolverImpl; import org.springframework.security.InsufficientAuthenticationException; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.ui.savedrequest.SavedRequest; import org.springframework.security.util.PortResolver; import org.springframework.security.util.PortResolverImpl; import org.springframework.security.util.ThrowableAnalyzer; import org.springframework.security.util.ThrowableCauseExtractor; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Handles any AccessDeniedException and AuthenticationException thrown within the * filter chain. *

* This filter is necessary because it provides the bridge between Java exceptions and HTTP responses. * It is solely concerned with maintaining the user interface. This filter does not do any actual security enforcement. *

*

* If an {@link AuthenticationException} is detected, the filter will launch the authenticationEntryPoint. * This allows common handling of authentication failures originating from any subclass of * {@link org.springframework.security.intercept.AbstractSecurityInterceptor}. *

*

* If an {@link AccessDeniedException} is detected, the filter will determine whether or not the user is an anonymous * user. If they are an anonymous user, the authenticationEntryPoint will be launched. If they are not * an anonymous user, the filter will delegate to the {@link org.springframework.security.ui.AccessDeniedHandler}. * By default the filter will use {@link org.springframework.security.ui.AccessDeniedHandlerImpl}. *

*

* To use this filter, it is necessary to specify the following properties: *

*
    *
  • authenticationEntryPoint indicates the handler that * should commence the authentication process if an * AuthenticationException is detected. Note that this may also * switch the current protocol from http to https for an SSL login.
  • *
  • portResolver is used to determine the "real" port that a * request was received on.
  • *
* * @author Ben Alex * @author colin sampaleanu * @version $Id$ */ public class ExceptionTranslationFilter extends SpringSecurityFilter implements InitializingBean { //~ Instance fields ================================================================================================ private AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerImpl(); private AuthenticationEntryPoint authenticationEntryPoint; private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); private PortResolver portResolver = new PortResolverImpl(); private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer(); private boolean createSessionAllowed = true; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(authenticationEntryPoint, "authenticationEntryPoint must be specified"); Assert.notNull(portResolver, "portResolver must be specified"); Assert.notNull(authenticationTrustResolver, "authenticationTrustResolver must be specified"); Assert.notNull(throwableAnalyzer, "throwableAnalyzer must be specified"); } public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { try { chain.doFilter(request, response); if (logger.isDebugEnabled()) { logger.debug("Chain processed normally"); } } catch (IOException ex) { throw ex; } catch (Exception ex) { // Try to extract a SpringSecurityException from the stacktrace Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(ex); SpringSecurityException ase = (SpringSecurityException) this.throwableAnalyzer.getFirstThrowableOfType(SpringSecurityException.class, causeChain); if (ase != null) { handleException(request, response, chain, ase); } else { // Rethrow ServletExceptions and RuntimeExceptions as-is if (ex instanceof ServletException) { throw (ServletException) ex; } else if (ex instanceof RuntimeException) { throw (RuntimeException) ex; } // Wrap other Exceptions. These are not expected to happen throw new RuntimeException(ex); } } } public AuthenticationEntryPoint getAuthenticationEntryPoint() { return authenticationEntryPoint; } public AuthenticationTrustResolver getAuthenticationTrustResolver() { return authenticationTrustResolver; } public PortResolver getPortResolver() { return portResolver; } private void handleException(ServletRequest request, ServletResponse response, FilterChain chain, SpringSecurityException exception) throws IOException, ServletException { if (exception instanceof AuthenticationException) { if (logger.isDebugEnabled()) { logger.debug("Authentication exception occurred; redirecting to authentication entry point", exception); } sendStartAuthentication(request, response, chain, (AuthenticationException) exception); } else if (exception instanceof AccessDeniedException) { if (authenticationTrustResolver.isAnonymous(SecurityContextHolder.getContext().getAuthentication())) { if (logger.isDebugEnabled()) { logger.debug("Access is denied (user is anonymous); redirecting to authentication entry point", exception); } sendStartAuthentication(request, response, chain, new InsufficientAuthenticationException( "Full authentication is required to access this resource")); } else { if (logger.isDebugEnabled()) { logger.debug("Access is denied (user is not anonymous); delegating to AccessDeniedHandler", exception); } accessDeniedHandler.handle(request, response, (AccessDeniedException) exception); } } } /** * If true, indicates that SecurityEnforcementFilter is permitted to store the target * URL and exception information in the HttpSession (the default). * In situations where you do not wish to unnecessarily create HttpSessions - because the user agent * will know the failed URL, such as with BASIC or Digest authentication - you may wish to * set this property to false. Remember to also set the * {@link org.springframework.security.context.HttpSessionContextIntegrationFilter#allowSessionCreation} * to false if you set this property to false. * * @return true if the HttpSession will be * used to store information about the failed request, false * if the HttpSession will not be used */ public boolean isCreateSessionAllowed() { return createSessionAllowed; } protected void sendStartAuthentication(ServletRequest request, ServletResponse response, FilterChain chain, AuthenticationException reason) throws ServletException, IOException { HttpServletRequest httpRequest = (HttpServletRequest) request; SavedRequest savedRequest = new SavedRequest(httpRequest, portResolver); if (logger.isDebugEnabled()) { logger.debug("Authentication entry point being called; SavedRequest added to Session: " + savedRequest); } if (createSessionAllowed) { // Store the HTTP request itself. Used by AbstractProcessingFilter // for redirection after successful authentication (SEC-29) httpRequest.getSession().setAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY, savedRequest); } // SEC-112: Clear the SecurityContextHolder's Authentication, as the // existing Authentication is no longer considered valid SecurityContextHolder.getContext().setAuthentication(null); authenticationEntryPoint.commence(httpRequest, response, reason); } public void setAccessDeniedHandler(AccessDeniedHandler accessDeniedHandler) { Assert.notNull(accessDeniedHandler, "AccessDeniedHandler required"); this.accessDeniedHandler = accessDeniedHandler; } public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; } public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver) { this.authenticationTrustResolver = authenticationTrustResolver; } public void setCreateSessionAllowed(boolean createSessionAllowed) { this.createSessionAllowed = createSessionAllowed; } public void setPortResolver(PortResolver portResolver) { this.portResolver = portResolver; } public void setThrowableAnalyzer(ThrowableAnalyzer throwableAnalyzer) { this.throwableAnalyzer = throwableAnalyzer; } public int getOrder() { return FilterChainOrder.EXCEPTION_TRANSLATION_FILTER; } /** * Default implementation of ThrowableAnalyzer which is capable of also unwrapping * ServletExceptions. */ private static final class DefaultThrowableAnalyzer extends ThrowableAnalyzer { /** * @see org.springframework.security.util.ThrowableAnalyzer#initExtractorMap() */ protected void initExtractorMap() { super.initExtractorMap(); registerExtractor(ServletException.class, new ThrowableCauseExtractor() { public Throwable extractCause(Throwable throwable) { ThrowableAnalyzer.verifyThrowableHierarchy(throwable, ServletException.class); return ((ServletException) throwable).getRootCause(); } }); } } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_cs_CZ.propertiesspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_cs_CZ.0000644000000000000000000001267711623517156030467 0ustar AuthByAdapterProvider.incorrectKey=Pou\u017eit\u00e1 implementace AuthByAdapter neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d BasicAclEntryAfterInvocationProvider.noPermission=Autentizovan\u00fd u\u017eivatel {0} nem\u00e1 \u017d\u00c1DN\u00c1 pr\u00e1va k objektu {1} BasicAclEntryAfterInvocationProvider.insufficientPermission=Autentizovan\u00fd u\u017eivatel {0} nem\u00e1 po\u017eadovan\u00e1 opr\u00e1vn\u011bn\u00ed k objektu {1} ConcurrentSessionControllerImpl.exceededAllowed=Maxim\u00e1ln\u00ed po\u010det sou\u010dasn\u00fdch p\u0159ihl\u00e1\u0161en\u00ed {0} tohoto u\u017eivatele je p\u0159ekro\u010den. ProviderManager.providerNotFound=Nebyl nalezen \u017e\u00e1dn\u00fd AuthenticationProvider pro {0} AnonymousAuthenticationProvider.incorrectKey=Pou\u017eit\u00fd AnonymousAuthenticationToken neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d CasAuthenticationProvider.incorrectKey=Pou\u017eit\u00fd CasAuthenticationToken neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d CasAuthenticationProvider.noServiceTicket=Nepoda\u0159ilo se z\u00edskat otisk CAS (centr\u00e1ln\u00ed autentiza\u010dn\u00ed autority) k ov\u011b\u0159en\u00ed autenticity u\u017eivatele. NamedCasProxyDecider.untrusted=Nelze v\u011b\u0159it nejbli\u017e\u0161\u00ed proxy {0} RejectProxyTickets.reject=Otisky proxy jsou odm\u00edtnuty AbstractSecurityInterceptor.authenticationNotFound=Nebyl nalezen \u017e\u00e1dn\u00fd Authentication objekt v SecurityContext AbstractUserDetailsAuthenticationProvider.onlySupports=Je podporov\u00e1n pouze UsernamePasswordAuthenticationToken AbstractUserDetailsAuthenticationProvider.locked=U\u017eivatelsk\u00fd \u00fa\u010det je uzam\u010den AbstractUserDetailsAuthenticationProvider.disabled=U\u017eivatelsk\u00fd \u00fa\u010det nen\u00ed aktivn\u00ed AbstractUserDetailsAuthenticationProvider.expired=Platnost u\u017eivatelsk\u00e9ho \u00fa\u010dtu vypr\u0161ela AbstractUserDetailsAuthenticationProvider.credentialsExpired=Platnost u\u017eivatelsk\u00e9ho hesla vypr\u0161ela AbstractUserDetailsAuthenticationProvider.badCredentials=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje X509AuthenticationProvider.certificateNull=Certifik\u00e1t je pr\u00e1zdn\u00fd DaoX509AuthoritiesPopulator.noMatching=V subjectDN nebyl nalezen \u017e\u00e1dn\u00fd \u0159et\u011bzec odpov\u00eddaj\u00edc\u00ed vy\u017eadovan\u00e9 masce: {0} RememberMeAuthenticationProvider.incorrectKey=Pou\u017eit\u00fd RememberMeAuthenticationToken neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d RunAsImplAuthenticationProvider.incorrectKey=Pou\u017eit\u00fd RunAsUserToken neobsahuje o\u010dek\u00e1van\u00fd kl\u00ed\u010d DigestProcessingFilter.missingMandatory=Chyb\u00ed povinn\u00e1 kl\u00ed\u010dov\u00e1 polo\u017eka; p\u0159ijat\u00e1 hlavi\u010dka {0} DigestProcessingFilter.missingAuth=Chyb\u00ed povinn\u00e1 kl\u00ed\u010dov\u00e1 polo\u017eka 'auth' QOP (\u00farove\u0148 bezpe\u010dnosti RFC 2617); p\u0159ijat\u00e1 hlavi\u010dka {0} DigestProcessingFilter.incorrectRealm=Oblast odpov\u011bdi {0} neodpov\u00edd\u00e1 syst\u00e9mov\u00e9 oblasti {1} DigestProcessingFilter.nonceExpired=Kryptovan\u00fd kl\u00ed\u010d (nonce) vypr\u0161el DigestProcessingFilter.nonceEncoding=Kryptovan\u00fd kl\u00ed\u010d (nonce) nen\u00ed p\u0159ek\u00e9dov\u00e1n do Base60; p\u0159ijat\u00fd kl\u00ed\u010d {0} DigestProcessingFilter.nonceNotTwoTokens=Kryptovan\u00fd kl\u00ed\u010d (nonce) by m\u011bl b\u00fdt slo\u017een ze dvou \u010d\u00e1st\u00ed {0} DigestProcessingFilter.nonceNotNumeric=Kryptovan\u00fd kl\u00ed\u010d (nonce) by m\u011bl m\u00edt prvn\u00ed \u010d\u00e1st \u010d\u00edselnou, ale je {0} DigestProcessingFilter.nonceCompromised=Kryptovan\u00fd kl\u00ed\u010d (nonce) je znehodnocen\u00fd {0} DigestProcessingFilter.usernameNotFound=U\u017eivatelsk\u00e9 jm\u00e9no {0} nebylo nalezeno DigestProcessingFilter.incorrectResponse=Vadn\u00e1 odpov\u011b\u010f SwitchUserProcessingFilter.noCurrentUser=\u017d\u00e1dn\u00fd u\u017eivatel nen\u00ed asociov\u00e1n s t\u00edmto po\u017eadavkem SwitchUserProcessingFilter.noOriginalAuthentication=Nepoda\u0159ilo se nal\u00e9zt p\u016fvodn\u00ed Authentication objekt SwitchUserProcessingFilter.usernameNotFound=U\u017eivatelsk\u00e9 jm\u00e9no {0} nebylo nalezeno SwitchUserProcessingFilter.locked=U\u017eivatelsk\u00fd \u00fa\u010det je uzam\u010den SwitchUserProcessingFilter.disabled=U\u017eivatelsk\u00fd \u00fa\u010det nen\u00ed aktivn\u00ed SwitchUserProcessingFilter.expired=Platnost u\u017eivatelsk\u00e9ho \u00fa\u010dtu vypr\u0161ela SwitchUserProcessingFilter.credentialsExpired=Platnost u\u017eivatelsk\u00e9ho hesla vypr\u0161ela AbstractAccessDecisionManager.accessDenied=P\u0159\u00edstup odep\u0159en LdapAuthenticationProvider.emptyUsername=Nen\u00ed povoleno pr\u00e1zdn\u00e9 u\u017eivatelsk\u00e9 jm\u00e9no LdapAuthenticationProvider.emptyPassword=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje DefaultIntitalDirContextFactory.communicationFailure=Nen\u00ed mo\u017en\u00e9 se p\u0159ipojit k LDAP serveru DefaultIntitalDirContextFactory.badCredentials=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje DefaultIntitalDirContextFactory.unexpectedException=Nepoda\u0159ilo se z\u00edskat InitialDirContext d\u00edky neo\u010dek\u00e1van\u00e9 vyj\u00edmce PasswordComparisonAuthenticator.badCredentials=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje BindAuthenticator.badCredentials=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje BindAuthenticator.failedToLoadAttributes=\u0160patn\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AbstractAuthenticationManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AbstractAuthent0000644000000000000000000000625611623517156030611 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * An abstract implementation of the {@link AuthenticationManager}. * * @author Wesley Hall * @version $Id$ */ public abstract class AbstractAuthenticationManager implements AuthenticationManager { //~ Instance fields ================================================================================================ private boolean clearExtraInformation = false; //~ Methods ======================================================================================================== /** * An implementation of the authenticate method that calls the abstract method * doAuthenticatation to do its work. *

* If doAuthenticate throws an AuthenticationException then the exception is populated * with the failed Authentication object that failed. * * @param authRequest the authentication request object * * @return a fully authenticated object including credentials * * @throws AuthenticationException if authentication fails */ public final Authentication authenticate(Authentication authRequest) throws AuthenticationException { try { return doAuthentication(authRequest); } catch (AuthenticationException e) { e.setAuthentication(authRequest); if (clearExtraInformation) { e.clearExtraInformation(); } throw e; } } /** * Concrete implementations of this class override this method to provide the authentication service. *

* The contract for this method is documented in the * {@link AuthenticationManager#authenticate(Authentication)}. * * @param authentication the authentication request object * * @return a fully authenticated object including credentials * * @throws AuthenticationException if authentication fails */ protected abstract Authentication doAuthentication(Authentication authentication) throws AuthenticationException; /** * If set to true, the extraInformation set on an AuthenticationException will be cleared * before rethrowing it. This is useful for use with remoting protocols where the information shouldn't * be serialized to the client. Defaults to 'false'. * * @see org.springframework.security.AuthenticationException#getExtraInformation() */ public void setClearExtraInformation(boolean clearExtraInformation) { this.clearExtraInformation = clearExtraInformation; } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/GrantedAuthority.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/GrantedAuthorit0000644000000000000000000000457411623517156030622 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; import java.io.Serializable; import org.springframework.security.userdetails.UserDetails; /** * Represents an authority granted to an {@link Authentication} object. * *

* A GrantedAuthority must either represent itself as a * String or be specifically supported by an {@link * AccessDecisionManager}. *

* *

* Implementations must implement {@link Comparable} in order to ensure that * array sorting logic guaranteed by {@link UserDetails#getAuthorities()} can * be reliably implemented. *

* * @author Ben Alex * @version $Id$ */ public interface GrantedAuthority extends Serializable, Comparable { //~ Methods ======================================================================================================== /** * If the GrantedAuthority can be represented as a String and that * String is sufficient in precision to be relied upon for an access control decision by an {@link * AccessDecisionManager} (or delegate), this method should return such a String.

If the * GrantedAuthority cannot be expressed with sufficient precision as a String, * null should be returned. Returning null will require an * AccessDecisionManager (or delegate) to specifically support the GrantedAuthority * implementation, so returning null should be avoided unless actually required.

* * @return a representation of the granted authority (or null if the granted authority cannot be * expressed as a String with sufficient precision). */ String getAuthority(); } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/0000755000000000000000000000000011623520546027363 5ustar ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/HttpFirewall.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/HttpFi0000644000000000000000000000221411623517156030506 0ustar package org.springframework.security.firewall; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Interface which can be used to reject potentially dangerous requests and/or wrap them to * control their behaviour. *

* The implementation is injected into the {@code FilterChainProxy} and will be invoked before * sending any request through the filter chain. It can also provide a response wrapper if the response * behaviour should also be restricted. * * @author Luke Taylor */ public interface HttpFirewall { /** * Provides the request object which will be passed through the filter chain. * * @throws RequestRejectedException if the request should be rejected immediately */ FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException; /** * Provides the response which will be passed through the filter chain. * * @param response the original response * @return either the original response or a replacement/wrapper. */ HttpServletResponse getFirewalledResponse(HttpServletResponse response); } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/RequestRejectedException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/Reques0000644000000000000000000000034611623517156030560 0ustar package org.springframework.security.firewall; /** * @author Luke Taylor */ public class RequestRejectedException extends RuntimeException { public RequestRejectedException(String message) { super(message); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/RequestWrapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/Reques0000644000000000000000000001202511623517156030555 0ustar package org.springframework.security.firewall; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.*; /** * Request wrapper which ensures values of {@code servletPath} and {@code pathInfo} are returned which are suitable for * pattern matching against. It strips out path parameters and extra consecutive '/' characters. * *

Path Parameters

* Parameters (as defined in RFC 2396) are stripped from the path * segments of the {@code servletPath} and {@code pathInfo} values of the request. *

* The parameter sequence is demarcated by a semi-colon, so each segment is checked for the occurrence of a ";" * character and truncated at that point if it is present. *

* The behaviour differs between servlet containers in how they interpret the servlet spec, which * does not clearly state what the behaviour should be. For consistency, we make sure they are always removed, to * avoid the risk of URL matching rules being bypassed by the malicious addition of parameters to the path component. * * @author Luke Taylor */ final class RequestWrapper extends FirewalledRequest { private final String strippedServletPath; private final String strippedPathInfo; private boolean stripPaths = true; public RequestWrapper(HttpServletRequest request) { super(request); strippedServletPath = strip(request.getServletPath()); String pathInfo = strip(request.getPathInfo()); if (pathInfo != null && pathInfo.length() == 0) { pathInfo = null; } strippedPathInfo = pathInfo; } /** * Removes path parameters from each path segment in the supplied path and truncates sequences of multiple '/' * characters to a single '/'. * * @param path either the {@code servletPath} and {@code pathInfo} from the original request * * @return the supplied value, with path parameters removed and sequences of multiple '/' characters truncated, * or null if the supplied path was null. */ private String strip(String path) { if (path == null) { return null; } int scIndex = path.indexOf(';'); if (scIndex < 0) { int doubleSlashIndex = path.indexOf("//"); if (doubleSlashIndex < 0) { // Most likely case, no parameters in any segment and no '//', so no stripping required return path; } } StringTokenizer st = new StringTokenizer(path, "/"); StringBuilder stripped = new StringBuilder(path.length()); if (path.charAt(0) == '/') { stripped.append('/'); } while(st.hasMoreTokens()) { String segment = st.nextToken(); scIndex = segment.indexOf(';'); if (scIndex >= 0) { segment = segment.substring(0, scIndex); } stripped.append(segment).append('/'); } // Remove the trailing slash if the original path didn't have one if (path.charAt(path.length() - 1) != '/') { stripped.deleteCharAt(stripped.length() - 1); } return stripped.toString(); } public String getPathInfo() { return stripPaths ? strippedPathInfo : super.getPathInfo(); } public String getServletPath() { return stripPaths ? strippedServletPath : super.getServletPath(); } public RequestDispatcher getRequestDispatcher(String path) { return this.stripPaths ? new FirewalledRequestAwareRequestDispatcher(path) : super.getRequestDispatcher(path); } public void reset() { this.stripPaths = false; } /** * Ensures {@link FirewalledRequest#reset()} is called prior to performing a forward. It then delegates work to the * {@link RequestDispatcher} from the original {@link HttpServletRequest}. * * @author Rob Winch */ private class FirewalledRequestAwareRequestDispatcher implements RequestDispatcher { private final String path; /** * * @param path the {@code path} that will be used to obtain the delegate {@link RequestDispatcher} from the * original {@link HttpServletRequest}. */ public FirewalledRequestAwareRequestDispatcher(String path) { this.path = path; } public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException { reset(); getDelegateDispatcher().forward(request, response); } public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException { getDelegateDispatcher().include(request, response); } private RequestDispatcher getDelegateDispatcher() { return RequestWrapper.super.getRequestDispatcher(path); } } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/DefaultHttpFirewall.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/Defaul0000644000000000000000000000534011623520546030510 0ustar package org.springframework.security.firewall; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Default implementation which wraps requests in order to provide consistent values of the {@code servletPath} and * {@code pathInfo}, which do not contain path parameters (as defined in * RFC 2396). Different servlet containers * interpret the servlet spec differently as to how path parameters are treated and it is possible they might be added * in order to bypass particular security constraints. When using this implementation, they will be removed for all * requests as the request passes through the security filter chain. Note that this means that any segments in the * decoded path which contain a semi-colon, will have the part following the semi-colon removed for * request matching. Your application should not contain any valid paths which contain semi-colons. *

* If any un-normalized paths are found (containing directory-traversal character sequences), the request will be * rejected immediately. Most containers normalize the paths before performing the servlet-mapping, but again this is * not guaranteed by the servlet spec. * * @author Luke Taylor */ public class DefaultHttpFirewall implements HttpFirewall { public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException { FirewalledRequest fwr = new RequestWrapper(request); if (!isNormalized(fwr.getServletPath()) || !isNormalized(fwr.getPathInfo())) { throw new RequestRejectedException("Un-normalized paths are not supported: " + fwr.getServletPath() + (fwr.getPathInfo() != null ? fwr.getPathInfo() : "")); } return fwr; } public HttpServletResponse getFirewalledResponse(HttpServletResponse response) { return new FirewalledResponse(response); } /** * Checks whether a path is normalized (doesn't contain path traversal sequences like "./", "/../" or "/.") * * @param path the path to test * @return true if the path doesn't contain any path-traversal character sequences. */ private boolean isNormalized(String path) { if (path == null) { return true; } for (int j = path.length(); j > 0;) { int i = path.lastIndexOf('/', j - 1); int gap = j - i; if (gap == 2 && path.charAt(i+1) == '.') { // ".", "/./" or "/." return false; } else if (gap == 3 && path.charAt(i+1) == '.'&& path.charAt(i+2) == '.') { return false; } j = i; } return true; } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/FirewalledResponse.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/Firewa0000644000000000000000000000153011623520546030522 0ustar package org.springframework.security.firewall; import javax.servlet.http.HttpServletResponseWrapper; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.regex.Pattern; /** * @author Luke Taylor */ class FirewalledResponse extends HttpServletResponseWrapper { Pattern CR_OR_LF = Pattern.compile("\\r|\\n"); public FirewalledResponse(HttpServletResponse response) { super(response); } public void sendRedirect(String location) throws IOException { // TODO: implement pluggable validation, instead of simple blacklisting. // SEC-1790. Prevent redirects containing CRLF if (CR_OR_LF.matcher(location).find()) { throw new IllegalArgumentException("Invalid characters (CR/LF) in redirect location"); } super.sendRedirect(location); } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/FirewalledRequest.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/firewall/Firewa0000644000000000000000000000216711623517156030534 0ustar package org.springframework.security.firewall; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** * Request wrapper which is returned by the {@code HttpFirewall} interface. *

* The only difference is the {@code reset} method which allows some * or all of the state to be reset by the {@code FilterChainProxy} when the * request leaves the security filter chain. * * @author Luke Taylor */ public abstract class FirewalledRequest extends HttpServletRequestWrapper { /** * Constructs a request object wrapping the given request. * * @throws IllegalArgumentException if the request is null */ public FirewalledRequest(HttpServletRequest request) { super(request); } /** * This method will be called once the request has passed through the * security filter chain, when it is about to proceed to the application * proper. *

* An implementation can thus choose to modify the state of the request * for the security infrastructure, while still maintaining the */ public abstract void reset(); } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AfterInvocationManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AfterInvocation0000644000000000000000000001025611623517156030603 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Reviews the Object returned from a secure object invocation, * being able to modify the Object or throw an {@link * AccessDeniedException}. * *

* Typically used to ensure the principal is permitted to access the domain * object instance returned by a service layer bean. Can also be used to * mutate the domain object instance so the principal is only able to access * authorised bean properties or Collection elements. Often used * in conjunction with an {@link org.springframework.security.acl.AclManager} to * obtain the access control list applicable for the domain object instance. *

* *

* Special consideration should be given to using an * AfterInvocationManager on bean methods that modify a database. * Typically an AfterInvocationManager is used with read-only * methods, such as public DomainObject getById(id). If used with * methods that modify a database, a transaction manager should be used to * ensure any AccessDeniedException will cause a rollback of the * changes made by the transaction. *

* * @author Ben Alex * @version $Id$ */ public interface AfterInvocationManager { //~ Methods ======================================================================================================== /** * Given the details of a secure object invocation including its returned Object, make an * access control decision or optionally modify the returned Object. * * @param authentication the caller that invoked the method * @param object the secured object that was called * @param config the configuration attributes associated with the secured object that was invoked * @param returnedObject the Object that was returned from the secure object invocation * * @return the Object that will ultimately be returned to the caller (if an implementation does not * wish to modify the object to be returned to the caller, the implementation should simply return the * same object it was passed by the returnedObject method argument) * * @throws AccessDeniedException if access is denied */ Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException; /** * Indicates whether this AfterInvocationManager is able to process "after invocation" * requests presented with the passed ConfigAttribute.

This allows the * AbstractSecurityInterceptor to check every configuration attribute can be consumed by the * configured AccessDecisionManager and/or RunAsManager and/or * AfterInvocationManager.

* * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor * * @return true if this AfterInvocationManager can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); /** * Indicates whether the AfterInvocationManager implementation is able to provide access * control decisions for the indicated secured object type. * * @param clazz the class that is being queried * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthenticationManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthenticationM0000644000000000000000000000461011623517156030601 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Processes an {@link Authentication} request. * * @author Ben Alex * @version $Id$ */ public interface AuthenticationManager { //~ Methods ======================================================================================================== /** * Attempts to authenticate the passed {@link Authentication} object, returning a fully populated * Authentication object (including granted authorities) if successful.

An * AuthenticationManager must honour the following contract concerning exceptions:

*

A {@link DisabledException} must be thrown if an account is disabled and the * AuthenticationManager can test for this state.

*

A {@link LockedException} must be thrown if an account is locked and the * AuthenticationManager can test for account locking.

*

A {@link BadCredentialsException} must be thrown if incorrect credentials are presented. Whilst the * above exceptions are optional, an AuthenticationManager must always test credentials.

*

Exceptions should be tested for and if applicable thrown in the order expressed above (ie if an * account is disabled or locked, the authentication request is immediately rejected and the credentials testing * process is not performed). This prevents credentials being tested against disabled or locked accounts.

* * @param authentication the authentication request object * * @return a fully authenticated object including credentials * * @throws AuthenticationException if authentication fails */ Authentication authenticate(Authentication authentication) throws AuthenticationException; } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/MutableGrantedAuthoritiesContainer.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/MutableGrantedA0000644000000000000000000000107611623517156030507 0ustar package org.springframework.security; /** * Indicates that a object can be used to store and retrieve GrantedAuthority objects. *

* Typically used in a pre-authenticated scenario when an AuthenticationDetails instance may also be * used to obtain user authorities. * * @author Ruud Senden * @author Luke Taylor * @since 2.0 */ public interface MutableGrantedAuthoritiesContainer extends GrantedAuthoritiesContainer { /** * Used to store authorities in the containing object. */ void setGrantedAuthorities(GrantedAuthority[] authorities); } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_pl.propertiesspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_pl.pro0000644000000000000000000001235711623517156030615 0ustar AuthByAdapterProvider.incorrectKey=Podana implementacja AuthByAdapter nie zawiera oczekiwanego klucza BasicAclEntryAfterInvocationProvider.noPermission=U\u017cytkownik {0} nie posiada \u017bADNYCH uprawnie\u0144 do obiektu {1} BasicAclEntryAfterInvocationProvider.insufficientPermission=U\u017cytkownik {0} nie posiada wymaganych uprawnie\u0144 do obiektu {1} ConcurrentSessionControllerImpl.exceededAllowed=Maksymalna liczba sesji ({0}) dla tego u\u017cytkownika zosta\u0142a przekroczona ProviderManager.providerNotFound=AuthenticationProvider dla {0} nie zosta\u0142 znaleziony AnonymousAuthenticationProvider.incorrectKey=Podany AnonymousAuthenticationToken nie zawiera oczekiwanego klucza CasAuthenticationProvider.incorrectKey=Podany CasAuthenticationToken nie zawiera oczekiwanego klucza CasAuthenticationProvider.noServiceTicket=Dostarczenie biletu serwisu CAS do walidacji nie powiod\u0142o si\u0119 NamedCasProxyDecider.untrusted=Najbli\u017cszy serwer po\u015brednicz\u0105cy {0} jest niezaufany RejectProxyTickets.reject=Bilety serwera po\u015brednicz\u0105cego zosta\u0142y odrzucone AbstractSecurityInterceptor.authenticationNotFound=Obiekt Authentication nie zosta\u0142 odnaleziony w SecurityContext AbstractUserDetailsAuthenticationProvider.onlySupports=Tylko UsernamePasswordAuthenticationToken jest obs\u0142ugiwany AbstractUserDetailsAuthenticationProvider.locked=Konto u\u017cytkownika jest zablokowane AbstractUserDetailsAuthenticationProvider.disabled=Konto u\u017cytkownika jest wy\u0142\u0105czone AbstractUserDetailsAuthenticationProvider.expired=Wa\u017cno\u015b\u0107 konta u\u017cytkownika wygas\u0142a AbstractUserDetailsAuthenticationProvider.credentialsExpired=Wa\u017cno\u015b\u0107 danych uwierzytelniaj\u0105cych wygas\u0142a AbstractUserDetailsAuthenticationProvider.badCredentials=Niepoprawne dane uwierzytelniaj\u0105ce X509AuthenticationProvider.certificateNull=Certyfikat jest pusty DaoX509AuthoritiesPopulator.noMatching=Nie odnaleziono pasuj\u0105cego wzorca w subjectDN: {0} RememberMeAuthenticationProvider.incorrectKey=Podany RememberMeAuthenticationToken nie zawiera oczekiwanego klucza RunAsImplAuthenticationProvider.incorrectKey=Podany RunAsUserToken nie zawiera oczekiwanego klucza DigestProcessingFilter.missingMandatory=Brakuje wymaganej warto\u015bci skr\u00f3tu; otrzymany nag\u0142\u00f3wek {0} DigestProcessingFilter.missingAuth=Brakuje wymaganej warto\u015bci skr\u00f3tu dla 'auth' QOP; otrzymany nag\u0142\u00f3wek {0} DigestProcessingFilter.incorrectRealm=Nazwa domeny {0} w odpowiedzi nie jest zgodna z nazw\u0105 domeny {1} w systemie DigestProcessingFilter.nonceExpired=Wa\u017cno\u015b\u0107 kodu jednorazowego (nonce) wygas\u0142a DigestProcessingFilter.nonceEncoding=Kod jednorazowy (nonce) nie jest zakodowany w Base64; otrzymany kod {0} DigestProcessingFilter.nonceNotTwoTokens=Kod jednorazowy (nonce) powinien zawiera\u0107 dwie warto\u015bci {0} DigestProcessingFilter.nonceNotNumeric=Pierwsza warto\u015b\u0107 kodu jednorazowego (nonce) nie jest warto\u015bci\u0105 numeryczn\u0105: {0} DigestProcessingFilter.nonceCompromised=Niepoprawny kod jednorazowy (nonce) {0} DigestProcessingFilter.usernameNotFound=Nazwa u\u017cytkownika {0} nie zosta\u0142a odnaleziona DigestProcessingFilter.incorrectResponse=Niepoprawna odpowied\u017a JdbcDaoImpl.notFound=Nazwa u\u017cytkownika {0} nie zosta\u0142a odnaleziona JdbcDaoImpl.noAuthority=U\u017cytkownik {0} nie posiada \u017cadnych uprawnie\u0144 (GrantedAuthority) SwitchUserProcessingFilter.noCurrentUser=\u017baden aktualny u\u017cytkownik nie jest powi\u0105zany z tym zapytaniem SwitchUserProcessingFilter.noOriginalAuthentication=Nie mo\u017cna by\u0142o odnale\u017a\u0107 oryginalnego obiektu Authentication SwitchUserProcessingFilter.usernameNotFound=Nazwa u\u017cytkownika {0} nie zosta\u0142a odnaleziona SwitchUserProcessingFilter.locked=Konto u\u017cytkownika jest zablokowane SwitchUserProcessingFilter.disabled=Konto u\u017cytkownika jest wy\u0142\u0105czone SwitchUserProcessingFilter.expired=Wa\u017cno\u015b\u0107 konta u\u017cytkownika wygas\u0142a SwitchUserProcessingFilter.credentialsExpired=Wa\u017cno\u015b\u0107 danych uwierzytelniaj\u0105cych wygas\u0142a AbstractAccessDecisionManager.accessDenied=Dost\u0119p zabroniony LdapAuthenticationProvider.emptyUsername=Pusta nazwa u\u017cytkownika jest niedozwolona LdapAuthenticationProvider.emptyPassword=Niepoprawne dane uwierzytelniaj\u0105ce DefaultIntitalDirContextFactory.communicationFailure=Po\u0142\u0105czenie z serwerem LDAP nie powiod\u0142o si\u0119 DefaultIntitalDirContextFactory.badCredentials=Niepoprawne dane uwierzytelniaj\u0105ce DefaultIntitalDirContextFactory.unexpectedException=Nie mo\u017cna by\u0142o uzyska\u0107 InitialDirContext z powodu nieoczekiwanego wyj\u0105tku PasswordComparisonAuthenticator.badCredentials=Niepoprawne dane uwierzytelniaj\u0105ce BindAuthenticator.badCredentials=Niepoprawne dane uwierzytelniaj\u0105ce BindAuthenticator.failedToLoadAttributes=Niepoprawne dane uwierzytelniaj\u0105ce UserDetailsService.locked=Konto u\u017cytkownika jest zablokowane UserDetailsService.disabled=Konto u\u017cytkownika jest wy\u0142\u0105czone UserDetailsService.expired=Wa\u017cno\u015b\u0107 konta u\u017cytkownika wygas\u0142a UserDetailsService.credentialsExpired=Wa\u017cno\u015b\u0107 danych uwierzytelniaj\u0105cych wygas\u0142a ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/BadCredentialsException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/BadCredentialsE0000644000000000000000000000345411623517156030463 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Thrown if an authentication request is rejected because the credentials are invalid. For this exception to be * thrown, it means the account is neither locked nor disabled. * * @author Ben Alex * @version $Id$ */ public class BadCredentialsException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs a BadCredentialsException with the specified * message. * * @param msg the detail message */ public BadCredentialsException(String msg) { super(msg); } public BadCredentialsException(String msg, Object extraInformation) { super(msg, extraInformation); } /** * Constructs a BadCredentialsException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public BadCredentialsException(String msg, Throwable t) { super(msg, t); } //~ Methods ======================================================================================================== } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthenticationException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthenticationE0000644000000000000000000000522411623520776030575 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Abstract superclass for all exceptions related an {@link Authentication} object being invalid for whatever * reason. * * @author Ben Alex * @version $Id$ */ public abstract class AuthenticationException extends SpringSecurityException { //~ Instance fields ================================================================================================ private Authentication authentication; private transient Object extraInformation; //~ Constructors =================================================================================================== /** * Constructs an AuthenticationException with the specified * message and root cause. * * @param msg the detail message * @param t the root cause */ public AuthenticationException(String msg, Throwable t) { super(msg, t); } /** * Constructs an AuthenticationException with the specified * message and no root cause. * * @param msg the detail message */ public AuthenticationException(String msg) { super(msg); } public AuthenticationException(String msg, Object extraInformation) { super(msg); this.extraInformation = extraInformation; } //~ Methods ======================================================================================================== /** * The authentication request which this exception corresponds to (may be null) */ public Authentication getAuthentication() { return authentication; } void setAuthentication(Authentication authentication) { this.authentication = authentication; } /** * Any additional information about the exception. Generally a UserDetails object. * * @return extra information or null */ public Object getExtraInformation() { return extraInformation; } void clearExtraInformation() { this.extraInformation = null; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/SecurityConfig.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/SecurityConfig.0000644000000000000000000000352211623517156030521 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; import org.springframework.util.Assert; /** * Stores a {@link ConfigAttribute} as a String. * * @author Ben Alex * @version $Id$ */ public class SecurityConfig implements ConfigAttribute { //~ Instance fields ================================================================================================ private String attrib; //~ Constructors =================================================================================================== public SecurityConfig(String config) { Assert.hasText(config, "You must provide a configuration attribute"); this.attrib = config; } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (obj instanceof ConfigAttribute) { ConfigAttribute attr = (ConfigAttribute) obj; return this.attrib.equals(attr.getAttribute()); } return false; } public String getAttribute() { return this.attrib; } public int hashCode() { return this.attrib.hashCode(); } public String toString() { return this.attrib; } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/GrantedAuthoritiesContainer.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/GrantedAuthorit0000644000000000000000000000071711623517156030615 0ustar package org.springframework.security; import java.io.Serializable; /** * Indicates that a object stores GrantedAuthority objects. *

* Typically used in a pre-authenticated scenario when an AuthenticationDetails instance may also be * used to obtain user authorities. * * @author Ruud Senden * @author Luke Taylor * @since 2.0 */ public interface GrantedAuthoritiesContainer extends Serializable { GrantedAuthority[] getGrantedAuthorities(); } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/0000755000000000000000000000000011623517156027743 5ustar ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/SessionIdentifierAware.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/Sess0000644000000000000000000000314511623517156030606 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.concurrent; /** * Implemented by {@link org.springframework.security.Authentication#getDetails()} * implementations that are capable of returning a session ID. * *

* This interface is used by {@link * org.springframework.security.concurrent.SessionRegistryUtils} to extract the session * ID from an Authentication object. In turn, * SessionRegistryUtils is used by {@link * ConcurrentSessionControllerImpl}. If not using this latter implementation, * you do not need the Authentication.getDetails() object to * implement SessionIdentifierAware. *

* * @author Ben Alex * @version $Id$ */ public interface SessionIdentifierAware { //~ Methods ======================================================================================================== /** * Obtains the session ID. * * @return the session ID, or null if not known. */ String getSessionId(); } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/NullConcurrentSessionController.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/Null0000644000000000000000000000247611623517156030611 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.concurrent; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; /** * No-op implementation of {@link org.springframework.security.concurrent.ConcurrentSessionController}. * * @author Ben Alex * @version $Id$ */ public class NullConcurrentSessionController implements ConcurrentSessionController { //~ Methods ======================================================================================================== public void checkAuthenticationAllowed(Authentication request) throws AuthenticationException {} public void registerSuccessfulAuthentication(Authentication authentication) {} } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/SessionRegistryImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/Sess0000644000000000000000000001411611623517156030606 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.concurrent; import org.springframework.security.ui.session.HttpSessionDestroyedEvent; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpSession; /** * Base implementation of {@link org.springframework.security.concurrent.SessionRegistry} * which also listens for {@link org.springframework.security.ui.session.HttpSessionDestroyedEvent}s * published in the Spring application context. * *

* NB: It is important that you register the {@link org.springframework.security.ui.session.HttpSessionEventPublisher} in * web.xml so that this class is notified of sessions that expire. *

* * @author Ben Alex * @version $Id$ */ public class SessionRegistryImpl implements SessionRegistry, ApplicationListener { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(SessionRegistryImpl.class); // ~ Instance fields =============================================================================================== private Map principals = Collections.synchronizedMap(new HashMap()); // private Map sessionIds = Collections.synchronizedMap(new HashMap()); // // ~ Methods ======================================================================================================= public Object[] getAllPrincipals() { return principals.keySet().toArray(); } public SessionInformation[] getAllSessions(Object principal, boolean includeExpiredSessions) { Set sessionsUsedByPrincipal = (Set) principals.get(principal); if (sessionsUsedByPrincipal == null) { return null; } List list = new ArrayList(); synchronized (sessionsUsedByPrincipal) { for (Iterator iter = sessionsUsedByPrincipal.iterator(); iter.hasNext();) { String sessionId = (String) iter.next(); SessionInformation sessionInformation = getSessionInformation(sessionId); if (sessionInformation == null) { continue; } if (includeExpiredSessions || !sessionInformation.isExpired()) { list.add(sessionInformation); } } } return (SessionInformation[]) list.toArray(new SessionInformation[] {}); } public SessionInformation getSessionInformation(String sessionId) { Assert.hasText(sessionId, "SessionId required as per interface contract"); return (SessionInformation) sessionIds.get(sessionId); } public void onApplicationEvent(ApplicationEvent event) { if (event instanceof HttpSessionDestroyedEvent) { String sessionId = ((HttpSession) event.getSource()).getId(); removeSessionInformation(sessionId); } } public void refreshLastRequest(String sessionId) { Assert.hasText(sessionId, "SessionId required as per interface contract"); SessionInformation info = getSessionInformation(sessionId); if (info != null) { info.refreshLastRequest(); } } public synchronized void registerNewSession(String sessionId, Object principal) { Assert.hasText(sessionId, "SessionId required as per interface contract"); Assert.notNull(principal, "Principal required as per interface contract"); if (logger.isDebugEnabled()) { logger.debug("Registering session " + sessionId +", for principal " + principal); } if (getSessionInformation(sessionId) != null) { removeSessionInformation(sessionId); } sessionIds.put(sessionId, new SessionInformation(principal, sessionId, new Date())); Set sessionsUsedByPrincipal = (Set) principals.get(principal); if (sessionsUsedByPrincipal == null) { sessionsUsedByPrincipal = Collections.synchronizedSet(new HashSet(4)); principals.put(principal, sessionsUsedByPrincipal); } sessionsUsedByPrincipal.add(sessionId); } public void removeSessionInformation(String sessionId) { Assert.hasText(sessionId, "SessionId required as per interface contract"); SessionInformation info = getSessionInformation(sessionId); if (info == null) { return; } if (logger.isDebugEnabled()) { logger.debug("Removing session " + sessionId + " from set of registered sessions"); } sessionIds.remove(sessionId); Set sessionsUsedByPrincipal = (Set) principals.get(info.getPrincipal()); if (sessionsUsedByPrincipal == null) { return; } if (logger.isDebugEnabled()) { logger.debug("Removing session " + sessionId + " from principal's set of registered sessions"); } synchronized (sessionsUsedByPrincipal) { sessionsUsedByPrincipal.remove(sessionId); if (sessionsUsedByPrincipal.size() == 0) { // No need to keep object in principals Map anymore if (logger.isDebugEnabled()) { logger.debug("Removing principal " + info.getPrincipal() + " from registry"); } principals.remove(info.getPrincipal()); } } } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/pack0000644000000000000000000000012411623517156030601 0ustar Concurrent session control and registration classes. ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/ConcurrentSessionFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/Conc0000644000000000000000000001261711623517156030557 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.concurrent; import org.springframework.security.Authentication; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.ui.FilterChainOrder; import org.springframework.security.ui.SpringSecurityFilter; import org.springframework.security.ui.logout.LogoutHandler; import org.springframework.security.ui.logout.SecurityContextLogoutHandler; import org.springframework.security.util.UrlUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; /** * Filter required by concurrent session handling package. *

* This filter performs two functions. First, it calls * {@link org.springframework.security.concurrent.SessionRegistry#refreshLastRequest(String)} for each request * so that registered sessions always have a correct "last update" date/time. Second, it retrieves a * {@link org.springframework.security.concurrent.SessionInformation} from the SessionRegistry * for each request and checks if the session has been marked as expired. * If it has been marked as expired, the configured logout handlers will be called (as happens with * {@link org.springframework.security.ui.logout.LogoutFilter}), typically to invalidate the session. * A redirect to the expiredURL specified will be performed, and the session invalidation will cause an * {@link org.springframework.security.ui.session.HttpSessionDestroyedEvent} to be published via the * {@link org.springframework.security.ui.session.HttpSessionEventPublisher} registered in web.xml.

* * @author Ben Alex * @version $Id$ */ public class ConcurrentSessionFilter extends SpringSecurityFilter implements InitializingBean { //~ Instance fields ================================================================================================ private SessionRegistry sessionRegistry; private String expiredUrl; private LogoutHandler[] handlers = new LogoutHandler[] {new SecurityContextLogoutHandler()}; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(sessionRegistry, "SessionRegistry required"); Assert.isTrue(UrlUtils.isValidRedirectUrl(expiredUrl), expiredUrl + " isn't a valid redirect URL"); } public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { HttpSession session = request.getSession(false); if (session != null) { SessionInformation info = sessionRegistry.getSessionInformation(session.getId()); if (info != null) { if (info.isExpired()) { // Expired - abort processing doLogout(request, response); String targetUrl = determineExpiredUrl(request, info); if (targetUrl != null) { targetUrl = request.getContextPath() + targetUrl; response.sendRedirect(response.encodeRedirectURL(targetUrl)); } else { response.getWriter().print("This session has been expired (possibly due to multiple concurrent " + "logins being attempted as the same user)."); response.flushBuffer(); } return; } else { // Non-expired - update last request date/time info.refreshLastRequest(); } } } chain.doFilter(request, response); } protected String determineExpiredUrl(HttpServletRequest request, SessionInformation info) { return expiredUrl; } private void doLogout(HttpServletRequest request, HttpServletResponse response) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); for (int i = 0; i < handlers.length; i++) { handlers[i].logout(request, response, auth); } } public void setExpiredUrl(String expiredUrl) { this.expiredUrl = expiredUrl; } public void setSessionRegistry(SessionRegistry sessionRegistry) { this.sessionRegistry = sessionRegistry; } public void setLogoutHandlers(LogoutHandler[] handlers) { Assert.notNull(handlers); this.handlers = handlers; } public int getOrder() { return FilterChainOrder.CONCURRENT_SESSION_FILTER; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/SessionInformation.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/Sess0000644000000000000000000000557011623517156030612 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.concurrent; import org.springframework.util.Assert; import java.util.Date; import java.io.Serializable; /** * Represents a record of a session within the Spring Security framework. *

This is primarily used for concurrent session support.

*

Sessions have three states: active, expired, and destroyed. A session can that is invalidated by * session.invalidate() or via Servlet Container management is considered "destroyed". An "expired" * session, on the other hand, is a session that Spring Security wants to end because it was selected for removal for * some reason (generally as it was the least recently used session and the maximum sessions for the user were * reached). An "expired" session is removed as soon as possible by a Filter.

* * @author Ben Alex * @version $Id$ */ public class SessionInformation implements Serializable { //~ Instance fields ================================================================================================ private Date lastRequest; private Object principal; private String sessionId; private boolean expired = false; //~ Constructors =================================================================================================== public SessionInformation(Object principal, String sessionId, Date lastRequest) { Assert.notNull(principal, "Principal required"); Assert.hasText(sessionId, "SessionId required"); Assert.notNull(lastRequest, "LastRequest required"); this.principal = principal; this.sessionId = sessionId; this.lastRequest = lastRequest; } //~ Methods ======================================================================================================== public void expireNow() { this.expired = true; } public Date getLastRequest() { return lastRequest; } public Object getPrincipal() { return principal; } public String getSessionId() { return sessionId; } public boolean isExpired() { return expired; } /** * Refreshes the internal lastRequest to the current date and time. */ public void refreshLastRequest() { this.lastRequest = new Date(); } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/SessionRegistryUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/Sess0000644000000000000000000000430211623517156030602 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.concurrent; import org.springframework.security.Authentication; import org.springframework.security.userdetails.UserDetails; import org.springframework.util.Assert; /** * Utility methods to assist with concurrent session management. * * @author Ben Alex * @version $Id$ */ public final class SessionRegistryUtils { //~ Constructors =================================================================================================== private SessionRegistryUtils() { } //~ Methods ======================================================================================================== public static Object obtainPrincipalFromAuthentication(Authentication auth) { Assert.notNull(auth, "Authentication required"); Assert.notNull(auth.getPrincipal(), "Authentication.getPrincipal() required"); if (auth.getPrincipal() instanceof UserDetails) { return ((UserDetails) auth.getPrincipal()).getUsername(); } else { return auth.getPrincipal(); } } public static String obtainSessionIdFromAuthentication(Authentication auth) { Assert.notNull(auth, "Authentication required"); Assert.notNull(auth.getDetails(), "Authentication.getDetails() required"); Assert.isInstanceOf(SessionIdentifierAware.class, auth.getDetails()); String sessionId = ((SessionIdentifierAware) auth.getDetails()).getSessionId(); Assert.hasText(sessionId, "SessionIdentifierAware did not return a Session ID (" + auth.getDetails() + ")"); return sessionId; } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/SessionRegistry.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/Sess0000644000000000000000000000672611623517156030616 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.concurrent; /** * Maintains a registry of SessionInformation instances. * * @author Ben Alex * @version $Id$ */ public interface SessionRegistry { //~ Methods ======================================================================================================== /** * Obtains all the known principals in the SessionRegistry. * * @return each of the unique principals, which can then be presented to {@link #getAllSessions(Object, boolean)}. */ Object[] getAllPrincipals(); /** * Obtains all the known sessions for the specified principal. Sessions that have been destroyed are not * returned. Sessions that have expired may be returned, depending on the passed argument. * * @param principal to locate sessions for (should never be null) * @param includeExpiredSessions if true, the returned sessions will also include those that have * expired for the principal * * @return the matching sessions for this principal, or null if none were found */ SessionInformation[] getAllSessions(Object principal, boolean includeExpiredSessions); /** * Obtains the session information for the specified sessionId. Even expired sessions are * returned (although destroyed sessions are never returned). * * @param sessionId to lookup (should never be null) * * @return the session information, or null if not found */ SessionInformation getSessionInformation(String sessionId); /** * Updates the given sessionId so its last request time is equal to the present date and time. * Silently returns if the given sessionId cannot be found or the session is marked to expire. * * @param sessionId for which to update the date and time of the last request (should never be null) */ void refreshLastRequest(String sessionId); /** * Registers a new session for the specified principal. The newly registered session will not be marked for * expiration. * * @param sessionId to associate with the principal (should never be null) * @param principal to associate with the session (should never be null) * * @throws SessionAlreadyUsedException DOCUMENT ME! */ void registerNewSession(String sessionId, Object principal) throws SessionAlreadyUsedException; /** * Deletes all the session information being maintained for the specified sessionId. If the * sessionId is not found, the method gracefully returns. * * @param sessionId to delete information for (should never be null) */ void removeSessionInformation(String sessionId); } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/SessionAlreadyUsedException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/Sess0000644000000000000000000000241411623517156030604 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.concurrent; import org.springframework.security.AuthenticationException; /** * Thrown by a SessionRegistry implementation if an attempt is made to create new session information * for an existing sessionId. The user should firstly clear the existing session from the * ConcurrentSessionRegistry. * * @author Ben Alex */ public class SessionAlreadyUsedException extends AuthenticationException { //~ Constructors =================================================================================================== public SessionAlreadyUsedException(String msg) { super(msg); } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/ConcurrentLoginException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/Conc0000644000000000000000000000227611623517156030557 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.concurrent; import org.springframework.security.AuthenticationException; /** * Thrown by ConcurrentSessionControllerImpl if an attempt is made to login and the user has already * exceeded their maxmimum allowed sessions. * * @author Ben Alex * @version $Id$ */ public class ConcurrentLoginException extends AuthenticationException { //~ Constructors =================================================================================================== public ConcurrentLoginException(String msg) { super(msg); } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/ConcurrentSessionControllerImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/Conc0000644000000000000000000001545211623517156030557 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.concurrent; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * Base implementation of {@link ConcurrentSessionControllerImpl} which prohibits simultaneous logins.

By default * uses {@link SessionRegistryImpl}, although any SessionRegistry may be used.

* * @author Ben Alex * @version $Id$ */ public class ConcurrentSessionControllerImpl implements ConcurrentSessionController, InitializingBean, MessageSourceAware { //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private SessionRegistry sessionRegistry; private boolean exceptionIfMaximumExceeded = false; private int maximumSessions = 1; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(sessionRegistry, "SessionRegistry required"); Assert.isTrue(maximumSessions != 0, "MaximumLogins must be either -1 to allow unlimited logins, or a positive integer to specify a maximum"); Assert.notNull(this.messages, "A message source must be set"); } /** * Allows subclasses to customise behaviour when too many sessions are detected. * * @param sessionId the session ID of the present request * @param sessions either null or all unexpired sessions associated with the principal * @param allowableSessions DOCUMENT ME! * @param registry an instance of the SessionRegistry for subclass use * * @throws ConcurrentLoginException DOCUMENT ME! */ protected void allowableSessionsExceeded(String sessionId, SessionInformation[] sessions, int allowableSessions, SessionRegistry registry) { if (exceptionIfMaximumExceeded || (sessions == null)) { throw new ConcurrentLoginException(messages.getMessage("ConcurrentSessionControllerImpl.exceededAllowed", new Object[] {new Integer(allowableSessions)}, "Maximum sessions of {0} for this principal exceeded")); } // Determine least recently used session, and mark it for invalidation SessionInformation leastRecentlyUsed = null; for (int i = 0; i < sessions.length; i++) { if ((leastRecentlyUsed == null) || sessions[i].getLastRequest().before(leastRecentlyUsed.getLastRequest())) { leastRecentlyUsed = sessions[i]; } } leastRecentlyUsed.expireNow(); } public void checkAuthenticationAllowed(Authentication request) throws AuthenticationException { Assert.notNull(request, "Authentication request cannot be null (violation of interface contract)"); Object principal = SessionRegistryUtils.obtainPrincipalFromAuthentication(request); String sessionId = SessionRegistryUtils.obtainSessionIdFromAuthentication(request); SessionInformation[] sessions = sessionRegistry.getAllSessions(principal, false); int sessionCount = 0; if (sessions != null) { sessionCount = sessions.length; } int allowableSessions = getMaximumSessionsForThisUser(request); Assert.isTrue(allowableSessions != 0, "getMaximumSessionsForThisUser() must return either -1 to allow " + "unlimited logins, or a positive integer to specify a maximum"); if (sessionCount < allowableSessions) { // They haven't got too many login sessions running at present return; } else if (allowableSessions == -1) { // We permit unlimited logins return; } else if (sessionCount == allowableSessions) { // Only permit it though if this request is associated with one of the sessions for (int i = 0; i < sessionCount; i++) { if (sessions[i].getSessionId().equals(sessionId)) { return; } } } allowableSessionsExceeded(sessionId, sessions, allowableSessions, sessionRegistry); } /** * Method intended for use by subclasses to override the maximum number of sessions that are permitted for * a particular authentication. The default implementation simply returns the maximumSessions value * for the bean. * * @param authentication to determine the maximum sessions for * * @return either -1 meaning unlimited, or a positive integer to limit (never zero) */ protected int getMaximumSessionsForThisUser(Authentication authentication) { return maximumSessions; } public void registerSuccessfulAuthentication(Authentication authentication) { Assert.notNull(authentication, "Authentication cannot be null (violation of interface contract)"); Object principal = SessionRegistryUtils.obtainPrincipalFromAuthentication(authentication); String sessionId = SessionRegistryUtils.obtainSessionIdFromAuthentication(authentication); sessionRegistry.registerNewSession(sessionId, principal); } public void setExceptionIfMaximumExceeded(boolean exceptionIfMaximumExceeded) { this.exceptionIfMaximumExceeded = exceptionIfMaximumExceeded; } public void setMaximumSessions(int maximumSessions) { this.maximumSessions = maximumSessions; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setSessionRegistry(SessionRegistry sessionRegistry) { this.sessionRegistry = sessionRegistry; } public SessionRegistry getSessionRegistry() { return sessionRegistry; } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/ConcurrentSessionController.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/concurrent/Conc0000644000000000000000000000471211623517156030554 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.concurrent; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; /** * Provides two methods that can be called by an {@link * org.springframework.security.AuthenticationManager} to integrate with the * concurrent session handling infrastructure. * * @author Ben Alex * @version $Id$ */ public interface ConcurrentSessionController { //~ Methods ======================================================================================================== /** * Called by any class that wishes to know whether the current authentication request should be permitted. * Generally callers will be AuthenticationManagers before they authenticate, but could equally * include Filters or other interceptors that wish to confirm the ongoing validity of a previously * authenticated Authentication.

The implementation should throw a suitable exception if the * user has exceeded their maximum allowed concurrent sessions.

* * @param request the authentication request (never null) * * @throws AuthenticationException if the user has exceeded their maximum allowed current sessions */ void checkAuthenticationAllowed(Authentication request) throws AuthenticationException; /** * Called by an AuthenticationManager when the authentication was successful. An * implementation is expected to register the authenticated user in some sort of registry, for future concurrent * tracking via the {@link #checkAuthenticationAllowed(Authentication)} method. * * @param authentication the successfully authenticated user (never null) */ void registerSuccessfulAuthentication(Authentication authentication); } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/0000755000000000000000000000000011623517156027245 5ustar ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/SecurityContext.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/Securit0000644000000000000000000000337411623517156030615 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.context; import org.springframework.security.Authentication; import java.io.Serializable; /** * Interface defining the minimum security information associated with the * current thread of execution. * *

* The security context is stored in a {@link SecurityContextHolder}. *

* * @author Ben Alex * @version $Id$ */ public interface SecurityContext extends Serializable { //~ Methods ======================================================================================================== /** * Obtains the currently authenticated principal, or an authentication request token. * * @return the Authentication or null if no authentication information is available */ Authentication getAuthentication(); /** * Changes the currently authenticated principal, or removes the authentication information. * * @param authentication the new Authentication token, or null if no further * authentication information should be stored */ void setAuthentication(Authentication authentication); } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/httpinvoker/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/httpinv0000755000000000000000000000000011623517156030662 5ustar ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/httpinvoker/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/httpinv0000644000000000000000000000161511623517156030667 0ustar Enables use of Spring's HttpInvoker extension points to present the principal and credentials located in the ContextHolder via BASIC authentication.

The beans are wired as follows:

<bean id="test" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl"><value>http://localhost/Test</value></property>
<property name="serviceInterface"><value>test.TargetInterface</value></property>
<property name="httpInvokerRequestExecutor"><ref bean="httpInvokerRequestExecutor"/></property>
</bean>

<bean id="httpInvokerRequestExecutor" class="org.springframework.security.context.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor"/>
././@LongLink0000000000000000000000000000023500000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/httpinv0000644000000000000000000001011111623517156030656 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.context.httpinvoker; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationCredentialsNotFoundException; import org.springframework.security.context.SecurityContextHolder; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor; import java.io.IOException; import java.net.HttpURLConnection; /** * Adds BASIC authentication support to SimpleHttpInvokerRequestExecutor. * * @author Ben Alex * @version $Id$ */ public class AuthenticationSimpleHttpInvokerRequestExecutor extends SimpleHttpInvokerRequestExecutor { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AuthenticationSimpleHttpInvokerRequestExecutor.class); //~ Methods ======================================================================================================== /** * Provided so subclasses can perform additional configuration if required (eg set additional request * headers for non-security related information etc). * * @param con the HTTP connection to prepare * @param contentLength the length of the content to send * * @throws IOException if thrown by HttpURLConnection methods */ protected void doPrepareConnection(HttpURLConnection con, int contentLength) throws IOException {} /** * Called every time a HTTP invocation is made.

Simply allows the parent to setup the connection, and * then adds an Authorization HTTP header property that will be used for BASIC authentication.

*

The SecurityContextHolder is used to obtain the relevant principal and credentials.

* * @param con the HTTP connection to prepare * @param contentLength the length of the content to send * * @throws IOException if thrown by HttpURLConnection methods * @throws AuthenticationCredentialsNotFoundException if the SecurityContextHolder does not contain a * valid Authentication with both its principal and credentials not * null */ protected void prepareConnection(HttpURLConnection con, int contentLength) throws IOException, AuthenticationCredentialsNotFoundException { super.prepareConnection(con, contentLength); Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if ((auth != null) && (auth.getName() != null) && (auth.getCredentials() != null)) { String base64 = auth.getName() + ":" + auth.getCredentials().toString(); con.setRequestProperty("Authorization", "Basic " + new String(Base64.encodeBase64(base64.getBytes()))); if (logger.isDebugEnabled()) { logger.debug("HttpInvocation now presenting via BASIC authentication SecurityContextHolder-derived: " + auth.toString()); } } else { if (logger.isDebugEnabled()) { logger.debug("Unable to set BASIC authentication header as SecurityContext did not provide " + "valid Authentication: " + auth); } } doPrepareConnection(con, contentLength); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/package0000644000000000000000000000037211623517156030565 0ustar Provides a "request context".

A request context is associated with the current execution thread. It holds objects that would otherwise need to be included in many method signatures, such as for authentication.

././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/SecurityContextHolderStrategy.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/Securit0000644000000000000000000000332011623517156030604 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.context; /** * A strategy for storing security context information against a thread. * *

* The preferred strategy is loaded by {@link * org.springframework.security.context.SecurityContextHolder}. *

* * @author Ben Alex * @version $Id$ */ public interface SecurityContextHolderStrategy { //~ Methods ======================================================================================================== /** * Clears the current context. */ void clearContext(); /** * Obtains the current context. * * @return a context (never null - create a default implementation if necessary) */ SecurityContext getContext(); /** * Sets the current context. * * @param context to the new argument (should never be null, although implementations must check if * null has been passed and throw an IllegalArgumentException in such cases) */ void setContext(SecurityContext context); } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/rmi/0000755000000000000000000000000011623520776030036 5ustar ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/rmi/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/rmi/pac0000644000000000000000000000171611623517156030527 0ustar Enables use of Spring's RMI remoting extension points to propagate the ContextHolder (which should contain an Authentication request token) from one JVM to the remote JVM.

The beans are wired as follows:

<bean id="test" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl"><value>rmi://localhost/Test</value></property>
<property name="serviceInterface"><value>test.TargetInterface</value></property>
<property name="refreshStubOnConnectFailure"><value>true</value></property>
<property name="remoteInvocationFactory"><ref bean="remoteInvocationFactory"/></property>
</bean>

<bean id="remoteInvocationFactory" class="org.springframework.security.context.rmi.ContextPropagatingRemoteInvocationFactory"/>
././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/rmi/ContextPropagatingRemoteInvocationFactory.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/rmi/Con0000644000000000000000000000305311623517156030477 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.context.rmi; import org.aopalliance.intercept.MethodInvocation; import org.springframework.remoting.support.RemoteInvocation; import org.springframework.remoting.support.RemoteInvocationFactory; /** * Called by a client-side instance of org.springframework.remoting.rmi.RmiProxyFactoryBean when it * wishes to create a remote invocation.

Set an instance of this bean against the above class' * remoteInvocationFactory property.

* * @author James Monaghan * @author Ben Alex * @version $Id$ */ public class ContextPropagatingRemoteInvocationFactory implements RemoteInvocationFactory { //~ Methods ======================================================================================================== public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) { return new ContextPropagatingRemoteInvocation(methodInvocation); } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/rmi/ContextPropagatingRemoteInvocation.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/rmi/Con0000644000000000000000000001156611623520776030511 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.context.rmi; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.remoting.support.RemoteInvocation; import org.springframework.security.Authentication; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import java.lang.reflect.InvocationTargetException; /** * The actual {@code RemoteInvocation} that is passed from the client to the server. *

* The principal and credentials information will be extracted from the current * security context and passed to the server as part of the invocation object. *

* To avoid potential serialization-based attacks, this implementation interprets the values as {@code String}s * and creates a {@code UsernamePasswordAuthenticationToken} on the server side to hold them. If a different * token type is required you can override the {@code createAuthenticationRequest} method. * * @author James Monaghan * @author Ben Alex * @author Luke Taylor */ public class ContextPropagatingRemoteInvocation extends RemoteInvocation { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(ContextPropagatingRemoteInvocation.class); //~ Instance fields ================================================================================================ private final String principal; private final String credentials; //~ Constructors =================================================================================================== /** * Constructs the object, storing the principal and credentials extracted from the client-side * security context. * * @param methodInvocation the method to invoke */ public ContextPropagatingRemoteInvocation(MethodInvocation methodInvocation) { super(methodInvocation); Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); if (currentUser != null) { principal = currentUser.getPrincipal().toString(); credentials = currentUser.getCredentials().toString(); } else { principal = credentials = null; } if (logger.isDebugEnabled()) { logger.debug("RemoteInvocation now has principal: " + principal); } } //~ Methods ======================================================================================================== /** * Invoked on the server-side. *

* The transmitted principal and credentials will be used to create an unauthenticated {@code Authentication} * instance for processing by the {@code AuthenticationManager}. * * @param targetObject the target object to apply the invocation to * * @return the invocation result * * @throws NoSuchMethodException if the method name could not be resolved * @throws IllegalAccessException if the method could not be accessed * @throws InvocationTargetException if the method invocation resulted in an exception */ public Object invoke(Object targetObject) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (principal != null) { Authentication request = createAuthenticationRequest(principal, credentials); request.setAuthenticated(false); SecurityContextHolder.getContext().setAuthentication(request); if (logger.isDebugEnabled()) { logger.debug("Set SecurityContextHolder to contain: " + request); } } try { return super.invoke(targetObject); } finally { SecurityContextHolder.clearContext(); if (logger.isDebugEnabled()) { logger.debug("Cleared SecurityContextHolder."); } } } /** * Creates the server-side authentication request object. */ protected Authentication createAuthenticationRequest(String principal, String credentials) { return new UsernamePasswordAuthenticationToken(principal, credentials); } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/ThreadLocalSecurityContextHolderStrategy.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/ThreadL0000644000000000000000000000363011623517156030515 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.context; import org.springframework.util.Assert; /** * A ThreadLocal-based implementation of {@link * org.springframework.security.context.SecurityContextHolderStrategy}. * * @author Ben Alex * @version $Id$ * * @see java.lang.ThreadLocal * @see org.springframework.security.context.HttpSessionContextIntegrationFilter */ public class ThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { //~ Static fields/initializers ===================================================================================== private static ThreadLocal contextHolder = new ThreadLocal(); //~ Methods ======================================================================================================== public void clearContext() { contextHolder.set(null); } public SecurityContext getContext() { if (contextHolder.get() == null) { contextHolder.set(new SecurityContextImpl()); } return (SecurityContext) contextHolder.get(); } public void setContext(SecurityContext context) { Assert.notNull(context, "Only non-null SecurityContext instances are permitted"); contextHolder.set(context); } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/GlobalSecurityContextHolderStrategy.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/GlobalS0000644000000000000000000000360311623517156030515 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.context; import org.springframework.util.Assert; /** * A static field-based implementation of {@link * org.springframework.security.context.SecurityContextHolderStrategy}.

This means that all instances in the JVM share the * same SecurityContext. This is generally useful with rich clients, such as Swing.

* * @author Ben Alex * @version $Id$ */ public class GlobalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { //~ Static fields/initializers ===================================================================================== private static SecurityContext contextHolder; //~ Methods ======================================================================================================== public void clearContext() { contextHolder = null; } public SecurityContext getContext() { if (contextHolder == null) { contextHolder = new SecurityContextImpl(); } return contextHolder; } public void setContext(SecurityContext context) { Assert.notNull(context, "Only non-null SecurityContext instances are permitted"); contextHolder = context; } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/HttpSessionContextIntegrationFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/HttpSes0000644000000000000000000005653611623517156030601 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.context; import java.io.IOException; import java.lang.reflect.Method; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import javax.servlet.http.HttpSession; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import org.springframework.security.AuthenticationTrustResolver; import org.springframework.security.AuthenticationTrustResolverImpl; import org.springframework.security.ui.SpringSecurityFilter; import org.springframework.security.ui.FilterChainOrder; /** * Populates the {@link SecurityContextHolder} with information obtained from * the HttpSession. *

*

* The HttpSession will be queried to retrieve the * SecurityContext that should be stored against the * SecurityContextHolder for the duration of the web request. At * the end of the web request, any updates made to the * SecurityContextHolder will be persisted back to the * HttpSession by this filter. *

*

* If a valid SecurityContext cannot be obtained from the * HttpSession for whatever reason, a fresh * SecurityContext will be created and used instead. The created * object will be of the instance defined by the {@link #setContextClass(Class)} * method (which defaults to {@link org.springframework.security.context.SecurityContextImpl}. *

*

* No HttpSession will be created by this filter if one does not * already exist. If at the end of the web request the HttpSession * does not exist, a HttpSession will only be created if * the current contents of the SecurityContextHolder are not * {@link java.lang.Object#equals(java.lang.Object)} to a new * instance of {@link #setContextClass(Class)}. This avoids needless * HttpSession creation, but automates the storage of changes * made to the SecurityContextHolder. There is one exception to * this rule, that is if the {@link #forceEagerSessionCreation} property is * true, in which case sessions will always be created * irrespective of normal session-minimisation logic (the default is * false, as this is resource intensive and not recommended). *

*

* This filter will only execute once per request, to resolve servlet container * (specifically Weblogic) incompatibilities. *

*

* If for whatever reason no HttpSession should ever be * created (eg this filter is only being used with Basic authentication or * similar clients that will never present the same jsessionid * etc), the {@link #setAllowSessionCreation(boolean)} should be set to * false. Only do this if you really need to conserve server * memory and ensure all classes using the SecurityContextHolder * are designed to have no persistence of the SecurityContext * between web requests. Please note that if {@link #forceEagerSessionCreation} * is true, the allowSessionCreation must also be * true (setting it to false will cause a startup * time error). *

*

* This filter MUST be executed BEFORE any authentication processing mechanisms. * Authentication processing mechanisms (eg BASIC, CAS processing filters etc) * expect the SecurityContextHolder to contain a valid * SecurityContext by the time they execute. *

* * @author Ben Alex * @author Patrick Burleson * @author Luke Taylor * @author Martin Algesten * * @version $Id$ */ public class HttpSessionContextIntegrationFilter extends SpringSecurityFilter implements InitializingBean { //~ Static fields/initializers ===================================================================================== static final String FILTER_APPLIED = "__spring_security_session_integration_filter_applied"; public static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; //~ Instance fields ================================================================================================ private Class contextClass = SecurityContextImpl.class; private Object contextObject; /** * Indicates if this filter can create a HttpSession if * needed (sessions are always created sparingly, but setting this value to * false will prohibit sessions from ever being created). * Defaults to true. Do not set to false if * you are have set {@link #forceEagerSessionCreation} to true, * as the properties would be in conflict. */ private boolean allowSessionCreation = true; /** * Indicates if this filter is required to create a HttpSession * for every request before proceeding through the filter chain, even if the * HttpSession would not ordinarily have been created. By * default this is false, which is entirely appropriate for * most circumstances as you do not want a HttpSession * created unless the filter actually needs one. It is envisaged the main * situation in which this property would be set to true is * if using other filters that depend on a HttpSession * already existing, such as those which need to obtain a session ID. This * is only required in specialised cases, so leave it set to * false unless you have an actual requirement and are * conscious of the session creation overhead. */ private boolean forceEagerSessionCreation = false; /** * Indicates whether the SecurityContext will be cloned from * the HttpSession. The default is to simply reference (ie * the default is false). The default may cause issues if * concurrent threads need to have a different security identity from other * threads being concurrently processed that share the same * HttpSession. In most normal environments this does not * represent an issue, as changes to the security identity in one thread is * allowed to affect the security identitiy in other threads associated with * the same HttpSession. For unusual cases where this is not * permitted, change this value to true and ensure the * {@link #contextClass} is set to a SecurityContext that * implements {@link Cloneable} and overrides the clone() * method. */ private boolean cloneFromHttpSession = false; private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); public boolean isCloneFromHttpSession() { return cloneFromHttpSession; } public void setCloneFromHttpSession(boolean cloneFromHttpSession) { this.cloneFromHttpSession = cloneFromHttpSession; } public HttpSessionContextIntegrationFilter() throws ServletException { this.contextObject = generateNewContext(); } //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { if ((this.contextClass == null) || (!SecurityContext.class.isAssignableFrom(this.contextClass))) { throw new IllegalArgumentException("context must be defined and implement SecurityContext " + "(typically use org.springframework.security.context.SecurityContextImpl; existing class is " + this.contextClass + ")"); } if (forceEagerSessionCreation && !allowSessionCreation) { throw new IllegalArgumentException( "If using forceEagerSessionCreation, you must set allowSessionCreation to also be true"); } contextObject = generateNewContext(); } public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (request.getAttribute(FILTER_APPLIED) != null) { // ensure that filter is only applied once per request chain.doFilter(request, response); return; } HttpSession httpSession = safeGetSession(request, forceEagerSessionCreation); boolean httpSessionExistedAtStartOfRequest = httpSession != null; SecurityContext contextBeforeChainExecution = readSecurityContextFromSession(httpSession); // Make the HttpSession null, as we don't want to keep a reference to it lying // around in case chain.doFilter() invalidates it. httpSession = null; if (contextBeforeChainExecution == null) { contextBeforeChainExecution = generateNewContext(); if (logger.isDebugEnabled()) { logger.debug("New SecurityContext instance will be associated with SecurityContextHolder"); } } else { if (logger.isDebugEnabled()) { logger.debug("Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT to " + "associate with SecurityContextHolder: '" + contextBeforeChainExecution + "'"); } } int contextHashBeforeChainExecution = contextBeforeChainExecution.hashCode(); request.setAttribute(FILTER_APPLIED, Boolean.TRUE); // Create a wrapper that will eagerly update the session with the security context // if anything in the chain does a sendError() or sendRedirect(). // See SEC-398 OnRedirectUpdateSessionResponseWrapper responseWrapper = new OnRedirectUpdateSessionResponseWrapper( response, request, httpSessionExistedAtStartOfRequest, contextHashBeforeChainExecution ); // Proceed with chain try { // This is the only place in this class where SecurityContextHolder.setContext() is called SecurityContextHolder.setContext(contextBeforeChainExecution); chain.doFilter(request, responseWrapper); } finally { // This is the only place in this class where SecurityContextHolder.getContext() is called SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext(); // Crucial removal of SecurityContextHolder contents - do this before anything else. SecurityContextHolder.clearContext(); request.removeAttribute(FILTER_APPLIED); // storeSecurityContextInSession() might already be called by the response wrapper // if something in the chain called sendError() or sendRedirect(). This ensures we only call it // once per request. if ( !responseWrapper.isSessionUpdateDone() ) { storeSecurityContextInSession(contextAfterChainExecution, request, httpSessionExistedAtStartOfRequest, contextHashBeforeChainExecution); } if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder now cleared, as request processing completed"); } } } /** * Gets the security context from the session (if available) and returns it. *

* If the session is null, the context object is null or the context object stored in the session * is not an instance of SecurityContext it will return null. *

* If cloneFromHttpSession is set to true, it will attempt to clone the context object * and return the cloned instance. * * @param httpSession the session obtained from the request. */ private SecurityContext readSecurityContextFromSession(HttpSession httpSession) { if (httpSession == null) { if (logger.isDebugEnabled()) { logger.debug("No HttpSession currently exists"); } return null; } // Session exists, so try to obtain a context from it. Object contextFromSessionObject = httpSession.getAttribute(SPRING_SECURITY_CONTEXT_KEY); if (contextFromSessionObject == null) { if (logger.isDebugEnabled()) { logger.debug("HttpSession returned null object for SPRING_SECURITY_CONTEXT"); } return null; } // We now have the security context object from the session. // Clone if required (see SEC-356) if (cloneFromHttpSession) { Assert.isInstanceOf(Cloneable.class, contextFromSessionObject, "Context must implement Clonable and provide a Object.clone() method"); try { Method m = contextFromSessionObject.getClass().getMethod("clone", new Class[]{}); if (!m.isAccessible()) { m.setAccessible(true); } contextFromSessionObject = m.invoke(contextFromSessionObject, new Object[]{}); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } if (!(contextFromSessionObject instanceof SecurityContext)) { if (logger.isWarnEnabled()) { logger.warn("SPRING_SECURITY_CONTEXT did not contain a SecurityContext but contained: '" + contextFromSessionObject + "'; are you improperly modifying the HttpSession directly " + "(you should always use SecurityContextHolder) or using the HttpSession attribute " + "reserved for this class?"); } return null; } // Everything OK. The only non-null return from this method. return (SecurityContext) contextFromSessionObject; } /** * Stores the supplied security context in the session (if available) and if it has changed since it was * set at the start of the request. If the AuthenticationTrustResolver identifies the current user as * anonymous, then the context will not be stored. * * @param securityContext the context object obtained from the SecurityContextHolder after the request has * been processed by the filter chain. SecurityContextHolder.getContext() cannot be used to obtain * the context as it has already been cleared by the time this method is called. * @param request the request object (used to obtain the session, if one exists). * @param httpSessionExistedAtStartOfRequest indicates whether there was a session in place before the * filter chain executed. If this is true, and the session is found to be null, this indicates that it was * invalidated during the request and a new session will now be created. * @param contextHashBeforeChainExecution the hashcode of the context before the filter chain executed. * The context will only be stored if it has a different hashcode, indicating that the context changed * during the request. * */ private void storeSecurityContextInSession(SecurityContext securityContext, HttpServletRequest request, boolean httpSessionExistedAtStartOfRequest, int contextHashBeforeChainExecution) { HttpSession httpSession = safeGetSession(request, false); if (httpSession == null) { if (httpSessionExistedAtStartOfRequest) { if (logger.isDebugEnabled()) { logger.debug("HttpSession is now null, but was not null at start of request; " + "session was invalidated, so do not create a new session"); } } else { // Generate a HttpSession only if we need to if (!allowSessionCreation) { if (logger.isDebugEnabled()) { logger.debug("The HttpSession is currently null, and the " + "HttpSessionContextIntegrationFilter is prohibited from creating an HttpSession " + "(because the allowSessionCreation property is false) - SecurityContext thus not " + "stored for next request"); } } else if (!contextObject.equals(securityContext)) { if (logger.isDebugEnabled()) { logger.debug("HttpSession being created as SecurityContextHolder contents are non-default"); } httpSession = safeGetSession(request, true); } else { if (logger.isDebugEnabled()) { logger.debug("HttpSession is null, but SecurityContextHolder has not changed from default: ' " + securityContext + "'; not creating HttpSession or storing SecurityContextHolder contents"); } } } } // If HttpSession exists, store current SecurityContextHolder contents but only if // the SecurityContext has actually changed (see JIRA SEC-37) if (httpSession != null && securityContext.hashCode() != contextHashBeforeChainExecution) { // See SEC-766 if (authenticationTrustResolver.isAnonymous(securityContext.getAuthentication())) { if (logger.isDebugEnabled()) { logger.debug("SecurityContext contents are anonymous - context will not be stored in HttpSession. "); } } else { httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, securityContext); if (logger.isDebugEnabled()) { logger.debug("SecurityContext stored to HttpSession: '" + securityContext + "'"); } } } } private HttpSession safeGetSession(HttpServletRequest request, boolean allowCreate) { try { return request.getSession(allowCreate); } catch (IllegalStateException ignored) { return null; } } public SecurityContext generateNewContext() throws ServletException { try { return (SecurityContext) this.contextClass.newInstance(); } catch (InstantiationException ie) { throw new ServletException(ie); } catch (IllegalAccessException iae) { throw new ServletException(iae); } } public boolean isAllowSessionCreation() { return allowSessionCreation; } public void setAllowSessionCreation(boolean allowSessionCreation) { this.allowSessionCreation = allowSessionCreation; } protected Class getContextClass() { return contextClass; } public void setContextClass(Class secureContext) { this.contextClass = secureContext; } public boolean isForceEagerSessionCreation() { return forceEagerSessionCreation; } public void setForceEagerSessionCreation(boolean forceEagerSessionCreation) { this.forceEagerSessionCreation = forceEagerSessionCreation; } public int getOrder() { return FilterChainOrder.HTTP_SESSION_CONTEXT_FILTER; } //~ Inner Classes ================================================================================================== /** * Wrapper that is applied to every request to update the HttpSession with * the SecurityContext when a sendError() or sendRedirect * happens. See SEC-398. The class contains the fields needed to call * storeSecurityContextInSession() */ private class OnRedirectUpdateSessionResponseWrapper extends HttpServletResponseWrapper { HttpServletRequest request; boolean httpSessionExistedAtStartOfRequest; int contextHashBeforeChainExecution; // Used to ensure storeSecurityContextInSession() is only // called once. boolean sessionUpdateDone = false; /** * Takes the parameters required to call storeSecurityContextInSession() in * addition to the response object we are wrapping. * @see HttpSessionContextIntegrationFilter#storeSecurityContextInSession(SecurityContext, HttpServletRequest, boolean, int) */ public OnRedirectUpdateSessionResponseWrapper(HttpServletResponse response, HttpServletRequest request, boolean httpSessionExistedAtStartOfRequest, int contextHashBeforeChainExecution) { super(response); this.request = request; this.httpSessionExistedAtStartOfRequest = httpSessionExistedAtStartOfRequest; this.contextHashBeforeChainExecution = contextHashBeforeChainExecution; } /** * Makes sure the session is updated before calling the * superclass sendError() */ public void sendError(int sc) throws IOException { doSessionUpdate(); super.sendError(sc); } /** * Makes sure the session is updated before calling the * superclass sendError() */ public void sendError(int sc, String msg) throws IOException { doSessionUpdate(); super.sendError(sc, msg); } /** * Makes sure the session is updated before calling the * superclass sendRedirect() */ public void sendRedirect(String location) throws IOException { doSessionUpdate(); super.sendRedirect(location); } /** * Calls storeSecurityContextInSession() */ private void doSessionUpdate() { if (sessionUpdateDone) { return; } SecurityContext securityContext = SecurityContextHolder.getContext(); storeSecurityContextInSession(securityContext, request, httpSessionExistedAtStartOfRequest, contextHashBeforeChainExecution); sessionUpdateDone = true; } /** * Tells if the response wrapper has called * storeSecurityContextInSession(). */ public boolean isSessionUpdateDone() { return sessionUpdateDone; } } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/SecurityContextHolder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/Securit0000644000000000000000000001345711623517156030620 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.context; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Constructor; /** * Associates a given {@link SecurityContext} with the current execution thread.

This class provides a series of * static methods that delegate to an instance of {@link org.springframework.security.context.SecurityContextHolderStrategy}. The * purpose of the class is to provide a convenient way to specify the strategy that should be used for a given JVM. * This is a JVM-wide setting, since everything in this class is static to facilitate ease of use in * calling code.

*

To specify which strategy should be used, you must provide a mode setting. A mode setting is one of the * three valid MODE_ settings defined as static final fields, or a fully qualified classname * to a concrete implementation of {@link org.springframework.security.context.SecurityContextHolderStrategy} that provides a * public no-argument constructor.

*

There are two ways to specify the desired strategy mode String. The first is to specify it via * the system property keyed on {@link #SYSTEM_PROPERTY}. The second is to call {@link #setStrategyName(String)} * before using the class. If neither approach is used, the class will default to using {@link #MODE_THREADLOCAL}, * which is backwards compatible, has fewer JVM incompatibilities and is appropriate on servers (whereas {@link * #MODE_GLOBAL} is definitely inappropriate for server use).

* * @author Ben Alex * @version $Id$ * * @see org.springframework.security.context.HttpSessionContextIntegrationFilter */ public class SecurityContextHolder { //~ Static fields/initializers ===================================================================================== public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL"; public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL"; public static final String MODE_GLOBAL = "MODE_GLOBAL"; public static final String SYSTEM_PROPERTY = "spring.security.strategy"; private static String strategyName = System.getProperty(SYSTEM_PROPERTY); private static SecurityContextHolderStrategy strategy; private static int initializeCount = 0; static { initialize(); } //~ Methods ======================================================================================================== /** * Explicitly clears the context value from the current thread. */ public static void clearContext() { strategy.clearContext(); } /** * Obtain the current SecurityContext. * * @return the security context (never null) */ public static SecurityContext getContext() { return strategy.getContext(); } /** * Primarily for troubleshooting purposes, this method shows how many times the class has reinitialized its * SecurityContextHolderStrategy. * * @return the count (should be one unless you've called {@link #setStrategyName(String)} to switch to an alternate * strategy. */ public static int getInitializeCount() { return initializeCount; } private static void initialize() { if ((strategyName == null) || "".equals(strategyName)) { // Set default strategyName = MODE_THREADLOCAL; } if (strategyName.equals(MODE_THREADLOCAL)) { strategy = new ThreadLocalSecurityContextHolderStrategy(); } else if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) { strategy = new InheritableThreadLocalSecurityContextHolderStrategy(); } else if (strategyName.equals(MODE_GLOBAL)) { strategy = new GlobalSecurityContextHolderStrategy(); } else { // Try to load a custom strategy try { Class clazz = Class.forName(strategyName); Constructor customStrategy = clazz.getConstructor(new Class[] {}); strategy = (SecurityContextHolderStrategy) customStrategy.newInstance(new Object[] {}); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } initializeCount++; } /** * Associates a new SecurityContext with the current thread of execution. * * @param context the new SecurityContext (may not be null) */ public static void setContext(SecurityContext context) { strategy.setContext(context); } /** * Changes the preferred strategy. Do NOT call this method more than once for a given JVM, as it * will reinitialize the strategy and adversely affect any existing threads using the old strategy. * * @param strategyName the fully qualified classname of the strategy that should be used. */ public static void setStrategyName(String strategyName) { SecurityContextHolder.strategyName = strategyName; initialize(); } public String toString() { return "SecurityContextHolder[strategy='" + strategyName + "'; initializeCount=" + initializeCount + "]"; } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/SecurityContextImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/Securit0000644000000000000000000000477211623517156030620 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.context; import org.springframework.security.Authentication; /** * Base implementation of {@link SecurityContext}.

Used by default by {@link SecurityContextHolder} and {@link * HttpSessionContextIntegrationFilter}.

* * @author Ben Alex * @version $Id$ */ public class SecurityContextImpl implements SecurityContext { //~ Instance fields ================================================================================================ private Authentication authentication; //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (obj instanceof SecurityContextImpl) { SecurityContextImpl test = (SecurityContextImpl) obj; if ((this.getAuthentication() == null) && (test.getAuthentication() == null)) { return true; } if ((this.getAuthentication() != null) && (test.getAuthentication() != null) && this.getAuthentication().equals(test.getAuthentication())) { return true; } } return false; } public Authentication getAuthentication() { return authentication; } public int hashCode() { if (this.authentication == null) { return -1; } else { return this.authentication.hashCode(); } } public void setAuthentication(Authentication authentication) { this.authentication = authentication; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString()); if (this.authentication == null) { sb.append(": Null authentication"); } else { sb.append(": Authentication: ").append(this.authentication); } return sb.toString(); } } ././@LongLink0000000000000000000000000000022600000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/InheritableThreadLocalSecurityContextHolderStrategy.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/context/Inherit0000644000000000000000000000367211623517156030602 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.context; import org.springframework.util.Assert; /** * An InheritableThreadLocal-based implementation of {@link * org.springframework.security.context.SecurityContextHolderStrategy}. * * @author Ben Alex * @version $Id$ * * @see java.lang.ThreadLocal * @see org.springframework.security.context.HttpSessionContextIntegrationFilter */ public class InheritableThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { //~ Static fields/initializers ===================================================================================== private static ThreadLocal contextHolder = new InheritableThreadLocal(); //~ Methods ======================================================================================================== public void clearContext() { contextHolder.set(null); } public SecurityContext getContext() { if (contextHolder.get() == null) { contextHolder.set(new SecurityContextImpl()); } return (SecurityContext) contextHolder.get(); } public void setContext(SecurityContext context) { Assert.notNull(context, "Only non-null SecurityContext instances are permitted"); contextHolder.set(context); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/package.html0000644000000000000000000000012511623517156030040 0ustar Provides core Spring Security interfaces and classes. ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_zh_CN.propertiesspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_zh_CN.0000644000000000000000000001273611623517156030463 0ustar AuthByAdapterProvider.incorrectKey=\u5c55\u793a\u7684AuthByAdapter\u5b9e\u73b0\u4e0d\u542b\u6709\u9884\u671f\u7684key BasicAclEntryAfterInvocationProvider.noPermission=\u7ed9\u5b9a\u7684Authentication\u5bf9\u8c61({0})\u6839\u672c\u65e0\u6743\u64cd\u63a7\u9886\u57df\u5bf9\u8c61({1}) BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentication\u5bf9\u8c61({0})\u786e\u5b9e\u542b\u6709ACL\u6743\u9650\uff0c\u4f46\u5e76\u4e0d\u662f\u76ee\u6807\u9886\u57df\u5bf9\u8c61\u6240\u8981\u6c42\u7684({1}) ConcurrentSessionControllerImpl.exceededAllowed=\u5df2\u7ecf\u8d85\u8fc7\u4e86\u5f53\u524d\u4e3b\u4f53({0})\u88ab\u5141\u8bb8\u7684\u6700\u5927\u4f1a\u8bdd\u6570\u91cf ProviderManager.providerNotFound=\u672a\u67e5\u627e\u5230\u9488\u5bf9{0}\u7684AuthenticationProvider AnonymousAuthenticationProvider.incorrectKey=\u5c55\u793a\u7684AnonymousAuthenticationToken\u4e0d\u542b\u6709\u9884\u671f\u7684key CasAuthenticationProvider.incorrectKey=\u5c55\u793a\u7684CasAuthenticationToken\u4e0d\u542b\u6709\u9884\u671f\u7684key CasAuthenticationProvider.noServiceTicket=\u672a\u80fd\u591f\u6b63\u786e\u63d0\u4f9b\u5f85\u9a8c\u8bc1\u7684CAS\u670d\u52a1\u7968\u6839 NamedCasProxyDecider.untrusted=\u4ee3\u7406({0})\u4e0d\u53d7\u4fe1\u4efb RejectProxyTickets.reject=Proxy\u7968\u6839\u88ab\u62d2\u7edd AbstractSecurityInterceptor.authenticationNotFound=\u672a\u5728SecurityContext\u4e2d\u67e5\u627e\u5230\u8ba4\u8bc1\u5bf9\u8c61 AbstractUserDetailsAuthenticationProvider.onlySupports=\u4ec5\u4ec5\u652f\u6301UsernamePasswordAuthenticationToken AbstractUserDetailsAuthenticationProvider.locked=\u7528\u6237\u5e10\u53f7\u5df2\u88ab\u9501\u5b9a AbstractUserDetailsAuthenticationProvider.disabled=\u7528\u6237\u5df2\u5931\u6548 AbstractUserDetailsAuthenticationProvider.expired=\u7528\u6237\u5e10\u53f7\u5df2\u8fc7\u671f AbstractUserDetailsAuthenticationProvider.credentialsExpired=\u7528\u6237\u51ed\u8bc1\u5df2\u8fc7\u671f AbstractUserDetailsAuthenticationProvider.badCredentials=\u574f\u7684\u51ed\u8bc1 X509AuthenticationProvider.certificateNull=\u672a\u63d0\u4f9b\u8bc1\u4e66 DaoX509AuthoritiesPopulator.noMatching=\u672a\u5728subjectDN: {0}\u4e2d\u627e\u5230\u5339\u914d\u7684\u6a21\u5f0f RememberMeAuthenticationProvider.incorrectKey=\u5c55\u793aRememberMeAuthenticationToken\u4e0d\u542b\u6709\u9884\u671f\u7684key RunAsImplAuthenticationProvider.incorrectKey=\u5c55\u793a\u7684RunAsUserToken\u4e0d\u542b\u6709\u9884\u671f\u7684key DigestProcessingFilter.missingMandatory=\u9057\u6f0f\u4e86\u5fc5\u987b\u7ed9\u5b9a\u7684\u6458\u8981\u53d6\u503c; \u63a5\u6536\u5230\u7684\u5934\u4fe1\u606f\u4e3a{0} DigestProcessingFilter.missingAuth=\u9057\u6f0f\u4e86\u9488\u5bf9'auth' QOP\u7684\u3001\u5fc5\u987b\u7ed9\u5b9a\u7684\u6458\u8981\u53d6\u503c; \u63a5\u6536\u5230\u7684\u5934\u4fe1\u606f\u4e3a{0} DigestProcessingFilter.incorrectRealm=\u54cd\u5e94\u7ed3\u679c\u4e2d\u7684Realm\u540d\u5b57({0})\u540c\u7cfb\u7edf\u6307\u5b9a\u7684Realm\u540d\u5b57({1})\u4e0d\u543b\u5408 DigestProcessingFilter.nonceExpired=Nonce\u5df2\u7ecf\u8fc7\u671f/\u8d85\u65f6 DigestProcessingFilter.nonceEncoding=Nonce\u672a\u7ecf\u8fc7Base64\u7f16\u7801; \u76f8\u5e94\u7684nonce\u53d6\u503c\u4e3a {0} DigestProcessingFilter.nonceNotTwoTokens=Nonce\u5e94\u8be5\u7531\u4e24\u90e8\u5206\u53d6\u503c\u6784\u6210\uff0c\u4f46\u7ed3\u679c\u5374\u662f{0} DigestProcessingFilter.nonceNotNumeric=Nonce\u4ee4\u724c\u7684\u7b2c1\u90e8\u5206\u5e94\u8be5\u662f\u6570\u5b57\uff0c\u4f46\u7ed3\u679c\u5374\u662f{0} DigestProcessingFilter.nonceCompromised=Nonce\u4ee4\u724c\u5df2\u7ecf\u5b58\u5728\u95ee\u9898\u4e86\uff0c{0} DigestProcessingFilter.usernameNotFound=\u7528\u6237\u540d{0}\u672a\u627e\u5230 DigestProcessingFilter.incorrectResponse=\u9519\u8bef\u7684\u54cd\u5e94\u7ed3\u679c JdbcDaoImpl.notFound=\u672a\u627e\u5230\u7528\u6237{0} JdbcDaoImpl.noAuthority=\u6ca1\u6709\u4e3a\u7528\u6237{0}\u6307\u5b9a\u89d2\u8272 SwitchUserProcessingFilter.noCurrentUser=\u4e0d\u5b58\u5728\u5f53\u524d\u7528\u6237 SwitchUserProcessingFilter.noOriginalAuthentication=\u4e0d\u80fd\u591f\u67e5\u627e\u5230\u539f\u5148\u7684\u5df2\u8ba4\u8bc1\u5bf9\u8c61 SwitchUserProcessingFilter.usernameNotFound=\u7528\u6237\u540d{0}\u672a\u627e\u5230 SwitchUserProcessingFilter.locked=\u7528\u6237\u5e10\u53f7\u5df2\u88ab\u9501\u5b9a SwitchUserProcessingFilter.disabled=\u7528\u6237\u5df2\u5931\u6548 SwitchUserProcessingFilter.expired=\u7528\u6237\u5e10\u53f7\u5df2\u8fc7\u671f SwitchUserProcessingFilter.credentialsExpired=\u7528\u6237\u51ed\u8bc1\u5df2\u8fc7\u671f AbstractAccessDecisionManager.accessDenied=\u4e0d\u5141\u8bb8\u8bbf\u95ee LdapAuthenticationProvider.emptyUsername=\u7528\u6237\u540d\u4e0d\u5141\u8bb8\u4e3a\u7a7a LdapAuthenticationProvider.emptyPassword=\u574f\u7684\u51ed\u8bc1 DefaultIntitalDirContextFactory.communicationFailure=\u4e0d\u80fd\u591f\u8fde\u63a5\u5230LDAP\u670d\u52a1\u5668 DefaultIntitalDirContextFactory.badCredentials=\u574f\u7684\u51ed\u8bc1 DefaultIntitalDirContextFactory.unexpectedException=\u7531\u4e8e\u672a\u9884\u671f\u5f02\u5e38\u800c\u4e0d\u80fd\u591f\u83b7\u5f97InitialDirContext PasswordComparisonAuthenticator.badCredentials=\u574f\u7684\u51ed\u8bc1 BindAuthenticator.badCredentials=\u574f\u7684\u51ed\u8bc1 BindAuthenticator.failedToLoadAttributes=\u574f\u7684\u51ed\u8bc1 UserDetailsService.locked=\u7528\u6237\u5e10\u53f7\u5df2\u88ab\u9501\u5b9a UserDetailsService.disabled=\u7528\u6237\u5df2\u5931\u6548 UserDetailsService.expired=\u7528\u6237\u5e10\u53f7\u5df2\u8fc7\u671f UserDetailsService.credentialsExpired=\u7528\u6237\u51ed\u8bc1\u5df2\u8fc7\u671f ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ConfigAttribute.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ConfigAttribute0000644000000000000000000000471511623517156030604 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; import java.io.Serializable; /** * Stores a security system related configuration attribute. * *

* When an {@link org.springframework.security.intercept.AbstractSecurityInterceptor} * is setup, a list of configuration attributes is defined for secure object * patterns. These configuration attributes have special meaning to a {@link * RunAsManager}, {@link AccessDecisionManager} or * AccessDecisionManager delegate. *

* *

* Stored at runtime with other ConfigAttributes for the same * secure object target within a {@link ConfigAttributeDefinition}. *

* * @author Ben Alex * @version $Id$ */ public interface ConfigAttribute extends Serializable { //~ Methods ======================================================================================================== /** * If the ConfigAttribute can be represented as a String and that * String is sufficient in precision to be relied upon as a configuration parameter by a {@link * RunAsManager}, {@link AccessDecisionManager} or AccessDecisionManager delegate, this method should * return such a String.

If the ConfigAttribute cannot be expressed with * sufficient precision as a String, null should be returned. Returning * null will require any relying classes to specifically support the ConfigAttribute * implementation, so returning null should be avoided unless actually required.

* * @return a representation of the configuration attribute (or null if the configuration attribute * cannot be expressed as a String with sufficient precision). */ String getAttribute(); } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/GrantedAuthoritiesContainerImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/GrantedAuthorit0000644000000000000000000000150411623517156030610 0ustar package org.springframework.security; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.springframework.util.Assert; public class GrantedAuthoritiesContainerImpl implements MutableGrantedAuthoritiesContainer { private List authorities; public void setGrantedAuthorities(GrantedAuthority[] newAuthorities) { this.authorities = new ArrayList(newAuthorities.length); authorities.addAll(Arrays.asList(newAuthorities)); } public GrantedAuthority[] getGrantedAuthorities() { Assert.notNull(authorities, "Granted authorities have not been set"); return (GrantedAuthority[]) authorities.toArray(new GrantedAuthority[authorities.size()]); } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("Authorities: ").append(authorities); return sb.toString(); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ConfigAttributeEditor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ConfigAttribute0000644000000000000000000000301611623517156030575 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; import org.springframework.util.StringUtils; import java.beans.PropertyEditorSupport; /** * A property editor that can create a populated {@link ConfigAttributeDefinition} from a comma separated list of * values. *

* Trims preceding and trailing spaces from presented command separated tokens, as this can be a source * of hard-to-spot configuration issues for end users. * * @author Ben Alex * @version $Id$ */ public class ConfigAttributeEditor extends PropertyEditorSupport { //~ Methods ======================================================================================================== public void setAsText(String s) throws IllegalArgumentException { if (StringUtils.hasText(s)) { setValue(new ConfigAttributeDefinition(StringUtils.commaDelimitedListToStringArray(s))); } else { setValue(null); } } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthenticationCredentialsNotFoundException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthenticationC0000644000000000000000000000324011623517156030565 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Thrown if an authentication request is rejected because there is no {@link Authentication} object in the {@link * org.springframework.security.context.SecurityContext SecurityContext}. * * @author Ben Alex * @version $Id$ */ public class AuthenticationCredentialsNotFoundException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs an AuthenticationCredentialsNotFoundException * with the specified message. * * @param msg the detail message */ public AuthenticationCredentialsNotFoundException(String msg) { super(msg); } /** * Constructs an AuthenticationCredentialsNotFoundException * with the specified message and root cause. * * @param msg the detail message * @param t root cause */ public AuthenticationCredentialsNotFoundException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AccountStatusException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AccountStatusEx0000644000000000000000000000110511623517156030576 0ustar package org.springframework.security; /** * Base class for authentication exceptions which are caused by a particular * user account status (locked, disabled etc). * * @author Luke Taylor * @version $Id$ */ public abstract class AccountStatusException extends AuthenticationException { public AccountStatusException(String msg) { super(msg); } public AccountStatusException(String msg, Throwable t) { super(msg, t); } protected AccountStatusException(String msg, Object extraInformation) { super(msg, extraInformation); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/0000755000000000000000000000000011623517156026702 5ustar ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000755000000000000000000000000011623517156030607 5ustar ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/LoggerListener.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000566511623517156030625 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.util.ClassUtils; /** * Outputs authentication-related application events to Commons Logging.

All authentication events are logged at * the warning level.

* * @author Ben Alex * @version $Id$ */ public class LoggerListener implements ApplicationListener { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(LoggerListener.class); /** If set to true, {@link InteractiveAuthenticationSuccessEvent} will be logged (defaults to true) */ private boolean logInteractiveAuthenticationSuccessEvents = true; //~ Methods ======================================================================================================== public void onApplicationEvent(ApplicationEvent event) { if (event instanceof AbstractAuthenticationEvent) { AbstractAuthenticationEvent authEvent = (AbstractAuthenticationEvent) event; if (!logInteractiveAuthenticationSuccessEvents && authEvent instanceof InteractiveAuthenticationSuccessEvent) { return; } if (logger.isWarnEnabled()) { String message = "Authentication event " + ClassUtils.getShortName(authEvent.getClass()) + ": " + authEvent.getAuthentication().getName() + "; details: " + authEvent.getAuthentication().getDetails(); if (event instanceof AbstractAuthenticationFailureEvent) { message = message + "; exception: " + ((AbstractAuthenticationFailureEvent) event).getException().getMessage(); } logger.warn(message); } } } public boolean isLogInteractiveAuthenticationSuccessEvents() { return logInteractiveAuthenticationSuccessEvents; } public void setLogInteractiveAuthenticationSuccessEvents( boolean logInteractiveAuthenticationSuccessEvents) { this.logInteractiveAuthenticationSuccessEvents = logInteractiveAuthenticationSuccessEvents; } } ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AuthenticationFailureLockedEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000245611623517156030620 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; /** * Application event which indicates authentication failure due to the user's account having been locked. * * @author Ben Alex * @version $Id$ */ public class AuthenticationFailureLockedEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureLockedEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000022100000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AuthenticationFailureExpiredEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000245411623517156030616 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; /** * Application event which indicates authentication failure due to the user's account having expired. * * @author Ben Alex * @version $Id$ */ public class AuthenticationFailureExpiredEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureExpiredEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AuthenticationSuccessEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000220611623517156030611 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; /** * Application event which indicates successful authentication. * * @author Ben Alex * @version $Id$ */ public class AuthenticationSuccessEvent extends AbstractAuthenticationEvent { //~ Constructors =================================================================================================== public AuthenticationSuccessEvent(Authentication authentication) { super(authentication); } } ././@LongLink0000000000000000000000000000023200000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AuthenticationFailureProviderNotFoundEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000257211623517156030617 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; /** * Application event which indicates authentication failure due to there being no registered * AuthenticationProvider that can process the request. * * @author Ben Alex * @version $Id$ */ public class AuthenticationFailureProviderNotFoundEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureProviderNotFoundEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AuthenticationFailureDisabledEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000245611623517156030620 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; /** * Application event which indicates authentication failure due to the user's account being disabled. * * @author Ben Alex * @version $Id$ */ public class AuthenticationFailureDisabledEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureDisabledEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000043211623517156030610 0ustar Enables events to be published to the Spring application context.

The ProviderManager automatically publishes events to the application context. These events are received by all registered Spring ApplicationListeners.

././@LongLink0000000000000000000000000000023000000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AuthenticationFailureBadCredentialsEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000247411623517156030620 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; /** * Application event which indicates authentication failure due to invalid credentials being presented. * * @author Ben Alex * @version $Id$ */ public class AuthenticationFailureBadCredentialsEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureBadCredentialsEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AuthenticationSwitchUserEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000345011623517156030613 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.security.userdetails.UserDetails; /** * Application event which indicates that a user context switch. * * @author Mark St.Godard * @version $Id$ */ public class AuthenticationSwitchUserEvent extends AbstractAuthenticationEvent { //~ Instance fields ================================================================================================ private UserDetails targetUser; //~ Constructors =================================================================================================== /** * Switch user context event constructor * * @param authentication The current Authentication object * @param targetUser The target user */ public AuthenticationSwitchUserEvent(Authentication authentication, UserDetails targetUser) { super(authentication); this.targetUser = targetUser; } //~ Methods ======================================================================================================== public UserDetails getTargetUser() { return targetUser; } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AbstractAuthenticationFailureEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000344511623517156030617 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.util.Assert; /** * Abstract application event which indicates authentication failure for some reason. * * @author Ben Alex * @version $Id$ */ public abstract class AbstractAuthenticationFailureEvent extends AbstractAuthenticationEvent { //~ Instance fields ================================================================================================ private AuthenticationException exception; //~ Constructors =================================================================================================== public AbstractAuthenticationFailureEvent(Authentication authentication, AuthenticationException exception) { super(authentication); Assert.notNull(exception, "AuthenticationException is required"); this.exception = exception; } //~ Methods ======================================================================================================== public AuthenticationException getException() { return exception; } } ././@LongLink0000000000000000000000000000022500000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/InteractiveAuthenticationSuccessEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000365111623517156030616 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.util.Assert; /** * Indicates an interactive authentication was successful.

The ApplicationEvent's * source will be the Authentication object.

* * @author Ben Alex * @version $Id$ */ public class InteractiveAuthenticationSuccessEvent extends AbstractAuthenticationEvent { //~ Instance fields ================================================================================================ private Class generatedBy; //~ Constructors =================================================================================================== public InteractiveAuthenticationSuccessEvent(Authentication authentication, Class generatedBy) { super(authentication); Assert.notNull(generatedBy); this.generatedBy = generatedBy; } //~ Methods ======================================================================================================== /** * Getter for the Class that generated this event. This can be useful for generating * additional logging information. * * @return the class */ public Class getGeneratedBy() { return generatedBy; } } ././@LongLink0000000000000000000000000000023200000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AuthenticationFailureServiceExceptionEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000255011623517156030613 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; /** * Application event which indicates authentication failure due to there being a problem internal to the * AuthenticationManager. * * @author Ben Alex * @version $Id$ */ public class AuthenticationFailureServiceExceptionEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureServiceExceptionEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000023400000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AuthenticationFailureCredentialsExpiredEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000250611623517156030614 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; /** * Application event which indicates authentication failure due to the user's credentials having expired. * * @author Ben Alex * @version $Id$ */ public class AuthenticationFailureCredentialsExpiredEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureCredentialsExpiredEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000023000000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AuthenticationFailureProxyUntrustedEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000252711623517156030617 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; /** * Application event which indicates authentication failure due to the CAS user's ticket being generated by an * untrusted proxy. * * @author Ben Alex * @version $Id$ */ public class AuthenticationFailureProxyUntrustedEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureProxyUntrustedEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000023100000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AuthenticationFailureConcurrentLoginEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000253211623517156030613 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; /** * Application event which indicates authentication failure due to the user attempting to login to too many * concurrent sessions. * * @author Ben Alex * @version $Id$ */ public class AuthenticationFailureConcurrentLoginEvent extends AbstractAuthenticationFailureEvent { //~ Constructors =================================================================================================== public AuthenticationFailureConcurrentLoginEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentication/AbstractAuthenticationEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authentic0000644000000000000000000000332211623517156030611 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authentication; import org.springframework.security.Authentication; import org.springframework.context.ApplicationEvent; /** * Represents an application authentication event.

The ApplicationEvent's source will * be the Authentication object.

* * @author Ben Alex * @version $Id$ */ public abstract class AbstractAuthenticationEvent extends ApplicationEvent { //~ Constructors =================================================================================================== public AbstractAuthenticationEvent(Authentication authentication) { super(authentication); } //~ Methods ======================================================================================================== /** * Getters for the Authentication request that caused the event. Also available from * super.getSource(). * * @return the authentication request */ public Authentication getAuthentication() { return (Authentication) super.getSource(); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authorization/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authoriza0000755000000000000000000000000011623517156030631 5ustar ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authorization/LoggerListener.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authoriza0000644000000000000000000000664611623517156030647 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authorization; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; /** * Outputs interceptor-related application events to Commons Logging. *

* All failures are logged at the warning level, with success events logged at the information level, * and public invocation events logged at the debug level. *

* * @author Ben Alex * @version $Id$ */ public class LoggerListener implements ApplicationListener { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(LoggerListener.class); //~ Methods ======================================================================================================== public void onApplicationEvent(ApplicationEvent event) { if (event instanceof AuthenticationCredentialsNotFoundEvent) { AuthenticationCredentialsNotFoundEvent authEvent = (AuthenticationCredentialsNotFoundEvent) event; if (logger.isWarnEnabled()) { logger.warn("Security interception failed due to: " + authEvent.getCredentialsNotFoundException() + "; secure object: " + authEvent.getSource() + "; configuration attributes: " + authEvent.getConfigAttributeDefinition()); } } if (event instanceof AuthorizationFailureEvent) { AuthorizationFailureEvent authEvent = (AuthorizationFailureEvent) event; if (logger.isWarnEnabled()) { logger.warn("Security authorization failed due to: " + authEvent.getAccessDeniedException() + "; authenticated principal: " + authEvent.getAuthentication() + "; secure object: " + authEvent.getSource() + "; configuration attributes: " + authEvent.getConfigAttributeDefinition()); } } if (event instanceof AuthorizedEvent) { AuthorizedEvent authEvent = (AuthorizedEvent) event; if (logger.isInfoEnabled()) { logger.info("Security authorized for authenticated principal: " + authEvent.getAuthentication() + "; secure object: " + authEvent.getSource() + "; configuration attributes: " + authEvent.getConfigAttributeDefinition()); } } if (event instanceof PublicInvocationEvent) { PublicInvocationEvent authEvent = (PublicInvocationEvent) event; if (logger.isInfoEnabled()) { logger.info("Security interception not required for public secure object: " + authEvent.getSource()); } } } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authorization/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authoriza0000644000000000000000000000015311623517156030632 0ustar Provides support objects for security event interception (ie authorization). ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authorization/AbstractAuthorizationEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authoriza0000644000000000000000000000241111623517156030631 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authorization; import org.springframework.context.ApplicationEvent; /** * Abstract superclass for all security interception related events. * * @author Ben Alex * @version $Id$ */ public abstract class AbstractAuthorizationEvent extends ApplicationEvent { //~ Constructors =================================================================================================== /** * Construct the event, passing in the secure object being intercepted. * * @param secureObject the secure object */ public AbstractAuthorizationEvent(Object secureObject) { super(secureObject); } } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authorization/PublicInvocationEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authoriza0000644000000000000000000000302611623517156030634 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authorization; /** * Event that is generated whenever a public secure object is invoked.

A public secure object is a secure object * that has no ConfigAttributeDefinition defined. A public secure object will not cause the * SecurityContextHolder to be inspected or authenticated, and no authorization will take place.

*

Published just before the secure object attempts to proceed.

* * @author Ben Alex * @version $Id$ */ public class PublicInvocationEvent extends AbstractAuthorizationEvent { //~ Constructors =================================================================================================== /** * Construct the event, passing in the public secure object. * * @param secureObject the public secure object */ public PublicInvocationEvent(Object secureObject) { super(secureObject); } } ././@LongLink0000000000000000000000000000022500000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authorization/AuthenticationCredentialsNotFoundEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authoriza0000644000000000000000000000532311623517156030636 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authorization; import org.springframework.security.AuthenticationCredentialsNotFoundException; import org.springframework.security.ConfigAttributeDefinition; /** * Indicates a secure object invocation failed because the Authentication could not be obtained from * the SecurityContextHolder. * * @author Ben Alex * @version $Id$ */ public class AuthenticationCredentialsNotFoundEvent extends AbstractAuthorizationEvent { //~ Instance fields ================================================================================================ private AuthenticationCredentialsNotFoundException credentialsNotFoundException; private ConfigAttributeDefinition configAttributeDefinition; //~ Constructors =================================================================================================== /** * Construct the event. * * @param secureObject the secure object * @param configAttribs that apply to the secure object * @param credentialsNotFoundException exception returned to the caller * (contains reason) * * @throws IllegalArgumentException DOCUMENT ME! */ public AuthenticationCredentialsNotFoundEvent(Object secureObject, ConfigAttributeDefinition configAttribs, AuthenticationCredentialsNotFoundException credentialsNotFoundException) { super(secureObject); if ((configAttribs == null) || (credentialsNotFoundException == null)) { throw new IllegalArgumentException("All parameters are required and cannot be null"); } this.configAttributeDefinition = configAttribs; this.credentialsNotFoundException = credentialsNotFoundException; } //~ Methods ======================================================================================================== public ConfigAttributeDefinition getConfigAttributeDefinition() { return configAttributeDefinition; } public AuthenticationCredentialsNotFoundException getCredentialsNotFoundException() { return credentialsNotFoundException; } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authorization/AuthorizedEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authoriza0000644000000000000000000000461611623517156030642 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authorization; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttributeDefinition; /** * Event indicating a secure object was invoked successfully.

Published just before the secure object attempts to * proceed.

* * @author Ben Alex * @version $Id$ */ public class AuthorizedEvent extends AbstractAuthorizationEvent { //~ Instance fields ================================================================================================ private Authentication authentication; private ConfigAttributeDefinition configAttributeDefinition; //~ Constructors =================================================================================================== /** * Construct the event. * * @param secureObject the secure object * @param configAttribs that apply to the secure object * @param authentication that successfully called the secure object * * @throws IllegalArgumentException DOCUMENT ME! */ public AuthorizedEvent(Object secureObject, ConfigAttributeDefinition configAttribs, Authentication authentication) { super(secureObject); if ((configAttribs == null) || (authentication == null)) { throw new IllegalArgumentException("All parameters are required and cannot be null"); } this.configAttributeDefinition = configAttribs; this.authentication = authentication; } //~ Methods ======================================================================================================== public Authentication getAuthentication() { return authentication; } public ConfigAttributeDefinition getConfigAttributeDefinition() { return configAttributeDefinition; } } ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authorization/AuthorizationFailureEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/event/authoriza0000644000000000000000000000621011623517156030632 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.event.authorization; import org.springframework.security.AccessDeniedException; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttributeDefinition; /** * Indicates a secure object invocation failed because the principal could not * be authorized for the request. * *

This event might be thrown as a result of either an * {@link org.springframework.security.AccessDecisionManager AccessDecisionManager} or an * {@link org.springframework.security.AfterInvocationManager AfterInvocationManager}. * * @author Ben Alex * @version $Id$ */ public class AuthorizationFailureEvent extends AbstractAuthorizationEvent { //~ Instance fields ================================================================================================ private AccessDeniedException accessDeniedException; private Authentication authentication; private ConfigAttributeDefinition configAttributeDefinition; //~ Constructors =================================================================================================== /** * Construct the event. * * @param secureObject the secure object * @param configAttribs that apply to the secure object * @param authentication that was found in the SecurityContextHolder * @param accessDeniedException that was returned by the * AccessDecisionManager * * @throws IllegalArgumentException if any null arguments are presented. */ public AuthorizationFailureEvent(Object secureObject, ConfigAttributeDefinition configAttribs, Authentication authentication, AccessDeniedException accessDeniedException) { super(secureObject); if ((configAttribs == null) || (authentication == null) || (accessDeniedException == null)) { throw new IllegalArgumentException("All parameters are required and cannot be null"); } this.configAttributeDefinition = configAttribs; this.authentication = authentication; this.accessDeniedException = accessDeniedException; } //~ Methods ======================================================================================================== public AccessDeniedException getAccessDeniedException() { return accessDeniedException; } public Authentication getAuthentication() { return authentication; } public ConfigAttributeDefinition getConfigAttributeDefinition() { return configAttributeDefinition; } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/0000755000000000000000000000000011623517156027026 5ustar ././@LongLink0000000000000000000000000000022500000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/CustomAuthenticationProviderBeanDefinitionDecorator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/CustomAu0000644000000000000000000000152311623517156030512 0ustar package org.springframework.security.config; import org.springframework.beans.factory.xml.BeanDefinitionDecorator; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.w3c.dom.Node; /** * Adds the decorated {@link org.springframework.security.providers.AuthenticationProvider} to the ProviderManager's * list. * * @author Luke Taylor * @version $Id$ */ public class CustomAuthenticationProviderBeanDefinitionDecorator implements BeanDefinitionDecorator { public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) { ConfigUtils.addAuthenticationProvider(parserContext, holder.getBeanName()); return holder; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/BeanIds.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/BeanIds.0000644000000000000000000001207211623517156030336 0ustar package org.springframework.security.config; /** * Contains all the default Bean IDs created by the namespace support in Spring Security 2. *

* These are mainly intended for internal use. * * @author Ben Alex * @version $Id$ */ public abstract class BeanIds { /** External alias for FilterChainProxy bean, for use in web.xml files */ public static final String SPRING_SECURITY_FILTER_CHAIN = "springSecurityFilterChain"; /** Package protected as end users shouldn't really be using this BFPP directly */ static final String INTERCEPT_METHODS_BEAN_FACTORY_POST_PROCESSOR = "_interceptMethodsBeanfactoryPP"; static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = "_contextSettingPostProcessor"; static final String ENTRY_POINT_INJECTION_POST_PROCESSOR = "_entryPointInjectionBeanPostProcessor"; static final String USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR = "_userServiceInjectionPostProcessor"; static final String SESSION_REGISTRY_INJECTION_POST_PROCESSOR = "_sessionRegistryInjectionPostProcessor"; static final String FILTER_CHAIN_POST_PROCESSOR = "_filterChainProxyPostProcessor"; static final String FILTER_LIST = "_filterChainList"; public static final String JDBC_USER_DETAILS_MANAGER = "_jdbcUserDetailsManager"; public static final String USER_DETAILS_SERVICE = "_userDetailsService"; public static final String ANONYMOUS_PROCESSING_FILTER = "_anonymousProcessingFilter"; public static final String ANONYMOUS_AUTHENTICATION_PROVIDER = "_anonymousAuthenticationProvider"; public static final String BASIC_AUTHENTICATION_FILTER = "_basicAuthenticationFilter"; public static final String BASIC_AUTHENTICATION_ENTRY_POINT = "_basicAuthenticationEntryPoint"; public static final String SESSION_REGISTRY = "_sessionRegistry"; public static final String CONCURRENT_SESSION_FILTER = "_concurrentSessionFilter"; public static final String CONCURRENT_SESSION_CONTROLLER = "_concurrentSessionController"; public static final String ACCESS_MANAGER = "_accessManager"; public static final String AUTHENTICATION_MANAGER = "_authenticationManager"; public static final String AFTER_INVOCATION_MANAGER = "_afterInvocationManager"; public static final String FORM_LOGIN_FILTER = "_formLoginFilter"; public static final String FORM_LOGIN_ENTRY_POINT = "_formLoginEntryPoint"; public static final String OPEN_ID_FILTER = "_openIDFilter"; public static final String OPEN_ID_ENTRY_POINT = "_openIDFilterEntryPoint"; public static final String OPEN_ID_PROVIDER = "_openIDAuthenticationProvider"; public static final String MAIN_ENTRY_POINT = "_mainEntryPoint"; public static final String FILTER_CHAIN_PROXY = "_filterChainProxy"; public static final String HTTP_SESSION_CONTEXT_INTEGRATION_FILTER = "_httpSessionContextIntegrationFilter"; public static final String LDAP_AUTHENTICATION_PROVIDER = "_ldapAuthenticationProvider"; public static final String LOGOUT_FILTER = "_logoutFilter"; public static final String EXCEPTION_TRANSLATION_FILTER = "_exceptionTranslationFilter"; public static final String FILTER_SECURITY_INTERCEPTOR = "_filterSecurityInterceptor"; public static final String CHANNEL_PROCESSING_FILTER = "_channelProcessingFilter"; public static final String CHANNEL_DECISION_MANAGER = "_channelDecisionManager"; public static final String REMEMBER_ME_FILTER = "_rememberMeFilter"; public static final String REMEMBER_ME_SERVICES = "_rememberMeServices"; public static final String REMEMBER_ME_AUTHENTICATION_PROVIDER = "_rememberMeAuthenticationProvider"; public static final String DEFAULT_LOGIN_PAGE_GENERATING_FILTER = "_defaultLoginPageFilter"; public static final String SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER = "_securityContextHolderAwareRequestFilter"; public static final String SESSION_FIXATION_PROTECTION_FILTER = "_sessionFixationProtectionFilter"; public static final String METHOD_SECURITY_INTERCEPTOR = "_methodSecurityInterceptor"; public static final String METHOD_SECURITY_INTERCEPTOR_POST_PROCESSOR = "_methodSecurityInterceptorPostProcessor"; public static final String METHOD_DEFINITION_SOURCE_ADVISOR = "_methodDefinitionSourceAdvisor"; public static final String PROTECT_POINTCUT_POST_PROCESSOR = "_protectPointcutPostProcessor"; public static final String DELEGATING_METHOD_DEFINITION_SOURCE = "_delegatingMethodDefinitionSource"; public static final String SECURED_METHOD_DEFINITION_SOURCE = "_securedMethodDefinitionSource"; public static final String JSR_250_METHOD_DEFINITION_SOURCE = "_jsr250MethodDefinitionSource"; public static final String EMBEDDED_APACHE_DS = "_apacheDirectoryServerContainer"; public static final String CONTEXT_SOURCE = "_securityContextSource"; public static final String PORT_MAPPER = "_portMapper"; public static final String X509_FILTER = "_x509ProcessingFilter"; public static final String X509_AUTH_PROVIDER = "_x509AuthenticationProvider"; public static final String PRE_AUTH_ENTRY_POINT = "_preAuthenticatedProcessingFilterEntryPoint"; public static final String REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR = "_rememberMeServicesInjectionBeanPostProcessor"; } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-security-2.0.2.xsdspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-s0000644000000000000000000017613611623517156030531 0ustar Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Whether a string should be base64 encoded Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. Specifies an IP port number. Used to configure an embedded LDAP server, for example. Specifies a URL. A bean identifier, used for referring to the bean elsewhere in the context. Defines a reference to a Spring bean Id. Defines a reference to a cache for use with a UserDetailsService. A reference to a user-service (or UserDetailsService bean) Id A reference to a DataSource bean Defines a reference to a Spring bean Id. Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Whether a string should be base64 encoded A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied. A bean identifier, used for referring to the bean elsewhere in the context. Specifies a URL. Specifies an IP port number. Used to configure an embedded LDAP server, for example. Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used. Explicitly specifies an ldif file resource to load into an embedded LDAP server Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org" The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. Search base for group membership searches. Defaults to "ou=groups". Search base for user searches. Defaults to "". The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object A bean identifier, used for referring to the bean elsewhere in the context. The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Search base for user searches. Defaults to "". Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. Search base for group membership searches. Defaults to "ou=groups". The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". Defines a reference to a cache for use with a UserDetailsService. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object Sets up an ldap authentication provider Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example. A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Search base for user searches. Defaults to "". Search base for group membership searches. Defaults to "ou=groups". Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object The attribute in the directory which contains the user password. Defaults to "userPassword". Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods Defines a protected method and the access control configuration attributes that apply to it. We strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security". Optional AccessDecisionManager bean ID to be used by the created method security interceptor. A method name Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B". Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for Spring Security annotations and/or matches with the ordered list of "protect-pointcut" sub-elements. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. If you use and enable all three sources of method security metadata (ie "protect-pointcut" declarations, @Secured and also JSR 250 security annotations), the metadata sources will be queried in that order. In practical terms, this enables you to use XML to override method security metadata expressed by way of @Secured annotations, with @Secured annotations overriding method security metadata expressed by JSR 250 annotations. It is perfectly acceptable to mix and match, with a given Java type using a combination of XML, @Secured and JSR 250 to express method security metadata (albeit on different methods). Defines a protected pointcut and the access control configuration attributes that apply to it. Every bean registered in the Spring application context that provides a method that matches the pointcut will receive security authorization. Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Please ensure you have the spring-security-tiger-xxx.jar on the classpath. Defaults to "disabled". Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Defaults to "disabled". Optional AccessDecisionManager bean ID to override the default used for method security. An AspectJ expression, including the 'execution' keyword. For example, 'execution(int com.foo.TargetObject.countLength(String))' (without the quotes). Access configuration attributes list that applies to all methods matching the pointcut, e.g. "ROLE_A,ROLE_B" Container element for HTTP security configuration Specifies the access attributes and/or filter list for a particular set of URLs. Sets up a form login configuration for authentication with a username and password Adds support for X.509 client authentication. Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute) Incorporates a logout processing filter. Most web applications require a logout filter, although you may not require one if you write a controller to provider similar logic. Adds support for concurrent session control, allowing limits to be placed on the number of sessions a user can have. Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach. Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority. Defines the list of mappings between http and https ports for use in redirects Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false". Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true". Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true". Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests. Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application". Indicates whether an existing session should be invalidated when a user authenticates and a new session started. If set to "none" no change will be made. "newSession" will create a new empty session. "migrateSession" will create a new session and copy the session attributes to the new session. Defaults to "migrateSession". Allows a customized AuthenticationEntryPoint to be used. Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true" Allows the access denied page to be set (the user will be redirected here if an AccessDeniedException is raised). The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax. The access configuration attributes that apply for the configured path. The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method. The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all filters created by the namespace configuration, and any added using 'custom-filter'), will be applied to any other paths. Used to specify that a URL must be accessed over http or https Specifies the URL that will cause a logout. Spring Security will initialize a filter that responds to this particular URL. Defaults to /j_spring_security_logout if unspecified. Specifies the URL to display once the user has logged out. If not specified, defaults to /. Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true. The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check. The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application. Whether the user should always be redirected to the default-target-url after login. The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested. The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /spring_security_login?login_error and a corresponding filter to render that login failure URL when requested. Sets up form login for authentication with an Open ID identity A reference to a user-service (or UserDetailsService bean) Id Used to explicitly configure a FilterChainProxy instance with a FilterChainMap Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom. Used to explicitly configure a FilterInvocationDefinitionSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error. Specifies the access attributes and/or filter list for a particular set of URLs. A bean identifier, used for referring to the bean elsewhere in the context. as for http element Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. The URL a user will be redirected to if they attempt to use a session which has been "expired" by the concurrent session controller. Specifies that an exception should be raised when a user attempts to login twice. The default behaviour is to expire the original session. Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration A reference to an external SessionRegistry implementation which will be used in place of the standard one. The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application. Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation. A reference to a DataSource bean A reference to a user-service (or UserDetailsService bean) Id The period (in seconds) for which the remember-me cookie should be valid. Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation. Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider. The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter". The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser". The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS". The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),". A reference to a user-service (or UserDetailsService bean) Id If you are using namespace configuration with Spring Security, an AuthenticationManager will automatically be registered. This element allows you to define an alias to allow you to reference the authentication-manager in your own beans. The alias you wish to use for the AuthenticationManager bean Allows the session controller to be set on the internal AuthenticationManager. This should not be used with the <concurrent-session-control /> element Indicates that the contained user-service should be used as an authentication source. element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example. A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. A reference to a user-service (or UserDetailsService bean) Id Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements. A bean identifier, used for referring to the bean elsewhere in the context. Represents a user in the application. The username assigned to the user. The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR" Can be set to "true" to mark an account as locked and unusable. Can be set to "true" to mark an account as disabled and unusable. Causes creation of a JDBC-based UserDetailsService. A bean identifier, used for referring to the bean elsewhere in the context. The bean ID of the DataSource which provides the required tables. Defines a reference to a cache for use with a UserDetailsService. An SQL statement to query a username, password, and enabled status given a username An SQL statement to query for a user's granted authorities given a username. An SQL statement to query user's group authorities given a username. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. Used to indicate that a filter bean declaration should be incorporated into the security filter chain. If neither the 'after' or 'before' options are supplied, then the filter must implement the Ordered interface directly. The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. The filter immediately before which the custom-filter should be placed in the chain The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter. The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. The filter immediately before which the custom-filter should be placed in the chain The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter. ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/MethodSecurityInterceptorPostProcessor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/MethodSe0000644000000000000000000000331311623517156030461 0ustar package org.springframework.security.config; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.security.AfterInvocationManager; import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor; /** * BeanPostProcessor which sets the AfterInvocationManager on the default MethodSecurityInterceptor, * if one has been configured. * * @author Luke Taylor * @version $Id$ * */ public class MethodSecurityInterceptorPostProcessor implements BeanPostProcessor, BeanFactoryAware{ private Log logger = LogFactory.getLog(getClass()); private BeanFactory beanFactory; public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if(!BeanIds.METHOD_SECURITY_INTERCEPTOR.equals(beanName)) { return bean; } MethodSecurityInterceptor interceptor = (MethodSecurityInterceptor) bean; if (beanFactory.containsBean(BeanIds.AFTER_INVOCATION_MANAGER)) { logger.debug("Setting AfterInvocationManaer on MethodSecurityInterceptor"); interceptor.setAfterInvocationManager((AfterInvocationManager) beanFactory.getBean(BeanIds.AFTER_INVOCATION_MANAGER)); } return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) { return bean; } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } } ././@LongLink0000000000000000000000000000022600000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/FilterInvocationDefinitionSourceBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/FilterIn0000644000000000000000000000501111623517156030462 0ustar package org.springframework.security.config; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.util.AntUrlPathMatcher; import org.springframework.security.util.UrlMatcher; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; /** * Allows for convenient creation of a {@link FilterInvocationDefinitionSource} bean for use with a FilterSecurityInterceptor. * * @author Luke Taylor * @version $Id$ */ public class FilterInvocationDefinitionSourceBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected String getBeanClassName(Element element) { return "org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource"; } protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { List interceptUrls = DomUtils.getChildElementsByTagName(element, "intercept-url"); // Check for attributes that aren't allowed in this context Iterator interceptUrlElts = interceptUrls.iterator(); while(interceptUrlElts.hasNext()) { Element elt = (Element) interceptUrlElts.next(); if (StringUtils.hasLength(elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL))) { parserContext.getReaderContext().error("The attribute '" + HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL + "' isn't allowed here.", elt); } if (StringUtils.hasLength(elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS))) { parserContext.getReaderContext().error("The attribute '" + HttpSecurityBeanDefinitionParser.ATT_FILTERS + "' isn't allowed here.", elt); } } UrlMatcher matcher = HttpSecurityBeanDefinitionParser.createUrlMatcher(element); boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl(); LinkedHashMap requestMap = HttpSecurityBeanDefinitionParser.parseInterceptUrlsForFilterInvocationRequestMap(interceptUrls, convertPathsToLowerCase, parserContext); builder.addConstructorArg(matcher); builder.addConstructorArg(requestMap); } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/AnonymousBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Anonymou0000644000000000000000000000645111623517156030564 0ustar package org.springframework.security.config; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.providers.anonymous.AnonymousAuthenticationProvider; import org.springframework.security.providers.anonymous.AnonymousProcessingFilter; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * @author Ben Alex * @version $Id: RememberMeBeanDefinitionParser.java 2231 2007-11-07 13:29:15Z luke_t $ */ public class AnonymousBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_KEY = "key"; static final String DEF_KEY = "doesNotMatter"; static final String ATT_USERNAME = "username"; static final String DEF_USERNAME = "roleAnonymous"; static final String ATT_GRANTED_AUTHORITY = "granted-authority"; static final String DEF_GRANTED_AUTHORITY = "ROLE_ANONYMOUS"; protected final Log logger = LogFactory.getLog(getClass()); public BeanDefinition parse(Element element, ParserContext parserContext) { String grantedAuthority = null; String username = null; String key = null; Object source = null; if (element != null) { grantedAuthority = element.getAttribute(ATT_GRANTED_AUTHORITY); username = element.getAttribute(ATT_USERNAME); key = element.getAttribute(ATT_KEY); source = parserContext.extractSource(element); } if (!StringUtils.hasText(grantedAuthority)) { grantedAuthority = DEF_GRANTED_AUTHORITY; } if (!StringUtils.hasText(username)) { username = DEF_USERNAME; } if (!StringUtils.hasText(key)) { key = DEF_KEY; } RootBeanDefinition filter = new RootBeanDefinition(AnonymousProcessingFilter.class); filter.setSource(source); filter.getPropertyValues().addPropertyValue("userAttribute", username + "," + grantedAuthority); filter.getPropertyValues().addPropertyValue(ATT_KEY, key); RootBeanDefinition provider = new RootBeanDefinition(AnonymousAuthenticationProvider.class); provider.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); provider.setSource(source); provider.getPropertyValues().addPropertyValue(ATT_KEY, key); parserContext.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER, provider); ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER); parserContext.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_PROCESSING_FILTER, filter); ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.ANONYMOUS_PROCESSING_FILTER)); parserContext.registerComponent(new BeanComponentDefinition(filter, BeanIds.ANONYMOUS_PROCESSING_FILTER)); return null; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/catalog.xmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/catalog.0000644000000000000000000000056311623517156030445 0ustar ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/CachingUserDetailsService.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/CachingU0000644000000000000000000000225611623517156030437 0ustar package org.springframework.security.config; import org.springframework.security.providers.dao.UserCache; import org.springframework.security.providers.dao.cache.NullUserCache; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.security.userdetails.UserDetails; import org.springframework.util.Assert; /** * * @author Luke Taylor * @since 2.0 */ class CachingUserDetailsService implements UserDetailsService { private UserCache userCache = new NullUserCache(); private UserDetailsService delegate; CachingUserDetailsService(UserDetailsService delegate) { this.delegate = delegate; } public UserCache getUserCache() { return userCache; } public void setUserCache(UserCache userCache) { this.userCache = userCache; } public UserDetails loadUserByUsername(String username) { UserDetails user = userCache.getUserFromCache(username); if (user == null) { user = delegate.loadUserByUsername(username); } Assert.notNull(user, "UserDetailsService " + delegate + " returned null for username " + username + ". " + "This is an interface contract violation"); userCache.putUserInCache(user); return user; } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/PasswordEncoderParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Password0000644000000000000000000001037011623517156030554 0ustar package org.springframework.security.config; import org.springframework.security.providers.encoding.Md4PasswordEncoder; import org.springframework.security.providers.encoding.Md5PasswordEncoder; import org.springframework.security.providers.encoding.PlaintextPasswordEncoder; import org.springframework.security.providers.encoding.ShaPasswordEncoder; import org.springframework.security.providers.encoding.BaseDigestPasswordEncoder; import org.springframework.security.providers.ldap.authenticator.LdapShaPasswordEncoder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.BeanMetadataElement; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Map; import java.util.HashMap; /** * Stateful parser for the element. * * Will produce a PasswordEncoder and (optionally) a SaltSource. * * @author Luke Taylor * @version $Id$ */ public class PasswordEncoderParser { static final String ATT_REF = "ref"; static final String ATT_HASH = "hash"; static final String ATT_BASE_64 = "base64"; static final String OPT_HASH_PLAINTEXT = "plaintext"; static final String OPT_HASH_SHA = "sha"; static final String OPT_HASH_SHA256 = "sha-256"; static final String OPT_HASH_MD4 = "md4"; static final String OPT_HASH_MD5 = "md5"; static final String OPT_HASH_LDAP_SHA = "{sha}"; static final Map ENCODER_CLASSES; static { ENCODER_CLASSES = new HashMap(); ENCODER_CLASSES.put(OPT_HASH_PLAINTEXT, PlaintextPasswordEncoder.class); ENCODER_CLASSES.put(OPT_HASH_SHA, ShaPasswordEncoder.class); ENCODER_CLASSES.put(OPT_HASH_SHA256, ShaPasswordEncoder.class); ENCODER_CLASSES.put(OPT_HASH_MD4, Md4PasswordEncoder.class); ENCODER_CLASSES.put(OPT_HASH_MD5, Md5PasswordEncoder.class); ENCODER_CLASSES.put(OPT_HASH_LDAP_SHA, LdapShaPasswordEncoder.class); } private Log logger = LogFactory.getLog(getClass()); private BeanMetadataElement passwordEncoder; private BeanDefinition saltSource; public PasswordEncoderParser(Element element, ParserContext parserContext) { parse(element, parserContext); } private void parse(Element element, ParserContext parserContext) { String hash = element.getAttribute(ATT_HASH); boolean useBase64 = false; if (StringUtils.hasText(element.getAttribute(ATT_BASE_64))) { useBase64 = new Boolean(element.getAttribute(ATT_BASE_64)).booleanValue(); } String ref = element.getAttribute(ATT_REF); if (StringUtils.hasText(ref)) { passwordEncoder = new RuntimeBeanReference(ref); } else { Class beanClass = (Class) ENCODER_CLASSES.get(hash); RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass); if (OPT_HASH_SHA256.equals(hash)) { beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, new Integer(256)); } beanDefinition.setSource(parserContext.extractSource(element)); if (useBase64) { if (BaseDigestPasswordEncoder.class.isAssignableFrom(beanClass)) { beanDefinition.getPropertyValues().addPropertyValue("encodeHashAsBase64", "true"); } else { logger.warn(ATT_BASE_64 + " isn't compatible with " + hash + " and will be ignored"); } } passwordEncoder = beanDefinition; } Element saltSourceElt = DomUtils.getChildElementByTagName(element, Elements.SALT_SOURCE); if (saltSourceElt != null) { saltSource = new SaltSourceBeanDefinitionParser().parse(saltSourceElt, parserContext); } } public BeanMetadataElement getPasswordEncoder() { return passwordEncoder; } public BeanDefinition getSaltSource() { return saltSource; } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/InterceptMethodsBeanDefinitionDecorator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Intercep0000644000000000000000000001022511623517156030522 0ustar package org.springframework.security.config; import java.util.Iterator; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionDecorator; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * @author Luke Taylor * @author Ben Alex * * @version $Id$ */ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDecorator { private BeanDefinitionDecorator delegate = new InternalInterceptMethodsBeanDefinitionDecorator(); public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) { ConfigUtils.registerProviderManagerIfNecessary(parserContext); ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext); return delegate.decorate(node, definition, parserContext); } } /** * This is the real class which does the work. We need access to the ParserContext in order to do bean * registration. */ class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator { static final String ATT_METHOD = "method"; static final String ATT_ACCESS = "access"; private static final String ATT_ACCESS_MGR = "access-decision-manager-ref"; private Log logger = LogFactory.getLog(getClass()); protected BeanDefinition createInterceptorDefinition(Node node) { Element interceptMethodsElt = (Element)node; BeanDefinitionBuilder interceptor = BeanDefinitionBuilder.rootBeanDefinition(MethodSecurityInterceptor.class); // Default to autowiring to pick up after invocation mgr interceptor.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE); String accessManagerId = interceptMethodsElt.getAttribute(ATT_ACCESS_MGR); if (!StringUtils.hasText(accessManagerId)) { accessManagerId = BeanIds.ACCESS_MANAGER; } interceptor.addPropertyValue("accessDecisionManager", new RuntimeBeanReference(accessManagerId)); interceptor.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER)); // Lookup parent bean information Element parent = (Element) node.getParentNode(); String parentBeanClass = parent.getAttribute("class"); String parentBeanId = parent.getAttribute("id"); parent = null; // Parse the included methods List methods = DomUtils.getChildElementsByTagName(interceptMethodsElt, Elements.PROTECT); StringBuffer sb = new StringBuffer(); for (Iterator i = methods.iterator(); i.hasNext();) { Element protectmethodElt = (Element) i.next(); String accessConfig = protectmethodElt.getAttribute(ATT_ACCESS); // Support inference of class names String methodName = protectmethodElt.getAttribute(ATT_METHOD); if (methodName.lastIndexOf(".") == -1) { if (parentBeanClass != null && !"".equals(parentBeanClass)) { methodName = parentBeanClass + "." + methodName; } } // Rely on the default property editor for MethodSecurityInterceptor.setObjectDefinitionSource to setup the MethodDefinitionSource sb.append(methodName + "=" + accessConfig).append("\r\n"); } interceptor.addPropertyValue("objectDefinitionSource", sb.toString()); return interceptor.getBeanDefinition(); } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/SessionRegistryInjectionBeanPostProcessor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/SessionR0000644000000000000000000000726711623517156030532 0ustar package org.springframework.security.config; import java.util.ArrayList; import java.util.List; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.security.concurrent.ConcurrentSessionController; import org.springframework.security.concurrent.ConcurrentSessionControllerImpl; import org.springframework.security.concurrent.SessionRegistry; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.ui.SessionFixationProtectionFilter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Registered by the AuthenticationManagerBeanDefinitionParser if an external * ConcurrentSessionController is set (and hence an external SessionRegistry). * Its responsibility is to set the SessionRegistry on namespace-registered beans which require access * to it. *

* It will attempt to read the registry directly from the registered controller. If that fails, it will look in * the application context for a registered SessionRegistry bean. * * See SEC-879. * * @author Luke Taylor * @since 2.0.3 */ class SessionRegistryInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware { private final Log logger = LogFactory.getLog(getClass()); private ListableBeanFactory beanFactory; private SessionRegistry sessionRegistry; private final String controllerBeanName; SessionRegistryInjectionBeanPostProcessor(String controllerBeanName) { this.controllerBeanName = controllerBeanName; } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (BeanIds.FORM_LOGIN_FILTER.equals(beanName) || BeanIds.OPEN_ID_FILTER.equals(beanName)) { ((AbstractProcessingFilter) bean).setSessionRegistry(getSessionRegistry()); } else if (BeanIds.SESSION_FIXATION_PROTECTION_FILTER.equals(beanName)) { ((SessionFixationProtectionFilter)bean).setSessionRegistry(getSessionRegistry()); } return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } private SessionRegistry getSessionRegistry() { if (sessionRegistry != null) { return sessionRegistry; } logger.info("Attempting to read SessionRegistry from registered ConcurrentSessionController bean"); ConcurrentSessionController controller = (ConcurrentSessionController) beanFactory.getBean(controllerBeanName); if (controller instanceof ConcurrentSessionControllerImpl) { sessionRegistry = ((ConcurrentSessionControllerImpl)controller).getSessionRegistry(); return sessionRegistry; } logger.info("ConcurrentSessionController is not a standard implementation. SessionRegistry could not be read from it. Looking for it in the context."); List sessionRegs = new ArrayList(beanFactory.getBeansOfType(SessionRegistry.class).values()); if (sessionRegs.size() == 0) { throw new SecurityConfigurationException("concurrent-session-controller-ref was set but no SessionRegistry could be obtained from the application context."); } if (sessionRegs.size() > 1) { logger.warn("More than one SessionRegistry instance in application context. Possible configuration errors may result."); } sessionRegistry = (SessionRegistry) sessionRegs.get(0); return sessionRegistry; } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = (ListableBeanFactory) beanFactory; } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/ConfigUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/ConfigUt0000644000000000000000000002026011623517156030467 0ustar package org.springframework.security.config; import java.util.ArrayList; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.afterinvocation.AfterInvocationProviderManager; import org.springframework.security.util.UrlUtils; import org.springframework.security.vote.AffirmativeBased; import org.springframework.security.vote.AuthenticatedVoter; import org.springframework.security.vote.RoleVoter; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * Utility methods used internally by the Spring Security namespace configuration code. * * @author Luke Taylor * @author Ben Alex * @version $Id$ */ public abstract class ConfigUtils { private static final Log logger = LogFactory.getLog(ConfigUtils.class); static void registerDefaultAccessManagerIfNecessary(ParserContext parserContext) { if (!parserContext.getRegistry().containsBeanDefinition(BeanIds.ACCESS_MANAGER)) { ManagedList defaultVoters = new ManagedList(2); defaultVoters.add(new RootBeanDefinition(RoleVoter.class)); defaultVoters.add(new RootBeanDefinition(AuthenticatedVoter.class)); BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class); accessMgrBuilder.addPropertyValue("decisionVoters", defaultVoters); BeanDefinition accessMgr = accessMgrBuilder.getBeanDefinition(); parserContext.getRegistry().registerBeanDefinition(BeanIds.ACCESS_MANAGER, accessMgr); } } public static int countNonEmpty(String[] objects) { int nonNulls = 0; for (int i = 0; i < objects.length; i++) { if (StringUtils.hasText(objects[i])) { nonNulls++; } } return nonNulls; } public static void addVoter(BeanDefinition voter, ParserContext parserContext) { registerDefaultAccessManagerIfNecessary(parserContext); BeanDefinition accessMgr = parserContext.getRegistry().getBeanDefinition(BeanIds.ACCESS_MANAGER); ManagedList voters = (ManagedList) accessMgr.getPropertyValues().getPropertyValue("decisionVoters").getValue(); voters.add(voter); accessMgr.getPropertyValues().addPropertyValue("decisionVoters", voters); } /** * Creates and registers the bean definition for the default ProviderManager instance and returns * the BeanDefinition for it. This method will typically be called when registering authentication providers * using the <security:provider /> tag or by other beans which have a dependency on the * authentication manager. */ static void registerProviderManagerIfNecessary(ParserContext parserContext) { if(parserContext.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER)) { return; } BeanDefinition authManager = new RootBeanDefinition(NamespaceAuthenticationManager.class); authManager.getPropertyValues().addPropertyValue("providerBeanNames", new ArrayList()); parserContext.getRegistry().registerBeanDefinition(BeanIds.AUTHENTICATION_MANAGER, authManager); } static void addAuthenticationProvider(ParserContext parserContext, String beanName) { registerProviderManagerIfNecessary(parserContext); BeanDefinition authManager = parserContext.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER); ((ArrayList) authManager.getPropertyValues().getPropertyValue("providerBeanNames").getValue()).add(beanName); } static ManagedList getRegisteredAfterInvocationProviders(ParserContext parserContext) { BeanDefinition manager = registerAfterInvocationProviderManagerIfNecessary(parserContext); return (ManagedList) manager.getPropertyValues().getPropertyValue("providers").getValue(); } private static BeanDefinition registerAfterInvocationProviderManagerIfNecessary(ParserContext parserContext) { if(parserContext.getRegistry().containsBeanDefinition(BeanIds.AFTER_INVOCATION_MANAGER)) { return parserContext.getRegistry().getBeanDefinition(BeanIds.AFTER_INVOCATION_MANAGER); } BeanDefinition manager = new RootBeanDefinition(AfterInvocationProviderManager.class); manager.getPropertyValues().addPropertyValue("providers", new ManagedList()); parserContext.getRegistry().registerBeanDefinition(BeanIds.AFTER_INVOCATION_MANAGER, manager); return manager; } private static void registerFilterChainPostProcessorIfNecessary(ParserContext pc) { if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_POST_PROCESSOR)) { return; } // Post processor specifically to assemble and order the filter chain immediately before the FilterChainProxy is initialized. RootBeanDefinition filterChainPostProcessor = new RootBeanDefinition(FilterChainProxyPostProcessor.class); filterChainPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_POST_PROCESSOR, filterChainPostProcessor); RootBeanDefinition filterList = new RootBeanDefinition(FilterChainList.class); filterList.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_LIST, filterList); } static void addHttpFilter(ParserContext pc, BeanMetadataElement filter) { registerFilterChainPostProcessorIfNecessary(pc); RootBeanDefinition filterList = (RootBeanDefinition) pc.getRegistry().getBeanDefinition(BeanIds.FILTER_LIST); ManagedList filters; MutablePropertyValues pvs = filterList.getPropertyValues(); if (pvs.contains("filters")) { filters = (ManagedList) pvs.getPropertyValue("filters").getValue(); } else { filters = new ManagedList(); pvs.addPropertyValue("filters", filters); } filters.add(filter); } /** * Bean which holds the list of filters which are maintained in the context and modified by calls to * addHttpFilter. The post processor retrieves these before injecting the list into the FilterChainProxy. */ public static class FilterChainList { List filters; public List getFilters() { return filters; } public void setFilters(List filters) { this.filters = filters; } } /** * Checks the value of an XML attribute which represents a redirect URL. * If not empty or starting with "$" (potential placeholder), "/" or "http" it will raise an error. */ static void validateHttpRedirect(String url, ParserContext pc, Object source) { if (UrlUtils.isValidRedirectUrl(url) || url.startsWith("$")) { return; } pc.getReaderContext().warning(url + " is not a valid redirect URL (must start with '/' or http(s))", source); } static void setSessionControllerOnAuthenticationManager(ParserContext pc, String beanName, Element sourceElt) { registerProviderManagerIfNecessary(pc); BeanDefinition authManager = pc.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER); PropertyValue pv = authManager.getPropertyValues().getPropertyValue("sessionController"); if (pv != null && pv.getValue() != null) { pc.getReaderContext().error("A session controller has already been set on the authentication manager. " + "The element isn't compatible with a custom session controller", pc.extractSource(sourceElt)); } authManager.getPropertyValues().addPropertyValue("sessionController", new RuntimeBeanReference(beanName)); } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-security-2.0.6.xsdspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-s0000644000000000000000000017330011623517156030517 0ustar Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Whether a string should be base64 encoded Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. Specifies an IP port number. Used to configure an embedded LDAP server, for example. Specifies a URL. A bean identifier, used for referring to the bean elsewhere in the context. Defines a reference to a Spring bean Id. Defines a reference to a cache for use with a UserDetailsService. A reference to a user-service (or UserDetailsService bean) Id A reference to a DataSource bean Defines a reference to a Spring bean Id. Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Whether a string should be base64 encoded A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied. A bean identifier, used for referring to the bean elsewhere in the context. Specifies a URL. Specifies an IP port number. Used to configure an embedded LDAP server, for example. Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used. The password for the manager DN. Explicitly specifies an ldif file resource to load into an embedded LDAP server Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org" The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. Search base for group membership searches. Defaults to "" (searching from the root). The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name. Search base for user searches. Defaults to "". Only used with a 'user-search-filter'. The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object A bean identifier, used for referring to the bean elsewhere in the context. The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name. Search base for user searches. Defaults to "". Only used with a 'user-search-filter'. Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. Search base for group membership searches. Defaults to "" (searching from the root). The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". Defines a reference to a cache for use with a UserDetailsService. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object Sets up an ldap authentication provider Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example. Password salting strategy. A system-wide constant or a property from the UserDetails object can be used. A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Search base for user searches. Defaults to "". Only used with a 'user-search-filter'. The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name. Search base for group membership searches. Defaults to "" (searching from the root). Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object The attribute in the directory which contains the user password. Defaults to "userPassword". Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods Defines a protected method and the access control configuration attributes that apply to it. We strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security". Optional AccessDecisionManager bean ID to be used by the created method security interceptor. A method name Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B". Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for Spring Security annotations and/or matches with the ordered list of "protect-pointcut" sub-elements. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. If you use and enable all three sources of method security metadata (ie "protect-pointcut" declarations, @Secured and also JSR 250 security annotations), the metadata sources will be queried in that order. In practical terms, this enables you to use XML to override method security metadata expressed by way of @Secured annotations, with @Secured annotations overriding method security metadata expressed by JSR 250 annotations. It is perfectly acceptable to mix and match, with a given Java type using a combination of XML, @Secured and JSR 250 to express method security metadata (albeit on different methods). Defines a protected pointcut and the access control configuration attributes that apply to it. Every bean registered in the Spring application context that provides a method that matches the pointcut will receive security authorization. Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Please ensure you have the spring-security-tiger-xxx.jar on the classpath. Defaults to "disabled". Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Defaults to "disabled". Optional AccessDecisionManager bean ID to override the default used for method security. Used to decorate an AfterInvocationProvider to specify that it should be used with method security. An AspectJ expression, including the 'execution' keyword. For example, 'execution(int com.foo.TargetObject.countLength(String))' (without the quotes). Access configuration attributes list that applies to all methods matching the pointcut, e.g. "ROLE_A,ROLE_B" Allows a custom instance of HttpFirewall to be injected into the FilterChainProxy created by the namespace. Container element for HTTP security configuration Specifies the access attributes and/or filter list for a particular set of URLs. Sets up a form login configuration for authentication with a username and password Adds support for X.509 client authentication. Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute) Incorporates a logout processing filter. Most web applications require a logout filter, although you may not require one if you write a controller to provider similar logic. Adds support for concurrent session control, allowing limits to be placed on the number of sessions a user can have. Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach. Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority. Defines the list of mappings between http and https ports for use in redirects Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false". Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true". Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true". Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests. Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application". Indicates whether an existing session should be invalidated when a user authenticates and a new session started. If set to "none" no change will be made. "newSession" will create a new empty session. "migrateSession" will create a new session and copy the session attributes to the new session. Defaults to "migrateSession". Allows a customized AuthenticationEntryPoint to be used. Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true" Allows the access denied page to be set (the user will be redirected here if an AccessDeniedException is raised). The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax. The access configuration attributes that apply for the configured path. The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method. The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all filters created by the namespace configuration, and any added using 'custom-filter'), will be applied to any other paths. Used to specify that a URL must be accessed over http or https, or that there is no preference. Specifies the URL that will cause a logout. Spring Security will initialize a filter that responds to this particular URL. Defaults to /j_spring_security_logout if unspecified. Specifies the URL to display once the user has logged out. If not specified, defaults to /. Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true. The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check. The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application. Whether the user should always be redirected to the default-target-url after login. The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested. The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /spring_security_login?login_error and a corresponding filter to render that login failure URL when requested. Sets up form login for authentication with an Open ID identity A reference to a user-service (or UserDetailsService bean) Id Used to explicitly configure a FilterChainProxy instance with a FilterChainMap Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom. Used to explicitly configure a FilterInvocationDefinitionSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error. Specifies the access attributes and/or filter list for a particular set of URLs. A bean identifier, used for referring to the bean elsewhere in the context. as for http element Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. The maximum number of sessions a single user can have open at the same time. Defaults to "1". The URL a user will be redirected to if they attempt to use a session which has been "expired" by the concurrent session controller because they have logged in again. Specifies that an exception should be raised when a user attempts to login when they already have the maximum configured sessions open. The default behaviour is to expire the original session. Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration A reference to an external SessionRegistry implementation which will be used in place of the standard one. The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application. Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation. A reference to a DataSource bean A reference to a user-service (or UserDetailsService bean) Id The period (in seconds) for which the remember-me cookie should be valid. Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation. Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider. The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter". The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser". The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS". The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),". A reference to a user-service (or UserDetailsService bean) Id If you are using namespace configuration with Spring Security, an AuthenticationManager will automatically be registered. This element allows you to define an alias to allow you to reference the authentication-manager in your own beans. The alias you wish to use for the AuthenticationManager bean Allows the session controller to be set on the internal AuthenticationManager. This should not be used with the <concurrent-session-control /> element Indicates that the contained user-service should be used as an authentication source. element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example. Password salting strategy. A system-wide constant or a property from the UserDetails object can be used. A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. A reference to a user-service (or UserDetailsService bean) Id Element used to decorate an AuthenticationProvider bean to add it to the internal AuthenticationManager maintained by the namespace. Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements. A bean identifier, used for referring to the bean elsewhere in the context. Represents a user in the application. The username assigned to the user. The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR" Can be set to "true" to mark an account as locked and unusable. Can be set to "true" to mark an account as disabled and unusable. Causes creation of a JDBC-based UserDetailsService. A bean identifier, used for referring to the bean elsewhere in the context. The bean ID of the DataSource which provides the required tables. Defines a reference to a cache for use with a UserDetailsService. An SQL statement to query a username, password, and enabled status given a username An SQL statement to query for a user's granted authorities given a username. An SQL statement to query user's group authorities given a username. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. Used to indicate that a filter bean declaration should be incorporated into the security filter chain. If neither the 'after' or 'before' options are supplied, then the filter must implement the Ordered interface directly. The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. The filter immediately before which the custom-filter should be placed in the chain The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter. The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. The filter immediately before which the custom-filter should be placed in the chain The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter. ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-security-2.0.6.rncspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-s0000644000000000000000000007001311623517156030514 0ustar namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes" default namespace = "http://www.springframework.org/schema/security" start = http | ldap-server | authentication-provider | ldap-authentication-provider | any-user-service | ldap-server | ldap-authentication-provider hash = ## Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. attribute hash {"plaintext" | "sha" | "sha-256" | "md5" | "md4" | "{sha}" | "{ssha}"} base64 = ## Whether a string should be base64 encoded attribute base64 {"true" | "false"} path-type = ## Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. attribute path-type {"ant" | "regex"} port = ## Specifies an IP port number. Used to configure an embedded LDAP server, for example. attribute port { xsd:integer } url = ## Specifies a URL. attribute url { xsd:string } id = ## A bean identifier, used for referring to the bean elsewhere in the context. attribute id {xsd:ID} ref = ## Defines a reference to a Spring bean Id. attribute ref {xsd:string} cache-ref = ## Defines a reference to a cache for use with a UserDetailsService. attribute cache-ref {xsd:string} user-service-ref = ## A reference to a user-service (or UserDetailsService bean) Id attribute user-service-ref {xsd:string} data-source-ref = ## A reference to a DataSource bean attribute data-source-ref {xsd:string} password-encoder = ## element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example. element password-encoder {password-encoder.attlist, salt-source?} password-encoder.attlist &= ref | (hash? & base64?) salt-source = ## Password salting strategy. A system-wide constant or a property from the UserDetails object can be used. element salt-source {user-property | system-wide} user-property = ## A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. attribute user-property {xsd:string} system-wide = ## A single value that will be used as the salt for a password encoder. attribute system-wide {xsd:string} boolean = "true" | "false" role-prefix = ## A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. attribute role-prefix {xsd:string} ldap-server = ## Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied. element ldap-server {ldap-server.attlist} ldap-server.attlist &= id? ldap-server.attlist &= (url | port)? ldap-server.attlist &= ## Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used. attribute manager-dn {xsd:string}? ldap-server.attlist &= ## The password for the manager DN. attribute manager-password {xsd:string}? ldap-server.attlist &= ## Explicitly specifies an ldif file resource to load into an embedded LDAP server attribute ldif { xsd:string }? ldap-server.attlist &= ## Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org" attribute root { xsd:string }? ldap-server-ref-attribute = ## The optional server to use. If omitted, and a default LDAP server is registered (using with no Id), that server will be used. attribute server-ref {xsd:string} group-search-filter-attribute = ## Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. attribute group-search-filter {xsd:string} group-search-base-attribute = ## Search base for group membership searches. Defaults to "" (searching from the root). attribute group-search-base {xsd:string} user-search-filter-attribute = ## The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name. attribute user-search-filter {xsd:string} user-search-base-attribute = ## Search base for user searches. Defaults to "". Only used with a 'user-search-filter'. attribute user-search-base {xsd:string} group-role-attribute-attribute = ## The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". attribute group-role-attribute {xsd:string} user-details-class-attribute = ## Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object attribute user-details-class {"person" | "inetOrgPerson"} ldap-user-service = element ldap-user-service {ldap-us.attlist} ldap-us.attlist &= id? ldap-us.attlist &= ldap-server-ref-attribute? ldap-us.attlist &= user-search-filter-attribute? ldap-us.attlist &= user-search-base-attribute? ldap-us.attlist &= group-search-filter-attribute? ldap-us.attlist &= group-search-base-attribute? ldap-us.attlist &= group-role-attribute-attribute? ldap-us.attlist &= cache-ref? ldap-us.attlist &= role-prefix? ldap-us.attlist &= user-details-class-attribute? ldap-authentication-provider = ## Sets up an ldap authentication provider element ldap-authentication-provider {ldap-ap.attlist, password-compare-element?} ldap-ap.attlist &= ldap-server-ref-attribute? ldap-ap.attlist &= user-search-base-attribute? ldap-ap.attlist &= user-search-filter-attribute? ldap-ap.attlist &= group-search-base-attribute? ldap-ap.attlist &= group-search-filter-attribute? ldap-ap.attlist &= group-role-attribute-attribute? ldap-ap.attlist &= ## A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username. attribute user-dn-pattern {xsd:string}? ldap-ap.attlist &= role-prefix? ldap-ap.attlist &= user-details-class-attribute? password-compare-element = ## Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user element password-compare {password-compare.attlist, password-encoder?} password-compare.attlist &= ## The attribute in the directory which contains the user password. Defaults to "userPassword". attribute password-attribute {xsd:string}? password-compare.attlist &= hash? intercept-methods = ## Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods element intercept-methods {intercept-methods.attlist, protect+} intercept-methods.attlist &= ## Optional AccessDecisionManager bean ID to be used by the created method security interceptor. attribute access-decision-manager-ref {xsd:string}? protect = ## Defines a protected method and the access control configuration attributes that apply to it. We strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security". element protect {protect.attlist, empty} protect.attlist &= ## A method name attribute method {xsd:string} protect.attlist &= ## Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B". attribute access {xsd:string} global-method-security = ## Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for Spring Security annotations and/or matches with the ordered list of "protect-pointcut" sub-elements. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. If you use and enable all three sources of method security metadata (ie "protect-pointcut" declarations, @Secured and also JSR 250 security annotations), the metadata sources will be queried in that order. In practical terms, this enables you to use XML to override method security metadata expressed by way of @Secured annotations, with @Secured annotations overriding method security metadata expressed by JSR 250 annotations. It is perfectly acceptable to mix and match, with a given Java type using a combination of XML, @Secured and JSR 250 to express method security metadata (albeit on different methods). element global-method-security {global-method-security.attlist, protect-pointcut*} global-method-security.attlist &= ## Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Please ensure you have the spring-security-tiger-xxx.jar on the classpath. Defaults to "disabled". attribute secured-annotations {"disabled" | "enabled" }? global-method-security.attlist &= ## Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Defaults to "disabled". attribute jsr250-annotations {"disabled" | "enabled" }? global-method-security.attlist &= ## Optional AccessDecisionManager bean ID to override the default used for method security. attribute access-decision-manager-ref {xsd:string}? custom-after-invocation-provider = ## Used to decorate an AfterInvocationProvider to specify that it should be used with method security. element custom-after-invocation-provider {empty} protect-pointcut = ## Defines a protected pointcut and the access control configuration attributes that apply to it. Every bean registered in the Spring application context that provides a method that matches the pointcut will receive security authorization. element protect-pointcut {protect-pointcut.attlist, empty} protect-pointcut.attlist &= ## An AspectJ expression, including the 'execution' keyword. For example, 'execution(int com.foo.TargetObject.countLength(String))' (without the quotes). attribute expression {xsd:string} protect-pointcut.attlist &= ## Access configuration attributes list that applies to all methods matching the pointcut, e.g. "ROLE_A,ROLE_B" attribute access {xsd:string} http-firewall = ## Allows a custom instance of HttpFirewall to be injected into the FilterChainProxy created by the namespace. element http-firewall {ref} http = ## Container element for HTTP security configuration element http {http.attlist, (intercept-url+ & form-login? & openid-login & x509? & http-basic? & logout? & concurrent-session-control? & remember-me? & anonymous? & port-mappings) } http.attlist &= ## Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false". attribute auto-config {boolean}? http.attlist &= ## Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". attribute create-session {"ifRequired" | "always" | "never" }? http.attlist &= ## The path format used to define the paths in child elements. path-type? http.attlist &= ## Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true". attribute lowercase-comparisons {boolean}? http.attlist &= ## Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true". attribute servlet-api-provision {boolean}? http.attlist &= ## Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests. attribute access-decision-manager-ref {xsd:string}? http.attlist &= ## Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application". attribute realm {xsd:string}? http.attlist &= ## Indicates whether an existing session should be invalidated when a user authenticates and a new session started. If set to "none" no change will be made. "newSession" will create a new empty session. "migrateSession" will create a new session and copy the session attributes to the new session. Defaults to "migrateSession". attribute session-fixation-protection {"none" | "newSession" | "migrateSession" }? http.attlist &= ## Allows a customized AuthenticationEntryPoint to be used. attribute entry-point-ref {xsd:string}? http.attlist &= ## Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true" attribute once-per-request {boolean}? http.attlist &= ## Allows the access denied page to be set (the user will be redirected here if an AccessDeniedException is raised). attribute access-denied-page {xsd:string}? intercept-url = ## Specifies the access attributes and/or filter list for a particular set of URLs. element intercept-url {intercept-url.attlist, empty} intercept-url.attlist &= ## The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax. attribute pattern {xsd:string} intercept-url.attlist &= ## The access configuration attributes that apply for the configured path. attribute access {xsd:string}? intercept-url.attlist &= ## The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method. attribute method {"GET" | "DELETE" | "HEAD" | "OPTIONS" | "POST" | "PUT" | "TRACE"}? intercept-url.attlist &= ## The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all filters created by the namespace configuration, and any added using 'custom-filter'), will be applied to any other paths. attribute filters {"none"}? intercept-url.attlist &= ## Used to specify that a URL must be accessed over http or https, or that there is no preference. attribute requires-channel {"http" | "https" | "any"}? logout = ## Incorporates a logout processing filter. Most web applications require a logout filter, although you may not require one if you write a controller to provider similar logic. element logout {logout.attlist, empty} logout.attlist &= ## Specifies the URL that will cause a logout. Spring Security will initialize a filter that responds to this particular URL. Defaults to /j_spring_security_logout if unspecified. attribute logout-url {xsd:string}? logout.attlist &= ## Specifies the URL to display once the user has logged out. If not specified, defaults to /. attribute logout-success-url {xsd:string}? logout.attlist &= ## Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true. attribute invalidate-session {boolean}? form-login = ## Sets up a form login configuration for authentication with a username and password element form-login {form-login.attlist, empty} form-login.attlist &= ## The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check. attribute login-processing-url {xsd:string}? form-login.attlist &= ## The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application. attribute default-target-url {xsd:string}? form-login.attlist &= ## Whether the user should always be redirected to the default-target-url after login. attribute always-use-default-target {boolean}? form-login.attlist &= ## The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested. attribute login-page {xsd:string}? form-login.attlist &= ## The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /spring_security_login?login_error and a corresponding filter to render that login failure URL when requested. attribute authentication-failure-url {xsd:string}? openid-login = ## Sets up form login for authentication with an Open ID identity element openid-login {form-login.attlist, user-service-ref?, empty} filter-chain-map = ## Used to explicitly configure a FilterChainProxy instance with a FilterChainMap element filter-chain-map {filter-chain-map.attlist, filter-chain+} filter-chain-map.attlist &= path-type filter-chain = ## Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom. element filter-chain {filter-chain.attlist, empty} filter-chain.attlist &= attribute pattern {xsd:string} filter-chain.attlist &= attribute filters {xsd:string} filter-invocation-definition-source = ## Used to explicitly configure a FilterInvocationDefinitionSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error. element filter-invocation-definition-source {fids.attlist, intercept-url+} fids.attlist &= id? fids.attlist &= ## as for http element attribute lowercase-comparisons {boolean}? fids.attlist &= ## as for http element path-type? http-basic = ## Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute) element http-basic {empty} concurrent-session-control = ## Adds support for concurrent session control, allowing limits to be placed on the number of sessions a user can have. element concurrent-session-control {concurrent-sessions.attlist, empty} concurrent-sessions.attlist &= ## The maximum number of sessions a single user can have open at the same time. Defaults to "1". attribute max-sessions {xsd:positiveInteger}? concurrent-sessions.attlist &= ## The URL a user will be redirected to if they attempt to use a session which has been "expired" by the concurrent session controller because they have logged in again. attribute expired-url {xsd:string}? concurrent-sessions.attlist &= ## Specifies that an exception should be raised when a user attempts to login when they already have the maximum configured sessions open. The default behaviour is to expire the original session. attribute exception-if-maximum-exceeded {boolean}? concurrent-sessions.attlist &= ## Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration attribute session-registry-alias {xsd:string}? concurrent-sessions.attlist &= ## A reference to an external SessionRegistry implementation which will be used in place of the standard one. attribute session-registry-ref {xsd:string}? remember-me = ## Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach. element remember-me {remember-me.attlist} remember-me.attlist &= ## The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application. attribute key {xsd:string}? remember-me.attlist &= (token-repository-ref | remember-me-data-source-ref | remember-me-services-ref) remember-me.attlist &= user-service-ref? remember-me.attlist &= ## The period (in seconds) for which the remember-me cookie should be valid. attribute token-validity-seconds {xsd:positiveInteger}? token-repository-ref = ## Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation. attribute token-repository-ref {xsd:string} remember-me-services-ref = ## Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider. attribute services-ref {xsd:string}? remember-me-data-source-ref = ## DataSource bean for the database that contains the token repository schema. data-source-ref anonymous = ## Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority. element anonymous {anonymous.attlist} anonymous.attlist &= ## The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter". attribute key {xsd:string}? anonymous.attlist &= ## The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser". attribute username {xsd:string}? anonymous.attlist &= ## The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS". attribute granted-authority {xsd:string}? port-mappings = ## Defines the list of mappings between http and https ports for use in redirects element port-mappings {port-mappings.attlist, port-mapping+} port-mappings.attlist &= empty port-mapping = element port-mapping {http-port, https-port} http-port = attribute http {xsd:string} https-port = attribute https {xsd:string} x509 = ## Adds support for X.509 client authentication. element x509 {x509.attlist} x509.attlist &= ## The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),". attribute subject-principal-regex {xsd:string}? x509.attlist &= ## Explicitly specifies which user-service should be used to load user data for X.509 authenticated clients. If ommitted, the default user-service will be used. user-service-ref? authentication-manager = ## If you are using namespace configuration with Spring Security, an AuthenticationManager will automatically be registered. This element allows you to define an alias to allow you to reference the authentication-manager in your own beans. element authentication-manager {authman.attlist} authman.attlist &= ## The alias you wish to use for the AuthenticationManager bean attribute alias {xsd:ID} authman.attlist &= ## Allows the session controller to be set on the internal AuthenticationManager. This should not be used with the element attribute session-controller-ref {xsd:string}? authentication-provider = ## Indicates that the contained user-service should be used as an authentication source. element authentication-provider {ap.attlist & any-user-service & password-encoder?} ap.attlist &= ## Specifies a reference to a separately configured UserDetailsService from which to obtain authentication data. user-service-ref? custom-authentication-provider = ## Element used to decorate an AuthenticationProvider bean to add it to the internal AuthenticationManager maintained by the namespace. element custom-authentication-provider {cap.attlist} cap.attlist &= empty user-service = ## Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements. element user-service {id? & (properties-file | (user*))} properties-file = attribute properties {xsd:string}? user = ## Represents a user in the application. element user {user.attlist, empty} user.attlist &= ## The username assigned to the user. attribute name {xsd:string} user.attlist &= ## The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). attribute password {xsd:string} user.attlist &= ## One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR" attribute authorities {xsd:string} user.attlist &= ## Can be set to "true" to mark an account as locked and unusable. attribute locked {boolean}? user.attlist &= ## Can be set to "true" to mark an account as disabled and unusable. attribute disabled {boolean}? jdbc-user-service = ## Causes creation of a JDBC-based UserDetailsService. element jdbc-user-service {id? & jdbc-user-service.attlist} jdbc-user-service.attlist &= ## The bean ID of the DataSource which provides the required tables. attribute data-source-ref {xsd:string} jdbc-user-service.attlist &= cache-ref? jdbc-user-service.attlist &= ## An SQL statement to query a username, password, and enabled status given a username attribute users-by-username-query {xsd:string}? jdbc-user-service.attlist &= ## An SQL statement to query for a user's granted authorities given a username. attribute authorities-by-username-query {xsd:string}? jdbc-user-service.attlist &= ## An SQL statement to query user's group authorities given a username. attribute group-authorities-by-username-query {xsd:string}? jdbc-user-service.attlist &= role-prefix? any-user-service = user-service | jdbc-user-service | ldap-user-service custom-filter = ## Used to indicate that a filter bean declaration should be incorporated into the security filter chain. If neither the 'after' or 'before' options are supplied, then the filter must implement the Ordered interface directly. element custom-filter {after | before | position}? after = ## The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. attribute after {named-security-filter} before = ## The filter immediately before which the custom-filter should be placed in the chain attribute before {named-security-filter} position = ## The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter. attribute position {named-security-filter} named-security-filter = "FIRST" | "CHANNEL_FILTER" | "CONCURRENT_SESSION_FILTER" | "SESSION_CONTEXT_INTEGRATION_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_PROCESSING_FILTER" | "AUTHENTICATION_PROCESSING_FILTER" | "OPENID_PROCESSING_FILTER" |"BASIC_PROCESSING_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "NTLM_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST" ././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/AuthenticationProviderBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Authenti0000644000000000000000000001446611623517156030545 0ustar package org.springframework.security.config; import org.springframework.beans.BeansException; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.core.Ordered; import org.springframework.security.providers.dao.DaoAuthenticationProvider; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; /** * Wraps a UserDetailsService bean with a DaoAuthenticationProvider and registers the latter with the * ProviderManager. * * @author Luke Taylor * @version $Id$ */ class AuthenticationProviderBeanDefinitionParser implements BeanDefinitionParser { private static String ATT_USER_DETAILS_REF = "user-service-ref"; public BeanDefinition parse(Element element, ParserContext parserContext) { RootBeanDefinition authProvider = new RootBeanDefinition(DaoAuthenticationProvider.class); authProvider.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); authProvider.setSource(parserContext.extractSource(element)); Element passwordEncoderElt = DomUtils.getChildElementByTagName(element, Elements.PASSWORD_ENCODER); if (passwordEncoderElt != null) { PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElt, parserContext); authProvider.getPropertyValues().addPropertyValue("passwordEncoder", pep.getPasswordEncoder()); if (pep.getSaltSource() != null) { authProvider.getPropertyValues().addPropertyValue("saltSource", pep.getSaltSource()); } } Element userServiceElt = DomUtils.getChildElementByTagName(element, Elements.USER_SERVICE); Element jdbcUserServiceElt = DomUtils.getChildElementByTagName(element, Elements.JDBC_USER_SERVICE); Element ldapUserServiceElt = DomUtils.getChildElementByTagName(element, Elements.LDAP_USER_SERVICE); // We need to register the provider to access it in the post processor to check if it has a cache final String id = parserContext.getReaderContext().generateBeanName(authProvider); parserContext.getRegistry().registerBeanDefinition(id, authProvider); parserContext.registerComponent(new BeanComponentDefinition(authProvider, id)); String ref = element.getAttribute(ATT_USER_DETAILS_REF); if (StringUtils.hasText(ref)) { if (userServiceElt != null || jdbcUserServiceElt != null || ldapUserServiceElt != null) { parserContext.getReaderContext().error("The " + ATT_USER_DETAILS_REF + " attribute cannot be used in combination with child" + "elements '" + Elements.USER_SERVICE + "', '" + Elements.JDBC_USER_SERVICE + "' or '" + Elements.LDAP_USER_SERVICE + "'", element); } } else { // Use the child elements to create the UserDetailsService AbstractUserDetailsServiceBeanDefinitionParser parser = null; Element elt = null; if (userServiceElt != null) { elt = userServiceElt; parser = new UserServiceBeanDefinitionParser(); } else if (jdbcUserServiceElt != null) { elt = jdbcUserServiceElt; parser = new JdbcUserServiceBeanDefinitionParser(); } else if (ldapUserServiceElt != null) { elt = ldapUserServiceElt; parser = new LdapUserServiceBeanDefinitionParser(); } else { parserContext.getReaderContext().error("A user-service is required", element); } parser.parse(elt, parserContext); ref = parser.getId(); } authProvider.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(ref)); BeanDefinitionBuilder cacheResolverBldr = BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProviderCacheResolver.class); cacheResolverBldr.addConstructorArg(id); cacheResolverBldr.addConstructorArg(ref); cacheResolverBldr.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); BeanDefinition cacheResolver = cacheResolverBldr.getBeanDefinition(); String name = parserContext.getReaderContext().generateBeanName(cacheResolver); parserContext.getRegistry().registerBeanDefinition(name , cacheResolver); parserContext.registerComponent(new BeanComponentDefinition(cacheResolver, name)); ConfigUtils.addAuthenticationProvider(parserContext, id); return null; } /** * Checks whether the registered user service bean has an associated cache and, if so, sets it on the * authentication provider. */ static class AuthenticationProviderCacheResolver implements BeanFactoryPostProcessor, Ordered { private String providerId; private String userServiceId; public AuthenticationProviderCacheResolver(String providerId, String userServiceId) { this.providerId = providerId; this.userServiceId = userServiceId; } public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { RootBeanDefinition provider = (RootBeanDefinition) beanFactory.getBeanDefinition(providerId); String cachingId = userServiceId + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX; if (beanFactory.containsBeanDefinition(cachingId)) { RootBeanDefinition cachingUserService = (RootBeanDefinition) beanFactory.getBeanDefinition(cachingId); PropertyValue userCacheProperty = cachingUserService.getPropertyValues().getPropertyValue("userCache"); provider.getPropertyValues().addPropertyValue(userCacheProperty); } } public int getOrder() { return HIGHEST_PRECEDENCE; } } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/RememberMeBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Remember0000644000000000000000000001511511623517156030512 0ustar package org.springframework.security.config; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.ui.rememberme.JdbcTokenRepositoryImpl; import org.springframework.security.ui.rememberme.PersistentTokenBasedRememberMeServices; import org.springframework.security.ui.rememberme.RememberMeProcessingFilter; import org.springframework.security.ui.rememberme.TokenBasedRememberMeServices; import org.springframework.security.providers.rememberme.RememberMeAuthenticationProvider; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * @author Luke Taylor * @author Ben Alex * @version $Id$ */ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_KEY = "key"; static final String DEF_KEY = "SpringSecured"; static final String ATT_DATA_SOURCE = "data-source-ref"; static final String ATT_SERVICES_REF = "services-ref"; static final String ATT_TOKEN_REPOSITORY = "token-repository-ref"; static final String ATT_USER_SERVICE_REF = "user-service-ref"; static final String ATT_TOKEN_VALIDITY = "token-validity-seconds"; protected final Log logger = LogFactory.getLog(getClass()); private String servicesName; public BeanDefinition parse(Element element, ParserContext parserContext) { String tokenRepository = null; String dataSource = null; String key = null; Object source = null; String userServiceRef = null; String rememberMeServicesRef = null; String tokenValiditySeconds = null; if (element != null) { tokenRepository = element.getAttribute(ATT_TOKEN_REPOSITORY); dataSource = element.getAttribute(ATT_DATA_SOURCE); key = element.getAttribute(ATT_KEY); userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF); rememberMeServicesRef = element.getAttribute(ATT_SERVICES_REF); tokenValiditySeconds = element.getAttribute(ATT_TOKEN_VALIDITY); source = parserContext.extractSource(element); } if (!StringUtils.hasText(key)) { key = DEF_KEY; } RootBeanDefinition services = null; boolean dataSourceSet = StringUtils.hasText(dataSource); boolean tokenRepoSet = StringUtils.hasText(tokenRepository); boolean servicesRefSet = StringUtils.hasText(rememberMeServicesRef); boolean userServiceSet = StringUtils.hasText(userServiceRef); boolean tokenValiditySet = StringUtils.hasText(tokenValiditySeconds); if (servicesRefSet && (dataSourceSet || tokenRepoSet || userServiceSet || tokenValiditySet)) { parserContext.getReaderContext().error(ATT_SERVICES_REF + " can't be used in combination with attributes " + ATT_TOKEN_REPOSITORY + "," + ATT_DATA_SOURCE + ", " + ATT_USER_SERVICE_REF + " or " + ATT_TOKEN_VALIDITY, source); } if (dataSourceSet && tokenRepoSet) { parserContext.getReaderContext().error("Specify " + ATT_TOKEN_REPOSITORY + " or " + ATT_DATA_SOURCE +" but not both", source); } boolean isPersistent = dataSourceSet | tokenRepoSet; if (isPersistent) { Object tokenRepo; services = new RootBeanDefinition(PersistentTokenBasedRememberMeServices.class); if (tokenRepoSet) { tokenRepo = new RuntimeBeanReference(tokenRepository); } else { tokenRepo = new RootBeanDefinition(JdbcTokenRepositoryImpl.class); ((BeanDefinition)tokenRepo).getPropertyValues().addPropertyValue("dataSource", new RuntimeBeanReference(dataSource)); } services.getPropertyValues().addPropertyValue("tokenRepository", tokenRepo); } else if (!servicesRefSet) { services = new RootBeanDefinition(TokenBasedRememberMeServices.class); } if (services != null) { if (userServiceSet) { services.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef)); } if (tokenValiditySet) { services.getPropertyValues().addPropertyValue("tokenValiditySeconds", new Integer(tokenValiditySeconds)); } services.setSource(source); services.getPropertyValues().addPropertyValue(ATT_KEY, key); parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services); servicesName = BeanIds.REMEMBER_ME_SERVICES; } else { servicesName = rememberMeServicesRef; parserContext.getRegistry().registerAlias(rememberMeServicesRef, BeanIds.REMEMBER_ME_SERVICES); } registerProvider(parserContext, source, key); registerFilter(parserContext, source); return null; } String getServicesName() { return servicesName; } private void registerProvider(ParserContext pc, Object source, String key) { //BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(pc); RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class); provider.setSource(source); provider.getPropertyValues().addPropertyValue(ATT_KEY, key); pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER, provider); ConfigUtils.addAuthenticationProvider(pc, BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER); } private void registerFilter(ParserContext pc, Object source) { RootBeanDefinition filter = new RootBeanDefinition(RememberMeProcessingFilter.class); filter.setSource(source); filter.getPropertyValues().addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER)); filter.getPropertyValues().addPropertyValue("rememberMeServices", new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES)); pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_FILTER, filter); ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.REMEMBER_ME_FILTER)); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Elements.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Elements0000644000000000000000000000463511623517156030535 0ustar package org.springframework.security.config; /** * Contains all the element names used by Spring Security 2 namespace support. * * @author Ben Alex * @version $Id$ */ abstract class Elements { public static final String AUTHENTICATION_MANAGER = "authentication-manager"; public static final String USER_SERVICE = "user-service"; public static final String JDBC_USER_SERVICE = "jdbc-user-service"; public static final String FILTER_CHAIN_MAP = "filter-chain-map"; public static final String INTERCEPT_METHODS = "intercept-methods"; public static final String INTERCEPT_URL = "intercept-url"; public static final String AUTHENTICATION_PROVIDER = "authentication-provider"; public static final String HTTP = "http"; public static final String LDAP_PROVIDER = "ldap-authentication-provider"; public static final String LDAP_SERVER = "ldap-server"; public static final String LDAP_USER_SERVICE = "ldap-user-service"; public static final String PROTECT_POINTCUT = "protect-pointcut"; public static final String PROTECT = "protect"; public static final String CONCURRENT_SESSIONS = "concurrent-session-control"; public static final String LOGOUT = "logout"; public static final String FORM_LOGIN = "form-login"; public static final String OPENID_LOGIN = "openid-login"; public static final String BASIC_AUTH = "http-basic"; public static final String REMEMBER_ME = "remember-me"; public static final String ANONYMOUS = "anonymous"; public static final String FILTER_CHAIN = "filter-chain"; public static final String GLOBAL_METHOD_SECURITY = "global-method-security"; public static final String PASSWORD_ENCODER = "password-encoder"; public static final String SALT_SOURCE = "salt-source"; public static final String PORT_MAPPINGS = "port-mappings"; public static final String PORT_MAPPING = "port-mapping"; public static final String CUSTOM_FILTER = "custom-filter"; public static final String CUSTOM_AUTH_PROVIDER = "custom-authentication-provider"; public static final String CUSTOM_AFTER_INVOCATION_PROVIDER = "custom-after-invocation-provider"; public static final String X509 = "x509"; public static final String FILTER_INVOCATION_DEFINITION_SOURCE = "filter-invocation-definition-source"; public static final String LDAP_PASSWORD_COMPARE = "password-compare"; public static final String HTTP_FIREWALL = "http-firewall"; } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-security-2.0.4.xsdspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-s0000644000000000000000000020267611623517156030530 0ustar Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Whether a string should be base64 encoded Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. Specifies an IP port number. Used to configure an embedded LDAP server, for example. Specifies a URL. A bean identifier, used for referring to the bean elsewhere in the context. Defines a reference to a Spring bean Id. Defines a reference to a cache for use with a UserDetailsService. A reference to a user-service (or UserDetailsService bean) Id A reference to a DataSource bean Defines a reference to a Spring bean Id. Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Whether a string should be base64 encoded A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied. A bean identifier, used for referring to the bean elsewhere in the context. Specifies a URL. Specifies an IP port number. Used to configure an embedded LDAP server, for example. Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used. The password for the manager DN. Explicitly specifies an ldif file resource to load into an embedded LDAP server Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org" The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. Search base for group membership searches. Defaults to "ou=groups". The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name. Search base for user searches. Defaults to "". Only used with a 'user-search-filter'. The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object A bean identifier, used for referring to the bean elsewhere in the context. The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name. Search base for user searches. Defaults to "". Only used with a 'user-search-filter'. Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. Search base for group membership searches. Defaults to "ou=groups". The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". Defines a reference to a cache for use with a UserDetailsService. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object Sets up an ldap authentication provider Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example. Password salting strategy. A system-wide constant or a property from the UserDetails object can be used. A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Search base for user searches. Defaults to "". Only used with a 'user-search-filter'. The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name. Search base for group membership searches. Defaults to "ou=groups". Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object The attribute in the directory which contains the user password. Defaults to "userPassword". Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods Defines a protected method and the access control configuration attributes that apply to it. We strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security". Optional AccessDecisionManager bean ID to be used by the created method security interceptor. A method name Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B". Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for Spring Security annotations and/or matches with the ordered list of "protect-pointcut" sub-elements. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. If you use and enable all three sources of method security metadata (ie "protect-pointcut" declarations, @Secured and also JSR 250 security annotations), the metadata sources will be queried in that order. In practical terms, this enables you to use XML to override method security metadata expressed by way of @Secured annotations, with @Secured annotations overriding method security metadata expressed by JSR 250 annotations. It is perfectly acceptable to mix and match, with a given Java type using a combination of XML, @Secured and JSR 250 to express method security metadata (albeit on different methods). Defines a protected pointcut and the access control configuration attributes that apply to it. Every bean registered in the Spring application context that provides a method that matches the pointcut will receive security authorization. Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Please ensure you have the spring-security-tiger-xxx.jar on the classpath. Defaults to "disabled". Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Defaults to "disabled". Optional AccessDecisionManager bean ID to override the default used for method security. Used to decorate an AfterInvocationProvider to specify that it should be used with method security. An AspectJ expression, including the 'execution' keyword. For example, 'execution(int com.foo.TargetObject.countLength(String))' (without the quotes). Access configuration attributes list that applies to all methods matching the pointcut, e.g. "ROLE_A,ROLE_B" Container element for HTTP security configuration Specifies the access attributes and/or filter list for a particular set of URLs. Sets up a form login configuration for authentication with a username and password Adds support for X.509 client authentication. Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute) Incorporates a logout processing filter. Most web applications require a logout filter, although you may not require one if you write a controller to provider similar logic. Adds support for concurrent session control, allowing limits to be placed on the number of sessions a user can have. Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach. Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority. Defines the list of mappings between http and https ports for use in redirects Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false". Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true". Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true". Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests. Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application". Indicates whether an existing session should be invalidated when a user authenticates and a new session started. If set to "none" no change will be made. "newSession" will create a new empty session. "migrateSession" will create a new session and copy the session attributes to the new session. Defaults to "migrateSession". Allows a customized AuthenticationEntryPoint to be used. Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true" Allows the access denied page to be set (the user will be redirected here if an AccessDeniedException is raised). The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax. The access configuration attributes that apply for the configured path. The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method. The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all filters created by the namespace configuration, and any added using 'custom-filter'), will be applied to any other paths. Used to specify that a URL must be accessed over http or https, or that there is no preference. Specifies the URL that will cause a logout. Spring Security will initialize a filter that responds to this particular URL. Defaults to /j_spring_security_logout if unspecified. Specifies the URL to display once the user has logged out. If not specified, defaults to /. Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true. The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check. The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application. Whether the user should always be redirected to the default-target-url after login. The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested. The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /spring_security_login?login_error and a corresponding filter to render that login failure URL when requested. Sets up form login for authentication with an Open ID identity A reference to a user-service (or UserDetailsService bean) Id Used to explicitly configure a FilterChainProxy instance with a FilterChainMap Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom. Used to explicitly configure a FilterInvocationDefinitionSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error. Specifies the access attributes and/or filter list for a particular set of URLs. A bean identifier, used for referring to the bean elsewhere in the context. as for http element Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. The maximum number of sessions a single user can have open at the same time. Defaults to "1". The URL a user will be redirected to if they attempt to use a session which has been "expired" by the concurrent session controller because they have logged in again. Specifies that an exception should be raised when a user attempts to login when they already have the maximum configured sessions open. The default behaviour is to expire the original session. Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration A reference to an external SessionRegistry implementation which will be used in place of the standard one. The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application. Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation. A reference to a DataSource bean A reference to a user-service (or UserDetailsService bean) Id The period (in seconds) for which the remember-me cookie should be valid. Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation. Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider. The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter". The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser". The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS". The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),". A reference to a user-service (or UserDetailsService bean) Id If you are using namespace configuration with Spring Security, an AuthenticationManager will automatically be registered. This element allows you to define an alias to allow you to reference the authentication-manager in your own beans. The alias you wish to use for the AuthenticationManager bean Allows the session controller to be set on the internal AuthenticationManager. This should not be used with the <concurrent-session-control /> element Indicates that the contained user-service should be used as an authentication source. element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example. Password salting strategy. A system-wide constant or a property from the UserDetails object can be used. A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. A reference to a user-service (or UserDetailsService bean) Id Element used to decorate an AuthenticationProvider bean to add it to the internal AuthenticationManager maintained by the namespace. Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements. A bean identifier, used for referring to the bean elsewhere in the context. Represents a user in the application. The username assigned to the user. The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR" Can be set to "true" to mark an account as locked and unusable. Can be set to "true" to mark an account as disabled and unusable. Causes creation of a JDBC-based UserDetailsService. A bean identifier, used for referring to the bean elsewhere in the context. The bean ID of the DataSource which provides the required tables. Defines a reference to a cache for use with a UserDetailsService. An SQL statement to query a username, password, and enabled status given a username An SQL statement to query for a user's granted authorities given a username. An SQL statement to query user's group authorities given a username. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty. Used to indicate that a filter bean declaration should be incorporated into the security filter chain. If neither the 'after' or 'before' options are supplied, then the filter must implement the Ordered interface directly. The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. The filter immediately before which the custom-filter should be placed in the chain The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter. The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. The filter immediately before which the custom-filter should be placed in the chain The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter. ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/RememberMeServicesInjectionBeanPostProcessor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Remember0000644000000000000000000000576011623517156030517 0ustar package org.springframework.security.config; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.ui.basicauth.BasicProcessingFilter; import org.springframework.security.ui.rememberme.RememberMeServices; import org.springframework.util.Assert; /** * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class RememberMeServicesInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware { private Log logger = LogFactory.getLog(getClass()); private ListableBeanFactory beanFactory; public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof AbstractProcessingFilter) { AbstractProcessingFilter pf = (AbstractProcessingFilter) bean; if (pf.getRememberMeServices() == null) { logger.info("Setting RememberMeServices on bean " + beanName); pf.setRememberMeServices(getRememberMeServices()); } } else if (BeanIds.BASIC_AUTHENTICATION_FILTER.equals(beanName)) { // NB: For remember-me to be sent back, a user must submit a "_spring_security_remember_me" with their login request. // Most of the time a user won't present such a parameter with their BASIC authentication request. // In the future we might support setting the AbstractRememberMeServices.alwaysRemember = true, but I am reluctant to // do so because it seems likely to lead to lower security for 99.99% of users if they set the property to true. BasicProcessingFilter bf = (BasicProcessingFilter) bean; logger.info("Setting RememberMeServices on bean " + beanName); bf.setRememberMeServices(getRememberMeServices()); } return bean; } private RememberMeServices getRememberMeServices() { Map beans = beanFactory.getBeansOfType(RememberMeServices.class); Assert.isTrue(beans.size() > 0, "No RememberMeServices configured"); Assert.isTrue(beans.size() == 1, "Use of '' requires a single instance of RememberMeServices " + "in the application context, but more than one was found."); return (RememberMeServices) beans.values().toArray()[0]; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = (ListableBeanFactory) beanFactory; } } ././@LongLink0000000000000000000000000000022600000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/CustomAfterInvocationProviderBeanDefinitionDecorator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/CustomAf0000644000000000000000000000150311623517156030471 0ustar package org.springframework.security.config; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.xml.BeanDefinitionDecorator; import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Node; /** * Adds the decorated {@link org.springframework.security.afterinvocation.AfterInvocationProvider} to the * AfterInvocationProviderManager's list. * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class CustomAfterInvocationProviderBeanDefinitionDecorator implements BeanDefinitionDecorator { public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) { ConfigUtils.getRegisteredAfterInvocationProviders(parserContext).add(holder.getBeanDefinition()); return holder; } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/HttpSecurityBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/HttpSecu0000644000000000000000000007665211623517156030530 0ustar package org.springframework.security.config; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.ConfigAttributeEditor; import org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter; import org.springframework.security.context.HttpSessionContextIntegrationFilter; import org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource; import org.springframework.security.intercept.web.FilterSecurityInterceptor; import org.springframework.security.intercept.web.RequestKey; import org.springframework.security.securechannel.ChannelDecisionManagerImpl; import org.springframework.security.securechannel.ChannelProcessingFilter; import org.springframework.security.securechannel.InsecureChannelProcessor; import org.springframework.security.securechannel.SecureChannelProcessor; import org.springframework.security.securechannel.RetryWithHttpEntryPoint; import org.springframework.security.securechannel.RetryWithHttpsEntryPoint; import org.springframework.security.ui.AccessDeniedHandlerImpl; import org.springframework.security.ui.ExceptionTranslationFilter; import org.springframework.security.ui.SessionFixationProtectionFilter; import org.springframework.security.ui.webapp.DefaultLoginPageGeneratingFilter; import org.springframework.security.util.FilterChainProxy; import org.springframework.security.util.RegexUrlPathMatcher; import org.springframework.security.util.AntUrlPathMatcher; import org.springframework.security.util.UrlMatcher; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; /** * Sets up HTTP security: filter stack and protected URLs. * * @author Luke Taylor * @author Ben Alex * @since 2.0 * @version $Id$ */ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { static final Log logger = LogFactory.getLog(HttpSecurityBeanDefinitionParser.class); static final String ATT_REALM = "realm"; static final String DEF_REALM = "Spring Security Application"; static final String ATT_PATH_PATTERN = "pattern"; static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection"; static final String OPT_SESSION_FIXATION_NO_PROTECTION = "none"; static final String OPT_SESSION_FIXATION_CLEAN_SESSION = "newSession"; static final String OPT_SESSION_FIXATION_MIGRATE_SESSION = "migrateSession"; static final String ATT_PATH_TYPE = "path-type"; static final String DEF_PATH_TYPE_ANT = "ant"; static final String OPT_PATH_TYPE_REGEX = "regex"; static final String ATT_FILTERS = "filters"; static final String OPT_FILTERS_NONE = "none"; static final String ATT_ACCESS_CONFIG = "access"; static final String ATT_REQUIRES_CHANNEL = "requires-channel"; static final String OPT_REQUIRES_HTTP = "http"; static final String OPT_REQUIRES_HTTPS = "https"; static final String OPT_ANY_CHANNEL = "any"; static final String ATT_HTTP_METHOD = "method"; static final String ATT_CREATE_SESSION = "create-session"; static final String DEF_CREATE_SESSION_IF_REQUIRED = "ifRequired"; static final String OPT_CREATE_SESSION_ALWAYS = "always"; static final String OPT_CREATE_SESSION_NEVER = "never"; static final String ATT_LOWERCASE_COMPARISONS = "lowercase-comparisons"; static final String DEF_LOWERCASE_COMPARISONS = "true"; static final String ATT_AUTO_CONFIG = "auto-config"; static final String DEF_AUTO_CONFIG = "false"; static final String ATT_SERVLET_API_PROVISION = "servlet-api-provision"; static final String DEF_SERVLET_API_PROVISION = "true"; static final String ATT_ACCESS_MGR = "access-decision-manager-ref"; static final String ATT_USER_SERVICE_REF = "user-service-ref"; static final String ATT_ENTRY_POINT_REF = "entry-point-ref"; static final String ATT_ONCE_PER_REQUEST = "once-per-request"; static final String ATT_ACCESS_DENIED_PAGE = "access-denied-page"; public BeanDefinition parse(Element element, ParserContext parserContext) { ConfigUtils.registerProviderManagerIfNecessary(parserContext); final BeanDefinitionRegistry registry = parserContext.getRegistry(); final UrlMatcher matcher = createUrlMatcher(element); final Object source = parserContext.extractSource(element); // SEC-501 - should paths stored in request maps be converted to lower case // true if Ant path and using lower case final boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl(); final List interceptUrlElts = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL); final Map filterChainMap = new LinkedHashMap(); final LinkedHashMap channelRequestMap = new LinkedHashMap(); registerFilterChainProxy(parserContext, filterChainMap, matcher, source); parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap, convertPathsToLowerCase, parserContext); boolean allowSessionCreation = registerHttpSessionIntegrationFilter(element, parserContext); registerServletApiFilter(element, parserContext); // Set up the access manager reference for http String accessManagerId = element.getAttribute(ATT_ACCESS_MGR); if (!StringUtils.hasText(accessManagerId)) { ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext); accessManagerId = BeanIds.ACCESS_MANAGER; } // Register the portMapper. A default will always be created, even if no element exists. BeanDefinition portMapper = new PortMappingsBeanDefinitionParser().parse( DomUtils.getChildElementByTagName(element, Elements.PORT_MAPPINGS), parserContext); registry.registerBeanDefinition(BeanIds.PORT_MAPPER, portMapper); registerExceptionTranslationFilter(element, parserContext, allowSessionCreation); if (channelRequestMap.size() > 0) { // At least one channel requirement has been specified registerChannelProcessingBeans(parserContext, matcher, channelRequestMap); } registerFilterSecurityInterceptor(element, parserContext, matcher, accessManagerId, parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, convertPathsToLowerCase, parserContext)); boolean sessionControlEnabled = registerConcurrentSessionControlBeansIfRequired(element, parserContext); registerSessionFixationProtectionFilter(parserContext, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION), sessionControlEnabled); boolean autoConfig = false; if ("true".equals(element.getAttribute(ATT_AUTO_CONFIG))) { autoConfig = true; } Element anonymousElt = DomUtils.getChildElementByTagName(element, Elements.ANONYMOUS); if (anonymousElt != null || autoConfig) { new AnonymousBeanDefinitionParser().parse(anonymousElt, parserContext); } parseRememberMeAndLogout(element, autoConfig, parserContext); parseBasicFormLoginAndOpenID(element, parserContext, autoConfig, allowSessionCreation); Element x509Elt = DomUtils.getChildElementByTagName(element, Elements.X509); if (x509Elt != null) { new X509BeanDefinitionParser().parse(x509Elt, parserContext); } // Register the post processors which will tie up the loose ends in the configuration once the app context has been created and all beans are available. RootBeanDefinition postProcessor = new RootBeanDefinition(EntryPointInjectionBeanPostProcessor.class); postProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(BeanIds.ENTRY_POINT_INJECTION_POST_PROCESSOR, postProcessor); RootBeanDefinition postProcessor2 = new RootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class); postProcessor2.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(BeanIds.USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR, postProcessor2); return null; } private void parseRememberMeAndLogout(Element elt, boolean autoConfig, ParserContext pc) { // Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation. Element rememberMeElt = DomUtils.getChildElementByTagName(elt, Elements.REMEMBER_ME); String rememberMeServices = null; if (rememberMeElt != null || autoConfig) { RememberMeBeanDefinitionParser rmbdp = new RememberMeBeanDefinitionParser(); rmbdp.parse(rememberMeElt, pc); rememberMeServices = rmbdp.getServicesName(); // Post processor to inject RememberMeServices into filters which need it RootBeanDefinition rememberMeInjectionPostProcessor = new RootBeanDefinition(RememberMeServicesInjectionBeanPostProcessor.class); rememberMeInjectionPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR, rememberMeInjectionPostProcessor); } Element logoutElt = DomUtils.getChildElementByTagName(elt, Elements.LOGOUT); if (logoutElt != null || autoConfig) { new LogoutBeanDefinitionParser(rememberMeServices).parse(logoutElt, pc); } } private void registerFilterChainProxy(ParserContext pc, Map filterChainMap, UrlMatcher matcher, Object source) { if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) { pc.getReaderContext().error("Duplicate element detected", source); } RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class); filterChainProxy.setSource(source); filterChainProxy.getPropertyValues().addPropertyValue("matcher", matcher); filterChainProxy.getPropertyValues().addPropertyValue("stripQueryStringFromUrls", Boolean.valueOf(matcher instanceof AntUrlPathMatcher)); filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap); pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy); pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN); } private boolean registerHttpSessionIntegrationFilter(Element element, ParserContext pc) { RootBeanDefinition httpScif = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class); boolean sessionCreationAllowed = true; String createSession = element.getAttribute(ATT_CREATE_SESSION); if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) { httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE); httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE); } else if (OPT_CREATE_SESSION_NEVER.equals(createSession)) { httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.FALSE); httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.FALSE); sessionCreationAllowed = false; } else { createSession = DEF_CREATE_SESSION_IF_REQUIRED; httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE); httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.FALSE); } pc.getRegistry().registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif); ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER)); return sessionCreationAllowed; } // Adds the servlet-api integration filter if required private void registerServletApiFilter(Element element, ParserContext pc) { String provideServletApi = element.getAttribute(ATT_SERVLET_API_PROVISION); if (!StringUtils.hasText(provideServletApi)) { provideServletApi = DEF_SERVLET_API_PROVISION; } if ("true".equals(provideServletApi)) { pc.getRegistry().registerBeanDefinition(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER, new RootBeanDefinition(SecurityContextHolderAwareRequestFilter.class)); ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER)); } } private boolean registerConcurrentSessionControlBeansIfRequired(Element element, ParserContext parserContext) { Element sessionControlElt = DomUtils.getChildElementByTagName(element, Elements.CONCURRENT_SESSIONS); if (sessionControlElt == null) { return false; } new ConcurrentSessionsBeanDefinitionParser().parse(sessionControlElt, parserContext); logger.info("Concurrent session filter in use, setting 'forceEagerSessionCreation' to true"); BeanDefinition sessionIntegrationFilter = parserContext.getRegistry().getBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER); sessionIntegrationFilter.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE); return true; } private void registerExceptionTranslationFilter(Element element, ParserContext pc, boolean allowSessionCreation) { String accessDeniedPage = element.getAttribute(ATT_ACCESS_DENIED_PAGE); ConfigUtils.validateHttpRedirect(accessDeniedPage, pc, pc.extractSource(element)); BeanDefinitionBuilder exceptionTranslationFilterBuilder = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class); exceptionTranslationFilterBuilder.addPropertyValue("createSessionAllowed", new Boolean(allowSessionCreation)); if (StringUtils.hasText(accessDeniedPage)) { BeanDefinition accessDeniedHandler = new RootBeanDefinition(AccessDeniedHandlerImpl.class); accessDeniedHandler.getPropertyValues().addPropertyValue("errorPage", accessDeniedPage); exceptionTranslationFilterBuilder.addPropertyValue("accessDeniedHandler", accessDeniedHandler); } pc.getRegistry().registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition()); ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.EXCEPTION_TRANSLATION_FILTER)); } private void registerFilterSecurityInterceptor(Element element, ParserContext pc, UrlMatcher matcher, String accessManagerId, LinkedHashMap filterInvocationDefinitionMap) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class); builder.addPropertyReference("accessDecisionManager", accessManagerId); builder.addPropertyReference("authenticationManager", BeanIds.AUTHENTICATION_MANAGER); if ("false".equals(element.getAttribute(ATT_ONCE_PER_REQUEST))) { builder.addPropertyValue("observeOncePerRequest", Boolean.FALSE); } DefaultFilterInvocationDefinitionSource fids = new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap); fids.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher); builder.addPropertyValue("objectDefinitionSource", fids); pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, builder.getBeanDefinition()); ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FILTER_SECURITY_INTERCEPTOR)); } private void registerChannelProcessingBeans(ParserContext pc, UrlMatcher matcher, LinkedHashMap channelRequestMap) { RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class); channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager", new RuntimeBeanReference(BeanIds.CHANNEL_DECISION_MANAGER)); DefaultFilterInvocationDefinitionSource channelFilterInvDefSource = new DefaultFilterInvocationDefinitionSource(matcher, channelRequestMap); channelFilterInvDefSource.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher); channelFilter.getPropertyValues().addPropertyValue("filterInvocationDefinitionSource", channelFilterInvDefSource); RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class); ManagedList channelProcessors = new ManagedList(3); RootBeanDefinition secureChannelProcessor = new RootBeanDefinition(SecureChannelProcessor.class); RootBeanDefinition retryWithHttp = new RootBeanDefinition(RetryWithHttpEntryPoint.class); RootBeanDefinition retryWithHttps = new RootBeanDefinition(RetryWithHttpsEntryPoint.class); RuntimeBeanReference portMapper = new RuntimeBeanReference(BeanIds.PORT_MAPPER); retryWithHttp.getPropertyValues().addPropertyValue("portMapper", portMapper); retryWithHttps.getPropertyValues().addPropertyValue("portMapper", portMapper); secureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", retryWithHttps); RootBeanDefinition inSecureChannelProcessor = new RootBeanDefinition(InsecureChannelProcessor.class); inSecureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", retryWithHttp); channelProcessors.add(secureChannelProcessor); channelProcessors.add(inSecureChannelProcessor); channelDecisionManager.getPropertyValues().addPropertyValue("channelProcessors", channelProcessors); pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_PROCESSING_FILTER, channelFilter); ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.CHANNEL_PROCESSING_FILTER)); pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_DECISION_MANAGER, channelDecisionManager); } private void registerSessionFixationProtectionFilter(ParserContext pc, String sessionFixationAttribute, boolean sessionControlEnabled) { if(!StringUtils.hasText(sessionFixationAttribute)) { sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION; } if (!sessionFixationAttribute.equals(OPT_SESSION_FIXATION_NO_PROTECTION)) { BeanDefinitionBuilder sessionFixationFilter = BeanDefinitionBuilder.rootBeanDefinition(SessionFixationProtectionFilter.class); sessionFixationFilter.addPropertyValue("migrateSessionAttributes", Boolean.valueOf(sessionFixationAttribute.equals(OPT_SESSION_FIXATION_MIGRATE_SESSION))); if (sessionControlEnabled) { sessionFixationFilter.addPropertyReference("sessionRegistry", BeanIds.SESSION_REGISTRY); } pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER, sessionFixationFilter.getBeanDefinition()); ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SESSION_FIXATION_PROTECTION_FILTER)); } } private void parseBasicFormLoginAndOpenID(Element element, ParserContext pc, boolean autoConfig, boolean allowSessionCreation) { RootBeanDefinition formLoginFilter = null; RootBeanDefinition formLoginEntryPoint = null; String formLoginPage = null; RootBeanDefinition openIDFilter = null; RootBeanDefinition openIDEntryPoint = null; String openIDLoginPage = null; String realm = element.getAttribute(ATT_REALM); if (!StringUtils.hasText(realm)) { realm = DEF_REALM; } Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH); if (basicAuthElt != null || autoConfig) { new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, pc); } Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN); if (formLoginElt != null || autoConfig) { FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check", "org.springframework.security.ui.webapp.AuthenticationProcessingFilter"); parser.parse(formLoginElt, pc); formLoginFilter = parser.getFilterBean(); formLoginEntryPoint = parser.getEntryPointBean(); formLoginPage = parser.getLoginPage(); } Element openIDLoginElt = DomUtils.getChildElementByTagName(element, Elements.OPENID_LOGIN); if (openIDLoginElt != null) { FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check", "org.springframework.security.ui.openid.OpenIDAuthenticationProcessingFilter"); parser.parse(openIDLoginElt, pc); openIDFilter = parser.getFilterBean(); openIDEntryPoint = parser.getEntryPointBean(); openIDLoginPage = parser.getLoginPage(); BeanDefinitionBuilder openIDProviderBuilder = BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.providers.openid.OpenIDAuthenticationProvider"); String userService = openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF); if (StringUtils.hasText(userService)) { openIDProviderBuilder.addPropertyReference("userDetailsService", userService); } BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition(); pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider); ConfigUtils.addAuthenticationProvider(pc, BeanIds.OPEN_ID_PROVIDER); } boolean needLoginPage = false; if (formLoginFilter != null) { needLoginPage = true; formLoginFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation)); pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, formLoginFilter); ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER)); pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, formLoginEntryPoint); } if (openIDFilter != null) { needLoginPage = true; openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation)); pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openIDFilter); ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER)); pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openIDEntryPoint); } // If no login page has been defined, add in the default page generator. if (needLoginPage && formLoginPage == null && openIDLoginPage == null) { logger.info("No login page configured. The default internal one will be used. Use the '" + FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE + "' attribute to set the URL of the login page."); BeanDefinitionBuilder loginPageFilter = BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class); if (formLoginFilter != null) { loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER)); } if (openIDFilter != null) { loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER)); } pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER, loginPageFilter.getBeanDefinition()); ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER)); } // We need to establish the main entry point. // First check if a custom entry point bean is set String customEntryPoint = element.getAttribute(ATT_ENTRY_POINT_REF); if (StringUtils.hasText(customEntryPoint)) { pc.getRegistry().registerAlias(customEntryPoint, BeanIds.MAIN_ENTRY_POINT); return; } // Basic takes precedence if explicit element is used and no others are configured if (basicAuthElt != null && formLoginElt == null && openIDLoginElt == null) { pc.getRegistry().registerAlias(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT); return; } // If formLogin has been enabled either through an element or auto-config, then it is used if no openID login page // has been set if (formLoginFilter != null && openIDLoginPage == null) { pc.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT); return; } // Otherwise use OpenID if enabled if (openIDFilter != null && formLoginFilter == null) { pc.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT); return; } // If X.509 has been enabled, use the preauth entry point. if (DomUtils.getChildElementByTagName(element, Elements.X509) != null) { pc.getRegistry().registerAlias(BeanIds.PRE_AUTH_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT); return; } pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " + "make sure you have a login mechanism configured through the namespace (such as form-login) or " + "specify a custom AuthenticationEntryPoint with the custom-entry-point-ref attribute ", pc.extractSource(element)); } static UrlMatcher createUrlMatcher(Element element) { String patternType = element.getAttribute(ATT_PATH_TYPE); if (!StringUtils.hasText(patternType)) { patternType = DEF_PATH_TYPE_ANT; } boolean useRegex = patternType.equals(OPT_PATH_TYPE_REGEX); UrlMatcher matcher = new AntUrlPathMatcher(); if (useRegex) { matcher = new RegexUrlPathMatcher(); } // Deal with lowercase conversion requests String lowercaseComparisons = element.getAttribute(ATT_LOWERCASE_COMPARISONS); if (!StringUtils.hasText(lowercaseComparisons)) { lowercaseComparisons = null; } // Only change from the defaults if the attribute has been set if ("true".equals(lowercaseComparisons)) { if (useRegex) { ((RegexUrlPathMatcher)matcher).setRequiresLowerCaseUrl(true); } // Default for ant is already to force lower case } else if ("false".equals(lowercaseComparisons)) { if (!useRegex) { ((AntUrlPathMatcher)matcher).setRequiresLowerCaseUrl(false); } // Default for regex is no change } return matcher; } /** * Parses the intercept-url elements and populates the FilterChainProxy's filter chain Map and the * map used to create the FilterInvocationDefintionSource for the FilterSecurityInterceptor. */ void parseInterceptUrlsForChannelSecurityAndFilterChain(List urlElts, Map filterChainMap, Map channelRequestMap, boolean useLowerCasePaths, ParserContext parserContext) { Iterator urlEltsIterator = urlElts.iterator(); ConfigAttributeEditor editor = new ConfigAttributeEditor(); while (urlEltsIterator.hasNext()) { Element urlElt = (Element) urlEltsIterator.next(); String path = urlElt.getAttribute(ATT_PATH_PATTERN); if(!StringUtils.hasText(path)) { parserContext.getReaderContext().error("path attribute cannot be empty or null", urlElt); } if (useLowerCasePaths) { path = path.toLowerCase(); } String requiredChannel = urlElt.getAttribute(ATT_REQUIRES_CHANNEL); if (StringUtils.hasText(requiredChannel)) { String channelConfigAttribute = null; if (requiredChannel.equals(OPT_REQUIRES_HTTPS)) { channelConfigAttribute = "REQUIRES_SECURE_CHANNEL"; } else if (requiredChannel.equals(OPT_REQUIRES_HTTP)) { channelConfigAttribute = "REQUIRES_INSECURE_CHANNEL"; } else if (requiredChannel.equals(OPT_ANY_CHANNEL)) { channelConfigAttribute = ChannelDecisionManagerImpl.ANY_CHANNEL; } else { parserContext.getReaderContext().error("Unsupported channel " + requiredChannel, urlElt); } editor.setAsText(channelConfigAttribute); channelRequestMap.put(new RequestKey(path), (ConfigAttributeDefinition) editor.getValue()); } String filters = urlElt.getAttribute(ATT_FILTERS); if (StringUtils.hasText(filters)) { if (!filters.equals(OPT_FILTERS_NONE)) { parserContext.getReaderContext().error("Currently only 'none' is supported as the custom " + "filters attribute", urlElt); } filterChainMap.put(path, Collections.EMPTY_LIST); } } } static LinkedHashMap parseInterceptUrlsForFilterInvocationRequestMap(List urlElts, boolean useLowerCasePaths, ParserContext parserContext) { LinkedHashMap filterInvocationDefinitionMap = new LinkedHashMap(); Iterator urlEltsIterator = urlElts.iterator(); ConfigAttributeEditor editor = new ConfigAttributeEditor(); while (urlEltsIterator.hasNext()) { Element urlElt = (Element) urlEltsIterator.next(); String path = urlElt.getAttribute(ATT_PATH_PATTERN); if(!StringUtils.hasText(path)) { parserContext.getReaderContext().error("path attribute cannot be empty or null", urlElt); } if (useLowerCasePaths) { path = path.toLowerCase(); } String method = urlElt.getAttribute(ATT_HTTP_METHOD); if (!StringUtils.hasText(method)) { method = null; } String access = urlElt.getAttribute(ATT_ACCESS_CONFIG); // Convert the comma-separated list of access attributes to a ConfigAttributeDefinition if (StringUtils.hasText(access)) { editor.setAsText(access); Object key = new RequestKey(path, method); if (filterInvocationDefinitionMap.containsKey(key)) { logger.warn("Duplicate URL defined: " + key + ". The original attribute values will be overwritten"); } filterInvocationDefinitionMap.put(key, editor.getValue()); } } return filterInvocationDefinitionMap; } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/EntryPointInjectionBeanPostProcessor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/EntryPoi0000644000000000000000000000463711623517156030534 0ustar package org.springframework.security.config; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.security.ui.AuthenticationEntryPoint; import org.springframework.security.ui.ExceptionTranslationFilter; import org.springframework.util.Assert; /** * * @author Luke Taylor * @since 2.0.2 */ public class EntryPointInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware { private final Log logger = LogFactory.getLog(getClass()); private ConfigurableListableBeanFactory beanFactory; public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (!BeanIds.EXCEPTION_TRANSLATION_FILTER.equals(beanName)) { return bean; } logger.info("Selecting AuthenticationEntryPoint for use in ExceptionTranslationFilter"); ExceptionTranslationFilter etf = (ExceptionTranslationFilter) beanFactory.getBean(BeanIds.EXCEPTION_TRANSLATION_FILTER); Object entryPoint = null; if (beanFactory.containsBean(BeanIds.MAIN_ENTRY_POINT)) { entryPoint = beanFactory.getBean(BeanIds.MAIN_ENTRY_POINT); logger.info("Using main configured AuthenticationEntryPoint."); } else { Map entryPoints = beanFactory.getBeansOfType(AuthenticationEntryPoint.class); Assert.isTrue(entryPoints.size() != 0, "No AuthenticationEntryPoint instances defined"); Assert.isTrue(entryPoints.size() == 1, "More than one AuthenticationEntryPoint defined in context"); entryPoint = entryPoints.values().toArray()[0]; } logger.info("Using bean '" + entryPoint + "' as the entry point."); etf.setAuthenticationEntryPoint((AuthenticationEntryPoint) entryPoint); return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-security-2.0.1.xsdspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-s0000644000000000000000000016537011623517156030527 0ustar Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Whether a string should be base64 encoded Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. Specifies an IP port number. Used to configure an embedded LDAP server, for example. Specifies a URL. A bean identifier, used for referring to the bean elsewhere in the context. Defines a reference to a Spring bean Id. Defines a reference to a cache for use with a UserDetailsService. A reference to a user-service (or UserDetailsService bean) Id Defines a reference to a Spring bean Id. Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Whether a string should be base64 encoded A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied. A bean identifier, used for referring to the bean elsewhere in the context. Specifies a URL. Specifies an IP port number. Used to configure an embedded LDAP server, for example. Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used. Explicitly specifies an ldif file resource to load into an embedded LDAP server Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org" The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. Search base for group membership searches. Defaults to "ou=groups". Search base for user searches. Defaults to "". The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object A bean identifier, used for referring to the bean elsewhere in the context. The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Search base for user searches. Defaults to "". Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. Search base for group membership searches. Defaults to "ou=groups". The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". Defines a reference to a cache for use with a UserDetailsService. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object Sets up an ldap authentication provider Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example. A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Search base for user searches. Defaults to "". Search base for group membership searches. Defaults to "ou=groups". Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object The attribute in the directory which contains the user password. Defaults to "userPassword". Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods Optional AccessDecisionManager bean ID to be used by the created method security interceptor. Defines a protected method and the access control configuration attributes that apply to it. We strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security". A method name Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B". Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for Spring Security annotations and/or matches with the ordered list of "protect-pointcut" sub-elements. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. If you use and enable all three sources of method security metadata (ie "protect-pointcut" declarations, @Secured and also JSR 250 security annotations), the metadata sources will be queried in that order. In practical terms, this enables you to use XML to override method security metadata expressed by way of @Secured annotations, with @Secured annotations overriding method security metadata expressed by JSR 250 annotations. It is perfectly acceptable to mix and match, with a given Java type using a combination of XML, @Secured and JSR 250 to express method security metadata (albeit on different methods). Defines a protected pointcut and the access control configuration attributes that apply to it. Every bean registered in the Spring application context that provides a method that matches the pointcut will receive security authorization. Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Please ensure you have the spring-security-tiger-xxx.jar on the classpath. Defaults to "disabled". Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Defaults to "disabled". Optional AccessDecisionManager bean ID to override the default used for method security. An AspectJ expression, including the 'execution' keyword. For example, 'execution(int com.foo.TargetObject.countLength(String))' (without the quotes). Access configuration attributes list that applies to all methods matching the pointcut, e.g. "ROLE_A,ROLE_B" Container element for HTTP security configuration Specifies the access attributes and/or filter list for a particular set of URLs. Sets up a form login configuration for authentication with a username and password Adds support for X.509 client authentication. Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute) Incorporates a logout processing filter. Most web applications require a logout filter, although you may not require one if you write a controller to provider similar logic. Adds support for concurrent session control, allowing limits to be placed on the number of sessions a user can have. Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority. Defines the list of mappings between http and https ports for use in redirects Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false". Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true". Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true". Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests. Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application". Indicates whether an existing session should be invalidated when a user authenticates and a new session started. If set to "none" no change will be made. "newSession" will create a new empty session. "migrateSession" will create a new session and copy the session attributes to the new session. Defaults to "migrateSession". Allows a customized AuthenticationEntryPoint to be used. Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true" Allows the access denied page to be set (the user will be redirected here if an AccessDeniedException is raised). The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax. The access configuration attributes that apply for the configured path. The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method. The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all defined filters, will be applied to any other paths). Used to specify that a URL must be accessed over http or https Specifies the URL that will cause a logout. Spring Security will initialize a filter that responds to this particular URL. Defaults to /j_spring_security_logout if unspecified. Specifies the URL to display once the user has logged out. If not specified, defaults to /. Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true. The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check. The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application. Whether the user should always be redirected to the default-target-url after login. The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested. The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /spring_security_login?login_error and a corresponding filter to render that login failure URL when requested. Sets up form login for authentication with an Open ID identity A reference to a user-service (or UserDetailsService bean) Id Used to explicitly configure a FilterChainProxy instance with a FilterChainMap Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom. Used to explicitly configure a FilterInvocationDefinitionSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error. Specifies the access attributes and/or filter list for a particular set of URLs. A bean identifier, used for referring to the bean elsewhere in the context. as for http element Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration A reference to a user-service (or UserDetailsService bean) Id The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter". The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser". The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS". The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),". A reference to a user-service (or UserDetailsService bean) Id If you are using namespace configuration with Spring Security, an AuthenticationManager will automatically be registered. This element simple allows you to define an alias to allow you to reference the authentication-manager in your own beans. The alias you wish to use for the AuthenticationManager bean Indicates that the contained user-service should be used as an authentication source. element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example. A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. A reference to a user-service (or UserDetailsService bean) Id Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements. A bean identifier, used for referring to the bean elsewhere in the context. Represents a user in the application. The username assigned to the user. The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR" Can be set to "true" to mark an account as locked and unusable. Can be set to "true" to mark an account as disabled and unusable. Causes creation of a JDBC-based UserDetailsService. A bean identifier, used for referring to the bean elsewhere in the context. The bean ID of the DataSource which provides the required tables. Defines a reference to a cache for use with a UserDetailsService. An SQL statement to query a username, password, and enabled status given a username An SQL statement to query for a user's granted authorities given a username. An SQL statement to query user's group authorities given a username. A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Used to indicate that a filter bean declaration should be incorporated into the security filter chain. If neither the 'after' or 'before' options are supplied, then the filter must implement the Ordered interface directly. The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. The filter immediately before which the custom-filter should be placed in the chain The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter. The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. The filter immediately before which the custom-filter should be placed in the chain The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter. ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/PortMappingsBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/PortMapp0000644000000000000000000000450111623517156030513 0ustar package org.springframework.security.config; import org.springframework.security.util.PortMapperImpl; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; import java.util.List; import java.util.Iterator; import java.util.Map; import java.util.HashMap; /** * Parses a port-mappings element, producing a single {@link org.springframework.security.util.PortMapperImpl} * bean. * * @author Luke Taylor * @version $Id$ */ public class PortMappingsBeanDefinitionParser implements BeanDefinitionParser { public static final String ATT_HTTP_PORT = "http"; public static final String ATT_HTTPS_PORT = "https"; public BeanDefinition parse(Element element, ParserContext parserContext) { RootBeanDefinition portMapper = new RootBeanDefinition(PortMapperImpl.class); portMapper.setSource(parserContext.extractSource(element)); if (element != null) { List mappingElts = DomUtils.getChildElementsByTagName(element, Elements.PORT_MAPPING); if(mappingElts.isEmpty()) { parserContext.getReaderContext().error("No port-mapping child elements specified", element); } Map mappings = new HashMap(); Iterator iterator = mappingElts.iterator(); while (iterator.hasNext()) { Element elt = (Element) iterator.next(); String httpPort = elt.getAttribute(ATT_HTTP_PORT); String httpsPort = elt.getAttribute(ATT_HTTPS_PORT); if (!StringUtils.hasText(httpPort)) { parserContext.getReaderContext().error("No http port supplied in port mapping", elt); } if (!StringUtils.hasText(httpsPort)) { parserContext.getReaderContext().error("No https port supplied in port mapping", elt); } mappings.put(httpPort, httpsPort); } portMapper.getPropertyValues().addPropertyValue("portMappings", mappings); } return portMapper; } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/SecurityNamespaceHandler.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Security0000644000000000000000000000437711623517156030573 0ustar package org.springframework.security.config; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; /** * Registers the bean definition parsers for the "security" namespace (http://www.springframework.org/schema/security). * * @author Luke Taylor * @author Ben Alex * @since 2.0 * @version $Id$ */ public class SecurityNamespaceHandler extends NamespaceHandlerSupport { public void init() { // Parsers registerBeanDefinitionParser(Elements.LDAP_PROVIDER, new LdapProviderBeanDefinitionParser()); registerBeanDefinitionParser(Elements.LDAP_SERVER, new LdapServerBeanDefinitionParser()); registerBeanDefinitionParser(Elements.LDAP_USER_SERVICE, new LdapUserServiceBeanDefinitionParser()); registerBeanDefinitionParser(Elements.HTTP, new HttpSecurityBeanDefinitionParser()); registerBeanDefinitionParser(Elements.USER_SERVICE, new UserServiceBeanDefinitionParser()); registerBeanDefinitionParser(Elements.JDBC_USER_SERVICE, new JdbcUserServiceBeanDefinitionParser()); registerBeanDefinitionParser(Elements.AUTHENTICATION_PROVIDER, new AuthenticationProviderBeanDefinitionParser()); registerBeanDefinitionParser(Elements.GLOBAL_METHOD_SECURITY, new GlobalMethodSecurityBeanDefinitionParser()); registerBeanDefinitionParser(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser()); registerBeanDefinitionParser(Elements.FILTER_INVOCATION_DEFINITION_SOURCE, new FilterInvocationDefinitionSourceBeanDefinitionParser()); registerBeanDefinitionParser(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser()); // Decorators registerBeanDefinitionDecorator(Elements.INTERCEPT_METHODS, new InterceptMethodsBeanDefinitionDecorator()); registerBeanDefinitionDecorator(Elements.FILTER_CHAIN_MAP, new FilterChainMapBeanDefinitionDecorator()); registerBeanDefinitionDecorator(Elements.CUSTOM_FILTER, new OrderedFilterBeanDefinitionDecorator()); registerBeanDefinitionDecorator(Elements.CUSTOM_AUTH_PROVIDER, new CustomAuthenticationProviderBeanDefinitionDecorator()); registerBeanDefinitionDecorator(Elements.CUSTOM_AFTER_INVOCATION_PROVIDER, new CustomAfterInvocationProviderBeanDefinitionDecorator()); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-security.xslspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-s0000644000000000000000000000350211623517156030513 0ustar ,anonymous,concurrent-session-control,filter-chain,form-login,http-basic,intercept-url,logout,password-encoder,port-mappings,port-mapper,password-compare,protect,protect-pointcut,remember-me,salt-source,x509, ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/OrderedFilterBeanDefinitionDecorator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/OrderedF0000644000000000000000000001167511623517156030455 0ustar package org.springframework.security.config; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.BeanDefinitionDecorator; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.core.Ordered; import org.springframework.security.ui.FilterChainOrder; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * Adds the decorated "Filter" bean into the standard filter chain maintained by the FilterChainProxy. * This allows user to add their own custom filters to the security chain. If the user's filter * already implements Ordered, and no "order" attribute is specified, the filter's default order will be used. * * @author Luke Taylor * @version $Id$ */ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecorator { public static final String ATT_AFTER = "after"; public static final String ATT_BEFORE = "before"; public static final String ATT_POSITION = "position"; public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) { Element elt = (Element)node; String order = getOrder(elt, parserContext); BeanDefinitionBuilder wrapper = BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.config.OrderedFilterBeanDefinitionDecorator$OrderedFilterDecorator"); wrapper.addConstructorArg(holder.getBeanName()); wrapper.addConstructorArg(new RuntimeBeanReference(holder.getBeanName())); if (StringUtils.hasText(order)) { wrapper.addPropertyValue("order", order); } ConfigUtils.addHttpFilter(parserContext, wrapper.getBeanDefinition()); return holder; } /** * Attempts to get the order of the filter by parsing the 'before' or 'after' attributes. */ private String getOrder(Element elt, ParserContext pc) { String after = elt.getAttribute(ATT_AFTER); String before = elt.getAttribute(ATT_BEFORE); String position = elt.getAttribute(ATT_POSITION); if(ConfigUtils.countNonEmpty(new String[] {after, before, position}) != 1) { pc.getReaderContext().error("A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" + ATT_POSITION + "' attribute must be supplied", pc.extractSource(elt)); } if (StringUtils.hasText(position)) { return Integer.toString(FilterChainOrder.getOrder(position)); } if (StringUtils.hasText(after)) { int order = FilterChainOrder.getOrder(after); return Integer.toString(order == Integer.MAX_VALUE ? order : order + 1); } if (StringUtils.hasText(before)) { int order = FilterChainOrder.getOrder(before); return Integer.toString(order == Integer.MIN_VALUE ? order : order - 1); } return null; } static class OrderedFilterDecorator implements Filter, Ordered { private Integer order = null; private Filter delegate; private String beanName; OrderedFilterDecorator(String beanName, Filter delegate) { this.delegate = delegate; this.beanName = beanName; } public final void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { delegate.doFilter(request, response, chain); } public final void init(FilterConfig filterConfig) throws ServletException { delegate.init(filterConfig); } public final void destroy() { delegate.destroy(); } public final int getOrder() { if(order == null) { Assert.isInstanceOf(Ordered.class, delegate, "Filter '"+ beanName +"' must implement the 'Ordered' interface " + " or you must specify one of the attributes '" + ATT_AFTER + "' or '" + ATT_BEFORE + "' in <" + Elements.CUSTOM_FILTER +">"); return ((Ordered)delegate).getOrder(); } return order.intValue(); } public final void setOrder(int order) { this.order = new Integer(order); } public String getBeanName() { return beanName; } public String toString() { return "OrderedFilterDecorator[ delegate=" + delegate + "; order=" + getOrder() + "]"; } Filter getDelegate() { return delegate; } } } ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/HttpFirewallInjectionBeanPostProcessor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/HttpFire0000644000000000000000000000266111623517156030503 0ustar package org.springframework.security.config; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.security.config.BeanIds; import org.springframework.security.util.FilterChainProxy; import org.springframework.security.firewall.HttpFirewall; /** * @author Luke Taylor */ public class HttpFirewallInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware { private ConfigurableListableBeanFactory beanFactory; private String ref; public HttpFirewallInjectionBeanPostProcessor(String ref) { this.ref = ref; } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (BeanIds.FILTER_CHAIN_PROXY.equals(beanName)) { HttpFirewall fw = (HttpFirewall) beanFactory.getBean(ref); ((FilterChainProxy)bean).setFirewall(fw); } return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/BasicAuthenticationBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/BasicAut0000644000000000000000000000456011623517156030451 0ustar package org.springframework.security.config; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.ui.basicauth.BasicProcessingFilter; import org.springframework.security.ui.basicauth.BasicProcessingFilterEntryPoint; import org.w3c.dom.Element; /** * Creates a {@link BasicProcessingFilter} and {@link BasicProcessingFilterEntryPoint} and * registers them in the application context. * * @author Luke Taylor * @author Ben Alex * @version $Id$ */ public class BasicAuthenticationBeanDefinitionParser implements BeanDefinitionParser { private String realmName; public BasicAuthenticationBeanDefinitionParser(String realmName) { this.realmName = realmName; } public BeanDefinition parse(Element elt, ParserContext parserContext) { BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicProcessingFilter.class); RootBeanDefinition entryPoint = new RootBeanDefinition(BasicProcessingFilterEntryPoint.class); entryPoint.setSource(parserContext.extractSource(elt)); entryPoint.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); entryPoint.getPropertyValues().addPropertyValue("realmName", realmName); parserContext.getRegistry().registerBeanDefinition(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, entryPoint); filterBuilder.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER)); filterBuilder.addPropertyValue("authenticationEntryPoint", new RuntimeBeanReference(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT)); parserContext.getRegistry().registerBeanDefinition(BeanIds.BASIC_AUTHENTICATION_FILTER, filterBuilder.getBeanDefinition()); ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.BASIC_AUTHENTICATION_FILTER)); parserContext.registerComponent(new BeanComponentDefinition(filterBuilder.getBeanDefinition(), BeanIds.BASIC_AUTHENTICATION_FILTER)); return null; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/SaltSourceBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/SaltSour0000644000000000000000000000373611623517156030536 0ustar package org.springframework.security.config; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.providers.dao.salt.ReflectionSaltSource; import org.springframework.security.providers.dao.salt.SystemWideSaltSource; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class SaltSourceBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_USER_PROPERTY = "user-property"; static final String ATT_SYSTEM_WIDE = "system-wide"; public BeanDefinition parse(Element element, ParserContext parserContext) { RootBeanDefinition saltSource; String userProperty = element.getAttribute(ATT_USER_PROPERTY); if (StringUtils.hasText(userProperty)) { saltSource = new RootBeanDefinition(ReflectionSaltSource.class); saltSource.getPropertyValues().addPropertyValue("userPropertyToUse", userProperty); saltSource.setSource(parserContext.extractSource(element)); saltSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); return saltSource; } String systemWideSalt = element.getAttribute(ATT_SYSTEM_WIDE); if (StringUtils.hasText(systemWideSalt)) { saltSource = new RootBeanDefinition(SystemWideSaltSource.class); saltSource.getPropertyValues().addPropertyValue("systemWideSalt", systemWideSalt); saltSource.setSource(parserContext.extractSource(element)); saltSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); return saltSource; } parserContext.getReaderContext().error(Elements.SALT_SOURCE + " requires an attribute", element); return null; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/LdapServerBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/LdapServ0000644000000000000000000001637611623517156030506 0ustar package org.springframework.security.config; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttributes; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedSet; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * @author Luke Taylor * @version $Id$ */ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { private static final String CONTEXT_SOURCE_CLASS="org.springframework.security.ldap.DefaultSpringSecurityContextSource"; private final Log logger = LogFactory.getLog(getClass()); /** Defines the Url of the ldap server to use. If not specified, an embedded apache DS instance will be created */ private static final String ATT_URL = "url"; private static final String ATT_PRINCIPAL = "manager-dn"; private static final String ATT_PASSWORD = "manager-password"; // Properties which apply to embedded server only - when no Url is set /** sets the configuration suffix (default is "dc=springframework,dc=org"). */ public static final String ATT_ROOT_SUFFIX = "root"; private static final String OPT_DEFAULT_ROOT_SUFFIX = "dc=springframework,dc=org"; /** * Optionally defines an ldif resource to be loaded. Otherwise an attempt will be made to load all ldif files * found on the classpath. */ public static final String ATT_LDIF_FILE = "ldif"; private static final String OPT_DEFAULT_LDIF_FILE = "classpath*:*.ldif"; /** Defines the port the LDAP_PROVIDER server should run on */ public static final String ATT_PORT = "port"; public static final String OPT_DEFAULT_PORT = "33389"; public BeanDefinition parse(Element elt, ParserContext parserContext) { String url = elt.getAttribute(ATT_URL); RootBeanDefinition contextSource; if (!StringUtils.hasText(url)) { contextSource = createEmbeddedServer(elt, parserContext); } else { contextSource = new RootBeanDefinition(); contextSource.setBeanClassName(CONTEXT_SOURCE_CLASS); contextSource.getConstructorArgumentValues().addIndexedArgumentValue(0, url); } contextSource.setSource(parserContext.extractSource(elt)); String managerDn = elt.getAttribute(ATT_PRINCIPAL); String managerPassword = elt.getAttribute(ATT_PASSWORD); if (StringUtils.hasText(managerDn)) { if(!StringUtils.hasText(managerPassword)) { parserContext.getReaderContext().error("You must specify the " + ATT_PASSWORD + " if you supply a " + managerDn, elt); } contextSource.getPropertyValues().addPropertyValue("userDn", managerDn); contextSource.getPropertyValues().addPropertyValue("password", managerPassword); } String id = elt.getAttribute(AbstractBeanDefinitionParser.ID_ATTRIBUTE); String contextSourceId = StringUtils.hasText(id) ? id : BeanIds.CONTEXT_SOURCE; parserContext.getRegistry().registerBeanDefinition(contextSourceId, contextSource); return null; } /** * Will be called if no url attribute is supplied. * * Registers beans to create an embedded apache directory server. * * @return the BeanDefinition for the ContextSource for the embedded server. * * @see ApacheDSContainer */ private RootBeanDefinition createEmbeddedServer(Element element, ParserContext parserContext) { Object source = parserContext.extractSource(element); BeanDefinitionBuilder configuration = BeanDefinitionBuilder.rootBeanDefinition("org.apache.directory.server.configuration.MutableServerStartupConfiguration"); BeanDefinitionBuilder partition = BeanDefinitionBuilder.rootBeanDefinition("org.apache.directory.server.core.partition.impl.btree.MutableBTreePartitionConfiguration"); configuration.setSource(source); partition.setSource(source); Attributes rootAttributes = new BasicAttributes("dc", "springsecurity"); Attribute a = new BasicAttribute("objectClass"); a.add("top"); a.add("domain"); a.add("extensibleObject"); rootAttributes.put(a); partition.addPropertyValue("name", "springsecurity"); partition.addPropertyValue("contextEntry", rootAttributes); String suffix = element.getAttribute(ATT_ROOT_SUFFIX); if (!StringUtils.hasText(suffix)) { suffix = OPT_DEFAULT_ROOT_SUFFIX; } partition.addPropertyValue("suffix", suffix); ManagedSet partitions = new ManagedSet(1); partitions.add(partition.getBeanDefinition()); String port = element.getAttribute(ATT_PORT); if (!StringUtils.hasText(port)) { port = OPT_DEFAULT_PORT; } configuration.addPropertyValue("ldapPort", port); // We shut down the server ourself when the app context is closed so we don't need // the extra shutdown hook from apache DS itself. configuration.addPropertyValue("shutdownHookEnabled", Boolean.FALSE); configuration.addPropertyValue("exitVmOnShutdown", Boolean.FALSE); configuration.addPropertyValue("contextPartitionConfigurations", partitions); String url = "ldap://127.0.0.1:" + port + "/" + suffix; BeanDefinitionBuilder contextSource = BeanDefinitionBuilder.rootBeanDefinition(CONTEXT_SOURCE_CLASS); contextSource.addConstructorArg(url); contextSource.addPropertyValue("userDn", "uid=admin,ou=system"); contextSource.addPropertyValue("password", "secret"); RootBeanDefinition apacheContainer = new RootBeanDefinition("org.springframework.security.config.ApacheDSContainer", null, null); apacheContainer.setSource(source); apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(configuration.getBeanDefinition()); apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(contextSource.getBeanDefinition()); String ldifs = element.getAttribute(ATT_LDIF_FILE); if (!StringUtils.hasText(ldifs)) { ldifs = OPT_DEFAULT_LDIF_FILE; } apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(ldifs); logger.info("Embedded LDAP server bean created for URL: " + url); if (parserContext.getRegistry().containsBeanDefinition(BeanIds.EMBEDDED_APACHE_DS)) { parserContext.getReaderContext().error("Only one embedded server bean is allowed per application context", element); } parserContext.getRegistry().registerBeanDefinition(BeanIds.EMBEDDED_APACHE_DS, apacheContainer); return (RootBeanDefinition) contextSource.getBeanDefinition(); } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/AuthenticationManagerBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Authenti0000644000000000000000000000474311623517156030542 0ustar package org.springframework.security.config; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * Registers an alias name for the default ProviderManager used by the namespace * configuration, allowing users to reference it in their beans and clearly see where the name is * coming from. Also allows the ConcurrentSessionController to be set on the ProviderManager. * * @author Luke Taylor * @version $Id$ */ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinitionParser { private static final String ATT_SESSION_CONTROLLER_REF = "session-controller-ref"; private static final String ATT_ALIAS = "alias"; public BeanDefinition parse(Element element, ParserContext parserContext) { ConfigUtils.registerProviderManagerIfNecessary(parserContext); String alias = element.getAttribute(ATT_ALIAS); if (!StringUtils.hasText(alias)) { parserContext.getReaderContext().error(ATT_ALIAS + " is required.", element ); } String sessionControllerRef = element.getAttribute(ATT_SESSION_CONTROLLER_REF); if (StringUtils.hasText(sessionControllerRef)) { BeanDefinition authManager = parserContext.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER); ConfigUtils.setSessionControllerOnAuthenticationManager(parserContext, BeanIds.CONCURRENT_SESSION_CONTROLLER, element); authManager.getPropertyValues().addPropertyValue("sessionController", new RuntimeBeanReference(sessionControllerRef)); RootBeanDefinition sessionRegistryInjector = new RootBeanDefinition(SessionRegistryInjectionBeanPostProcessor.class); sessionRegistryInjector.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); sessionRegistryInjector.getConstructorArgumentValues().addGenericArgumentValue(sessionControllerRef); parserContext.getRegistry().registerBeanDefinition(BeanIds.SESSION_REGISTRY_INJECTION_POST_PROCESSOR, sessionRegistryInjector); } parserContext.getRegistry().registerAlias(BeanIds.AUTHENTICATION_MANAGER, alias); return null; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/LdapConfigUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/LdapConf0000644000000000000000000000664011623517156030445 0ustar package org.springframework.security.config; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.core.Ordered; import org.springframework.security.ldap.SpringSecurityContextSource; /** * @author Luke Taylor * @version $Id$ * @since 2.0 */ class LdapConfigUtils { /** * Checks for the presence of a ContextSource instance. Also supplies the standard reference to any * unconfigured or beans. This is * necessary in cases where the user has given the server a specific Id, but hasn't used * the server-ref attribute to link this to the other ldap definitions. See SEC-799. */ private static class ContextSourceSettingPostProcessor implements BeanFactoryPostProcessor, Ordered { /** If set to true, a bean parser has indicated that the default context source name needs to be set */ private boolean defaultNameRequired; public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException { String[] sources = bf.getBeanNamesForType(SpringSecurityContextSource.class); if (sources.length == 0) { throw new SecurityConfigurationException("No SpringSecurityContextSource instances found. Have you " + "added an <" + Elements.LDAP_SERVER + " /> element to your application context?"); } if (!bf.containsBean(BeanIds.CONTEXT_SOURCE) && defaultNameRequired) { if (sources.length > 1) { throw new SecurityConfigurationException("More than one SpringSecurityContextSource instance found. " + "Please specify a specific server id using the 'server-ref' attribute when configuring your <" + Elements.LDAP_PROVIDER + "> " + "or <" + Elements.LDAP_USER_SERVICE + ">."); } bf.registerAlias(sources[0], BeanIds.CONTEXT_SOURCE); } } public void setDefaultNameRequired(boolean defaultNameRequired) { this.defaultNameRequired = defaultNameRequired; } public int getOrder() { return LOWEST_PRECEDENCE; } } static void registerPostProcessorIfNecessary(BeanDefinitionRegistry registry, boolean defaultNameRequired) { if (registry.containsBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR)) { if (defaultNameRequired) { BeanDefinition bd = registry.getBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR); bd.getPropertyValues().addPropertyValue("defaultNameRequired", Boolean.valueOf(defaultNameRequired)); } return; } BeanDefinition bd = new RootBeanDefinition(ContextSourceSettingPostProcessor.class); registry.registerBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR, bd); bd.getPropertyValues().addPropertyValue("defaultNameRequired", Boolean.valueOf(defaultNameRequired)); } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/GlobalMethodSecurityBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/GlobalMe0000644000000000000000000002237611623517156030445 0ustar package org.springframework.security.config; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.springframework.aop.config.AopNamespaceUtils; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.method.DelegatingMethodDefinitionSource; import org.springframework.security.intercept.method.MapBasedMethodDefinitionSource; import org.springframework.security.intercept.method.ProtectPointcutPostProcessor; import org.springframework.security.intercept.method.aopalliance.MethodDefinitionSourceAdvisor; import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; /** * Processes the top-level "global-method-security" element. * * @author Ben Alex * @version $Id$ */ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser { public static final String SECURED_DEPENDENCY_CLASS = "org.springframework.security.annotation.Secured"; public static final String SECURED_METHOD_DEFINITION_SOURCE_CLASS = "org.springframework.security.annotation.SecuredMethodDefinitionSource"; public static final String JSR_250_SECURITY_METHOD_DEFINITION_SOURCE_CLASS = "org.springframework.security.annotation.Jsr250MethodDefinitionSource"; public static final String JSR_250_VOTER_CLASS = "org.springframework.security.annotation.Jsr250Voter"; private static final String ATT_ACCESS = "access"; private static final String ATT_EXPRESSION = "expression"; private static final String ATT_ACCESS_MGR = "access-decision-manager-ref"; private static final String ATT_USE_JSR250 = "jsr250-annotations"; private static final String ATT_USE_SECURED = "secured-annotations"; public BeanDefinition parse(Element element, ParserContext parserContext) { Object source = parserContext.extractSource(element); // The list of method metadata delegates ManagedList delegates = new ManagedList(); boolean jsr250Enabled = registerAnnotationBasedMethodDefinitionSources(element, parserContext, delegates); MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource = new MapBasedMethodDefinitionSource(); delegates.add(mapBasedMethodDefinitionSource); // Now create a Map for each sub-element Map pointcutMap = parseProtectPointcuts(parserContext, DomUtils.getChildElementsByTagName(element, Elements.PROTECT_POINTCUT)); if (pointcutMap.size() > 0) { registerProtectPointcutPostProcessor(parserContext, pointcutMap, mapBasedMethodDefinitionSource, source); } registerDelegatingMethodDefinitionSource(parserContext, delegates, source); // Register the applicable AccessDecisionManager, handling the special JSR 250 voter if being used String accessManagerId = element.getAttribute(ATT_ACCESS_MGR); if (!StringUtils.hasText(accessManagerId)) { ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext); if (jsr250Enabled) { ConfigUtils.addVoter(new RootBeanDefinition(JSR_250_VOTER_CLASS, null, null), parserContext); } accessManagerId = BeanIds.ACCESS_MANAGER; } registerMethodSecurityInterceptor(parserContext, accessManagerId, source); registerAdvisor(parserContext, source); AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element); return null; } /** * Checks whether JSR-250 and/or Secured annotations are enabled and adds the appropriate * MethodDefinitionSource delegates if required. */ private boolean registerAnnotationBasedMethodDefinitionSources(Element element, ParserContext pc, ManagedList delegates) { boolean useJsr250 = "enabled".equals(element.getAttribute(ATT_USE_JSR250)); boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED)); if (useSecured) { delegates.add(BeanDefinitionBuilder.rootBeanDefinition(SECURED_METHOD_DEFINITION_SOURCE_CLASS).getBeanDefinition()); } if (useJsr250) { delegates.add(BeanDefinitionBuilder.rootBeanDefinition(JSR_250_SECURITY_METHOD_DEFINITION_SOURCE_CLASS).getBeanDefinition()); } return useJsr250; } private void registerDelegatingMethodDefinitionSource(ParserContext parserContext, ManagedList delegates, Object source) { if (parserContext.getRegistry().containsBeanDefinition(BeanIds.DELEGATING_METHOD_DEFINITION_SOURCE)) { parserContext.getReaderContext().error("Duplicate detected.", source); } RootBeanDefinition delegatingMethodDefinitionSource = new RootBeanDefinition(DelegatingMethodDefinitionSource.class); delegatingMethodDefinitionSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); delegatingMethodDefinitionSource.setSource(source); delegatingMethodDefinitionSource.getPropertyValues().addPropertyValue("methodDefinitionSources", delegates); parserContext.getRegistry().registerBeanDefinition(BeanIds.DELEGATING_METHOD_DEFINITION_SOURCE, delegatingMethodDefinitionSource); } private void registerProtectPointcutPostProcessor(ParserContext parserContext, Map pointcutMap, MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource, Object source) { RootBeanDefinition ppbp = new RootBeanDefinition(ProtectPointcutPostProcessor.class); ppbp.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); ppbp.setSource(source); ppbp.getConstructorArgumentValues().addGenericArgumentValue(mapBasedMethodDefinitionSource); ppbp.getPropertyValues().addPropertyValue("pointcutMap", pointcutMap); parserContext.getRegistry().registerBeanDefinition(BeanIds.PROTECT_POINTCUT_POST_PROCESSOR, ppbp); } private Map parseProtectPointcuts(ParserContext parserContext, List protectPointcutElts) { Map pointcutMap = new LinkedHashMap(); for (Iterator i = protectPointcutElts.iterator(); i.hasNext();) { Element childElt = (Element) i.next(); String accessConfig = childElt.getAttribute(ATT_ACCESS); String expression = childElt.getAttribute(ATT_EXPRESSION); if (!StringUtils.hasText(accessConfig)) { parserContext.getReaderContext().error("Access configuration required", parserContext.extractSource(childElt)); } if (!StringUtils.hasText(expression)) { parserContext.getReaderContext().error("Pointcut expression required", parserContext.extractSource(childElt)); } ConfigAttributeDefinition def = new ConfigAttributeDefinition(StringUtils.commaDelimitedListToStringArray(accessConfig)); pointcutMap.put(expression, def); } return pointcutMap; } private void registerMethodSecurityInterceptor(ParserContext parserContext, String accessManagerId, Object source) { RootBeanDefinition interceptor = new RootBeanDefinition(MethodSecurityInterceptor.class); interceptor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); interceptor.setSource(source); interceptor.getPropertyValues().addPropertyValue("accessDecisionManager", new RuntimeBeanReference(accessManagerId)); interceptor.getPropertyValues().addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER)); interceptor.getPropertyValues().addPropertyValue("objectDefinitionSource", new RuntimeBeanReference(BeanIds.DELEGATING_METHOD_DEFINITION_SOURCE)); parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_SECURITY_INTERCEPTOR, interceptor); parserContext.registerComponent(new BeanComponentDefinition(interceptor, BeanIds.METHOD_SECURITY_INTERCEPTOR)); parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_SECURITY_INTERCEPTOR_POST_PROCESSOR, new RootBeanDefinition(MethodSecurityInterceptorPostProcessor.class)); } private void registerAdvisor(ParserContext parserContext, Object source) { RootBeanDefinition advisor = new RootBeanDefinition(MethodDefinitionSourceAdvisor.class); advisor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); advisor.setSource(source); advisor.getConstructorArgumentValues().addGenericArgumentValue(BeanIds.METHOD_SECURITY_INTERCEPTOR); advisor.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference(BeanIds.DELEGATING_METHOD_DEFINITION_SOURCE)); parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_DEFINITION_SOURCE_ADVISOR, advisor); } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/FormLoginBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/FormLogi0000644000000000000000000001575511623517156030504 0ustar package org.springframework.security.config; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint; import org.springframework.security.ui.webapp.DefaultLoginPageGeneratingFilter; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * @author Luke Taylor * @author Ben Alex * @version $Id$ */ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser { protected final Log logger = LogFactory.getLog(getClass()); static final String ATT_LOGIN_URL = "login-processing-url"; static final String ATT_LOGIN_PAGE = "login-page"; static final String DEF_LOGIN_PAGE = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL; static final String ATT_FORM_LOGIN_TARGET_URL = "default-target-url"; static final String ATT_ALWAYS_USE_DEFAULT_TARGET_URL = "always-use-default-target"; static final String DEF_FORM_LOGIN_TARGET_URL = "/"; static final String ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_URL = "authentication-failure-url"; static final String DEF_FORM_LOGIN_AUTHENTICATION_FAILURE_URL = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL + "?" + DefaultLoginPageGeneratingFilter.ERROR_PARAMETER_NAME; String defaultLoginProcessingUrl; String filterClassName; RootBeanDefinition filterBean; RootBeanDefinition entryPointBean; String loginPage; FormLoginBeanDefinitionParser(String defaultLoginProcessingUrl, String filterClassName) { this.defaultLoginProcessingUrl = defaultLoginProcessingUrl; this.filterClassName = filterClassName; } public BeanDefinition parse(Element elt, ParserContext pc) { String loginUrl = null; String defaultTargetUrl = null; String authenticationFailureUrl = null; String alwaysUseDefault = null; Object source = null; // Copy values from the session fixation protection filter final Boolean sessionFixationProtectionEnabled = new Boolean(pc.getRegistry().containsBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER)); Boolean migrateSessionAttributes = Boolean.FALSE; if (sessionFixationProtectionEnabled.booleanValue()) { PropertyValue pv = pc.getRegistry().getBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER) .getPropertyValues().getPropertyValue("migrateSessionAttributes"); migrateSessionAttributes = (Boolean)pv.getValue(); } if (elt != null) { source = pc.extractSource(elt); loginUrl = elt.getAttribute(ATT_LOGIN_URL); ConfigUtils.validateHttpRedirect(loginUrl, pc, source); defaultTargetUrl = elt.getAttribute(ATT_FORM_LOGIN_TARGET_URL); ConfigUtils.validateHttpRedirect(defaultTargetUrl, pc, source); authenticationFailureUrl = elt.getAttribute(ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_URL); ConfigUtils.validateHttpRedirect(authenticationFailureUrl, pc, source); alwaysUseDefault = elt.getAttribute(ATT_ALWAYS_USE_DEFAULT_TARGET_URL); loginPage = elt.getAttribute(ATT_LOGIN_PAGE); if (!StringUtils.hasText(loginPage)) { loginPage = null; } ConfigUtils.validateHttpRedirect(loginPage, pc, source); } ConfigUtils.registerProviderManagerIfNecessary(pc); filterBean = createFilterBean(loginUrl, defaultTargetUrl, alwaysUseDefault, loginPage, authenticationFailureUrl); filterBean.setSource(source); filterBean.getPropertyValues().addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER)); filterBean.getPropertyValues().addPropertyValue("invalidateSessionOnSuccessfulAuthentication", sessionFixationProtectionEnabled); filterBean.getPropertyValues().addPropertyValue("migrateInvalidatedSessionAttributes", migrateSessionAttributes); if (pc.getRegistry().containsBeanDefinition(BeanIds.REMEMBER_ME_SERVICES)) { filterBean.getPropertyValues().addPropertyValue("rememberMeServices", new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES) ); } if (pc.getRegistry().containsBeanDefinition(BeanIds.SESSION_REGISTRY)) { filterBean.getPropertyValues().addPropertyValue("sessionRegistry", new RuntimeBeanReference(BeanIds.SESSION_REGISTRY)); } BeanDefinitionBuilder entryPointBuilder = BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProcessingFilterEntryPoint.class); entryPointBuilder.setSource(source); entryPointBuilder.addPropertyValue("loginFormUrl", loginPage != null ? loginPage : DEF_LOGIN_PAGE); entryPointBean = (RootBeanDefinition) entryPointBuilder.getBeanDefinition(); return null; } private RootBeanDefinition createFilterBean(String loginUrl, String defaultTargetUrl, String alwaysUseDefault, String loginPage, String authenticationFailureUrl) { BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(filterClassName); if (!StringUtils.hasText(loginUrl)) { loginUrl = defaultLoginProcessingUrl; } if ("true".equals(alwaysUseDefault)) { filterBuilder.addPropertyValue("alwaysUseDefaultTargetUrl", Boolean.TRUE); } filterBuilder.addPropertyValue("filterProcessesUrl", loginUrl); if (!StringUtils.hasText(defaultTargetUrl)) { defaultTargetUrl = DEF_FORM_LOGIN_TARGET_URL; } filterBuilder.addPropertyValue("defaultTargetUrl", defaultTargetUrl); if (!StringUtils.hasText(authenticationFailureUrl)) { // Fallback to redisplaying the custom login page, if one was specified if (StringUtils.hasText(loginPage)) { authenticationFailureUrl = loginPage; } else { authenticationFailureUrl = DEF_FORM_LOGIN_AUTHENTICATION_FAILURE_URL; } } filterBuilder.addPropertyValue("authenticationFailureUrl", authenticationFailureUrl); return (RootBeanDefinition) filterBuilder.getBeanDefinition(); } RootBeanDefinition getFilterBean() { return filterBean; } RootBeanDefinition getEntryPointBean() { return entryPointBean; } String getLoginPage() { return loginPage; } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/X509BeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/X509Bean0000644000000000000000000000667011623517156030215 0ustar package org.springframework.security.config; import org.springframework.security.ui.preauth.PreAuthenticatedProcessingFilterEntryPoint; import org.springframework.security.ui.preauth.x509.X509PreAuthenticatedProcessingFilter; import org.springframework.security.ui.preauth.x509.SubjectDnX509PrincipalExtractor; import org.springframework.security.userdetails.UserDetailsByNameServiceWrapper; import org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationProvider; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * Parses x509 element in namespace, registering an {@link X509PreAuthenticatedProcessingFilter} instance and a * {@link PreAuthenticatedProcessingFilterEntryPoint}. * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class X509BeanDefinitionParser implements BeanDefinitionParser { public static final String ATT_REGEX = "subject-principal-regex"; public static final String ATT_USER_SERVICE_REF = "user-service-ref"; public BeanDefinition parse(Element element, ParserContext parserContext) { BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(X509PreAuthenticatedProcessingFilter.class); RootBeanDefinition entryPoint = new RootBeanDefinition(PreAuthenticatedProcessingFilterEntryPoint.class); Object source = parserContext.extractSource(element); filterBuilder.setSource(source); entryPoint.setSource(source); String regex = element.getAttribute(ATT_REGEX); if (StringUtils.hasText(regex)) { SubjectDnX509PrincipalExtractor extractor = new SubjectDnX509PrincipalExtractor(); extractor.setSubjectDnRegex(regex); filterBuilder.addPropertyValue("principalExtractor", extractor); } BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class); parserContext.getRegistry().registerBeanDefinition(BeanIds.X509_AUTH_PROVIDER, provider); ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.X509_AUTH_PROVIDER); String userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF); if (StringUtils.hasText(userServiceRef)) { RootBeanDefinition preAuthUserService = new RootBeanDefinition(UserDetailsByNameServiceWrapper.class); preAuthUserService.setSource(source); preAuthUserService.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef)); provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", preAuthUserService); } parserContext.getRegistry().registerBeanDefinition(BeanIds.PRE_AUTH_ENTRY_POINT, entryPoint); filterBuilder.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER)); parserContext.getRegistry().registerBeanDefinition(BeanIds.X509_FILTER, filterBuilder.getBeanDefinition()); ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.X509_FILTER)); return null; } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/HttpFirewallBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/HttpFire0000644000000000000000000000217611623517156030504 0ustar package org.springframework.security.config; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * Injects the supplied {@code HttpFirewall} bean reference into the {@code FilterChainProxy}. * * @author Luke Taylor */ public class HttpFirewallBeanDefinitionParser implements BeanDefinitionParser { public BeanDefinition parse(Element element, ParserContext pc) { String ref = element.getAttribute("ref"); if (!StringUtils.hasText(ref)) { pc.getReaderContext().error("ref attribute is required", pc.extractSource(element)); } BeanDefinitionBuilder injector = BeanDefinitionBuilder.rootBeanDefinition(HttpFirewallInjectionBeanPostProcessor.class); injector.addConstructorArg(ref); pc.getReaderContext().registerWithGeneratedName(injector.getBeanDefinition()); return null; } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/UserServiceBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/UserServ0000644000000000000000000000627711623517156030543 0ustar package org.springframework.security.config; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.security.userdetails.memory.UserMap; import org.springframework.security.userdetails.User; import org.springframework.security.util.AuthorityUtils; import org.springframework.util.StringUtils; import org.springframework.util.CollectionUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; import java.util.List; import java.util.Iterator; /** * @author Luke Taylor * @author Ben Alex * @version $Id$ */ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser { static final String ATT_PASSWORD = "password"; static final String ATT_NAME = "name"; static final String ELT_USER = "user"; static final String ATT_AUTHORITIES = "authorities"; static final String ATT_PROPERTIES = "properties"; static final String ATT_DISABLED = "disabled"; static final String ATT_LOCKED = "locked"; protected String getBeanClassName(Element element) { return "org.springframework.security.userdetails.memory.InMemoryDaoImpl"; } protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String userProperties = element.getAttribute(ATT_PROPERTIES); List userElts = DomUtils.getChildElementsByTagName(element, ELT_USER); if (StringUtils.hasText(userProperties)) { if(!CollectionUtils.isEmpty(userElts)) { throw new BeanDefinitionStoreException("Use of a properties file and user elements are mutually exclusive"); } BeanDefinition bd = new RootBeanDefinition(PropertiesFactoryBean.class); bd.getPropertyValues().addPropertyValue("location", userProperties); builder.addPropertyValue("userProperties", bd); return; } if(CollectionUtils.isEmpty(userElts)) { throw new BeanDefinitionStoreException("You must supply user definitions, either with <" + ELT_USER + "> child elements or a " + "properties file (using the '" + ATT_PROPERTIES + "' attribute)" ); } UserMap users = new UserMap(); for (Iterator i = userElts.iterator(); i.hasNext();) { Element userElt = (Element) i.next(); String userName = userElt.getAttribute(ATT_NAME); String password = userElt.getAttribute(ATT_PASSWORD); boolean locked = "true".equals(userElt.getAttribute(ATT_LOCKED)); boolean disabled = "true".equals(userElt.getAttribute(ATT_DISABLED)); users.addUser(new User(userName, password, !disabled, true, true, !locked, AuthorityUtils.commaSeparatedStringToAuthorityArray(userElt.getAttribute(ATT_AUTHORITIES)))); } builder.addPropertyValue("userMap", users); } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/SecurityConfigurationException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Security0000644000000000000000000000067611623517156030571 0ustar package org.springframework.security.config; import org.springframework.security.SpringSecurityException; /** * @author Luke Taylor * @author Ben Alex * @version $Id$ */ public class SecurityConfigurationException extends SpringSecurityException { public SecurityConfigurationException(String s) { super(s); } public SecurityConfigurationException(String s, Throwable throwable) { super(s, throwable); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/ApacheDSContainer.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/ApacheDS0000644000000000000000000001672511623517156030374 0ustar package org.springframework.security.config; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContext; import org.springframework.context.Lifecycle; import org.springframework.core.io.Resource; import org.springframework.ldap.core.ContextSource; import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.directory.server.configuration.MutableServerStartupConfiguration; import org.apache.directory.server.jndi.ServerContextFactory; import org.apache.directory.server.protocol.shared.store.LdifFileLoader; import org.apache.directory.server.core.configuration.ShutdownConfiguration; import org.apache.directory.server.core.DirectoryService; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import java.util.Properties; import java.io.File; import java.io.IOException; /** * Provides lifecycle services for the embedded apacheDS server defined by the supplied configuration. * Used by {@link LdapServerBeanDefinitionParser}. An instance will be stored in the application context for * each embedded server instance. It will start the server when the context is initialized and shut it down when * it is closed. It is intended for temporary embedded use and will not retain changes across start/stop boundaries. The * working directory is deleted on shutdown. * *

* If used repeatedly in a single JVM process with the same configuration (for example, when * repeatedly loading an application context during testing), it's important that the * application context is closed to allow the bean to be disposed of and the server shutdown * prior to attempting to start it again. *

* * @author Luke Taylor * @version $Id$ */ class ApacheDSContainer implements InitializingBean, DisposableBean, Lifecycle, ApplicationContextAware { private Log logger = LogFactory.getLog(getClass()); private MutableServerStartupConfiguration configuration; private ApplicationContext ctxt; private File workingDir; private ContextSource contextSource; private boolean running; private String ldifResources; public ApacheDSContainer(MutableServerStartupConfiguration config, ContextSource contextSource, String ldifs) { this.configuration = config; this.contextSource = contextSource; this.ldifResources = ldifs; } public void afterPropertiesSet() throws Exception { if (workingDir == null) { String apacheWorkDir = System.getProperty("apacheDSWorkDir"); if (apacheWorkDir == null) { apacheWorkDir = System.getProperty("java.io.tmpdir") + File.separator + "apacheds-spring-security"; } setWorkingDirectory(new File(apacheWorkDir)); } start(); } public void destroy() throws Exception { stop(); } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ctxt = applicationContext; } private boolean deleteDir(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); for (int i=0; i < children.length; i++) { boolean success = deleteDir(new File(dir, children[i])); if (!success) { return false; } } } return dir.delete(); } public void setWorkingDirectory(File workingDir) { Assert.notNull(workingDir); logger.info("Setting working directory for LDAP_PROVIDER: " + workingDir.getAbsolutePath()); if (workingDir.exists()) { throw new IllegalArgumentException("The specified working directory '" + workingDir.getAbsolutePath() + "' already exists. Another directory service instance may be using it or it may be from a " + " previous unclean shutdown. Please confirm and delete it or configure a different " + "working directory"); } this.workingDir = workingDir; configuration.setWorkingDirectory(workingDir); } public void start() { if (isRunning()) { return; } DirectoryService ds = DirectoryService.getInstance(configuration.getInstanceId()); if (ds.isStarted()) { throw new IllegalStateException("A DirectoryService with Id '" + configuration.getInstanceId() + "' is already running."); } logger.info("Starting directory server with Id '" + configuration.getInstanceId() + "'"); Properties env = new Properties(); env.setProperty(Context.INITIAL_CONTEXT_FACTORY, ServerContextFactory.class.getName()); env.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); env.setProperty(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system"); env.setProperty(Context.SECURITY_CREDENTIALS, "secret"); env.putAll(configuration.toJndiEnvironment()); try { new InitialDirContext(env); } catch (NamingException e) { logger.error("Failed to start directory service", e); return; } running = true; try { importLdifs(); } catch (Exception e) { logger.error("Failed to import LDIF file(s)", e); } } private void importLdifs() throws IOException, NamingException { // Import any ldif files Resource[] ldifs = ctxt.getResources(ldifResources); // Note that we can't just import using the ServerContext returned // from starting Apace DS, apparently because of the long-running issue DIRSERVER-169. // We need a standard context. DirContext dirContext = contextSource.getReadWriteContext(); if(ldifs != null && ldifs.length > 0) { try { String ldifFile = ldifs[0].getFile().getAbsolutePath(); logger.info("Loading LDIF file: " + ldifFile); LdifFileLoader loader = new LdifFileLoader(dirContext, ldifFile); loader.execute(); } finally { dirContext.close(); } } } public void stop() { Properties env = new Properties(); env.setProperty(Context.INITIAL_CONTEXT_FACTORY, ServerContextFactory.class.getName()); env.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); env.setProperty(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system"); env.setProperty(Context.SECURITY_CREDENTIALS, "secret"); ShutdownConfiguration shutdown = new ShutdownConfiguration(configuration.getInstanceId()); env.putAll(shutdown.toJndiEnvironment()); logger.info("Shutting down directory server with Id '" + configuration.getInstanceId() + "'"); try { new InitialContext(env); } catch (NamingException e) { logger.error("Failed to shutdown directory server", e); return; } running = false; if (workingDir.exists()) { logger.info("Deleting working directory " + workingDir.getAbsolutePath()); deleteDir(workingDir); } } public boolean isRunning() { return running; } } ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/AbstractUserDetailsServiceBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Abstract0000644000000000000000000000630611623517156030521 0ustar package org.springframework.security.config; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * @author Luke Taylor * @version $Id$ */ public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements BeanDefinitionParser { private static final String CACHE_REF = "cache-ref"; public static final String CACHING_SUFFIX = ".caching"; /** UserDetailsService bean Id. For use in a stateful context (i.e. in AuthenticationProviderBDP) */ private String id; protected abstract String getBeanClassName(Element element); protected abstract void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder); public BeanDefinition parse(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(getBeanClassName(element)); doParse(element, parserContext, builder); RootBeanDefinition userService = (RootBeanDefinition) builder.getBeanDefinition(); String beanId = resolveId(element, userService, parserContext); parserContext.getRegistry().registerBeanDefinition(beanId, userService); String cacheRef = element.getAttribute(CACHE_REF); // Register a caching version of the user service if there's a cache-ref if (StringUtils.hasText(cacheRef)) { BeanDefinitionBuilder cachingUSBuilder = BeanDefinitionBuilder.rootBeanDefinition(CachingUserDetailsService.class); cachingUSBuilder.addConstructorArgReference(beanId); cachingUSBuilder.addPropertyValue("userCache", new RuntimeBeanReference(cacheRef)); BeanDefinition cachingUserService = cachingUSBuilder.getBeanDefinition(); parserContext.getRegistry().registerBeanDefinition(beanId + CACHING_SUFFIX, cachingUserService); } id = beanId; return null; } private String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) throws BeanDefinitionStoreException { String id = element.getAttribute("id"); if (StringUtils.hasText(id)) { return id; } if(Elements.AUTHENTICATION_PROVIDER.equals(element.getParentNode().getNodeName())) { return parserContext.getReaderContext().generateBeanName(definition); } // If top level, use the default name or throw an exception if already used if (parserContext.getRegistry().containsBeanDefinition(BeanIds.USER_DETAILS_SERVICE)) { throw new BeanDefinitionStoreException("No id supplied and another " + "bean is already registered as " + BeanIds.USER_DETAILS_SERVICE); } return BeanIds.USER_DETAILS_SERVICE; } String getId() { return id; } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-security-2.0.xsdspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/spring-s0000644000000000000000000015632611623517156030530 0ustar Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Whether a string should be base64 encoded Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. Specifies an IP port number. Used to configure an embedded LDAP server, for example. Specifies a URL. A bean identifier, used for referring to the bean elsewhere in the context. Defines a reference to a Spring bean Id. Defines a reference to a cache for use with a UserDetailsService. A reference to a user-service (or UserDetailsService bean) Id Defines a reference to a Spring bean Id. Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Whether a string should be base64 encoded A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied. A bean identifier, used for referring to the bean elsewhere in the context. Specifies a URL. Specifies an IP port number. Used to configure an embedded LDAP server, for example. Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used. Explicitly specifies an ldif file resource to load into an embedded LDAP server Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org" The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. Search base for group membership searches. Defaults to "" (searching from the root). Search base for user searches. Defaults to "". The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". A bean identifier, used for referring to the bean elsewhere in the context. The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. Search base for group membership searches. Defaults to "ou=groups". The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". Defines a reference to a cache for use with a UserDetailsService. Sets up an ldap authentication provider Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example. A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used. Search base for group membership searches. Defaults to "ou=groups". Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user. The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn". A specific pattern used to build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present and will be substituted with the username. The attribute in the directory which contains the user password. Defaults to "userPassword". Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm. Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods Optional AccessDecisionManager bean ID to be used by the created method security interceptor. Defines a protected method and the access control configuration attributes that apply to it. We strongly advise you NOT to mix "protect" declarations with any services provided "global-method-security". A method name Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B". Provides method security for all beans registered in the Spring application context. Specifically, beans will be scanned for Spring Security annotations and/or matches with the ordered list of "protect-pointcut" sub-elements. Where there is a match, the beans will automatically be proxied and security authorization applied to the methods accordingly. If you use and enable all three sources of method security metadata (ie "protect-pointcut" declarations, @Secured and also JSR 250 security annotations), the metadata sources will be queried in that order. In practical terms, this enables you to use XML to override method security metadata expressed by way of @Secured annotations, with @Secured annotations overriding method security metadata expressed by JSR 250 annotations. It is perfectly acceptable to mix and match, with a given Java type using a combination of XML, @Secured and JSR 250 to express method security metadata (albeit on different methods). Defines a protected pointcut and the access control configuration attributes that apply to it. Every bean registered in the Spring application context that provides a method that matches the pointcut will receive security authorization. Specifies whether the use of Spring Security's @Secured annotations should be enabled for this application context. Please ensure you have the spring-security-tiger-xxx.jar on the classpath. Defaults to "disabled". Specifies whether JSR-250 style attributes are to be used (for example "RolesAllowed"). This will require the javax.annotation.security classes on the classpath. Defaults to "disabled". Optional AccessDecisionManager bean ID to override the default used for method security. An AspectJ expression, including the 'execution' keyword. For example, 'execution(int com.foo.TargetObject.countLength(String))' (without the quotes). Access configuration attributes list that applies to all methods matching the pointcut, e.g. "ROLE_A,ROLE_B" Container element for HTTP security configuration Specifies the access attributes and/or filter list for a particular set of URLs. Sets up a form login configuration for authentication with a username and password Adds support for X.509 client authentication. Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute) Incorporates a logout processing filter. Most web applications require a logout filter, although you may not require one if you write a controller to provider similar logic. Adds support for concurrent session control, allowing limits to be placed on the number of sessions a user can have. Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority. Defines the list of mappings between http and https ports for use in redirects Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false". Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true". Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true". Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests. Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application". Indicates whether an existing session should be invalidated when a user authenticates and a new session started. If set to "none" no change will be made. "newSession" will create a new empty session. "migrateSession" will create a new session and copy the session attributes to the new session. Defaults to "migrateSession". Allows a customized AuthenticationEntryPoint to be used. Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "false" Allows the access denied page to be set (the user will be redirected here if an AccessDeniedException is raised). The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax. The access configuration attributes that apply for the configured path. The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method. The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all defined filters, will be applied to any other paths). Used to specify that a URL must be accessed over http or https Specifies the URL that will cause a logout. Spring Security will initialize a filter that responds to this particular URL. Defaults to /j_spring_security_logout if unspecified. Specifies the URL to display once the user has logged out. If not specified, defaults to /. Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true. The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check. The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application. Whether the user should always be redirected to the default-target-url after login. The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested. The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /spring_security_login?login_error and a corresponding filter to render that login failure URL when requested. Sets up form login for authentication with an Open ID identity A reference to a user-service (or UserDetailsService bean) Id Used to explicitly configure a FilterChainProxy instance with a FilterChainMap Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom. Used to explicitly configure a FilterInvocationDefinitionSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error. Specifies the access attributes and/or filter list for a particular set of URLs. A bean identifier, used for referring to the bean elsewhere in the context. as for http element Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration A reference to a user-service (or UserDetailsService bean) Id The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter". The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser". The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS". The regular expression used to obtain the username from the certificate's subject. Defaults to matching on the common name using the pattern "CN=(.*?),". A reference to a user-service (or UserDetailsService bean) Id If you are using namespace configuration with Spring Security, an AuthenticationManager will automatically be registered. This element simple allows you to define an alias to allow you to reference the authentication-manager in your own beans. The alias you wish to use for the AuthenticationManager bean Indicates that the contained user-service should be used as an authentication source. element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example. A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used. A single value that will be used as the salt for a password encoder. A reference to a user-service (or UserDetailsService bean) Id Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements. A bean identifier, used for referring to the bean elsewhere in the context. Represents a user in the application. The username assigned to the user. The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR" Can be set to "true" to mark an account as locked and unusable. Causes creation of a JDBC-based UserDetailsService. A bean identifier, used for referring to the bean elsewhere in the context. The bean ID of the DataSource which provides the required tables. Defines a reference to a cache for use with a UserDetailsService. An SQL statement to query a username, password, and enabled status given a username An SQL statement to query for a user's granted authorities given a username. An SQL statement to query user's group authorities given a username. Used to indicate that a filter bean declaration should be incorporated into the security filter chain. If neither the 'after' or 'before' options are supplied, then the filter must implement the Ordered interface directly. The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. The filter immediately before which the custom-filter should be placed in the chain The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter. The filter immediately after which the custom-filter should be placed in the chain. This feature will only be needed by advanced users who wish to mix their own filters into the security filter chain and have some knowledge of the standard Spring Security filters. The filter names map to specific Spring Security implementation filters. The filter immediately before which the custom-filter should be placed in the chain The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter. ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/FilterChainProxyPostProcessor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/FilterCh0000644000000000000000000002303711623517156030456 0ustar package org.springframework.security.config; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import javax.servlet.Filter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.OrderComparator; import org.springframework.core.Ordered; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.config.ConfigUtils.FilterChainList; import org.springframework.security.context.HttpSessionContextIntegrationFilter; import org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource; import org.springframework.security.intercept.web.FilterSecurityInterceptor; import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; import org.springframework.security.providers.anonymous.AnonymousProcessingFilter; import org.springframework.security.ui.ExceptionTranslationFilter; import org.springframework.security.ui.SessionFixationProtectionFilter; import org.springframework.security.ui.basicauth.BasicProcessingFilter; import org.springframework.security.ui.webapp.AuthenticationProcessingFilter; import org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint; import org.springframework.security.ui.webapp.DefaultLoginPageGeneratingFilter; import org.springframework.security.util.FilterChainProxy; import org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter; /** * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class FilterChainProxyPostProcessor implements BeanPostProcessor, BeanFactoryAware { private Log logger = LogFactory.getLog(getClass()); private ListableBeanFactory beanFactory; public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if(!BeanIds.FILTER_CHAIN_PROXY.equals(beanName)) { return bean; } FilterChainProxy filterChainProxy = (FilterChainProxy) bean; FilterChainList filterList = (FilterChainList) beanFactory.getBean(BeanIds.FILTER_LIST); List filters = new ArrayList(filterList.getFilters()); Collections.sort(filters, new OrderComparator()); logger.info("Checking sorted filter chain: " + filters); for(int i=0; i < filters.size(); i++) { Ordered filter = (Ordered)filters.get(i); if (i > 0) { Ordered previous = (Ordered)filters.get(i-1); if (filter.getOrder() == previous.getOrder()) { throw new SecurityConfigurationException("Filters '" + unwrapFilter(filter) + "' and '" + unwrapFilter(previous) + "' have the same 'order' value. When using custom filters, " + "please make sure the positions do not conflict with default filters. " + "Alternatively you can disable the default filters by removing the corresponding " + "child elements from and avoiding the use of ."); } } } logger.info("Filter chain..."); for (int i=0; i < filters.size(); i++) { // Remove the ordered wrapper from the filter and put it back in the chain at the same position. Filter filter = unwrapFilter(filters.get(i)); logger.info("[" + i + "] - " + filter); filters.set(i, filter); } checkFilterStack(filters); // Note that this returns a copy Map filterMap = filterChainProxy.getFilterChainMap(); filterMap.put(filterChainProxy.getMatcher().getUniversalMatchPattern(), filters); filterChainProxy.setFilterChainMap(filterMap); checkLoginPageIsntProtected(filterChainProxy); logger.info("FilterChainProxy: " + filterChainProxy); return bean; } /** * Checks the filter list for possible errors and logs them */ private void checkFilterStack(List filters) { checkForDuplicates(HttpSessionContextIntegrationFilter.class, filters); checkForDuplicates(AuthenticationProcessingFilter.class, filters); checkForDuplicates(SessionFixationProtectionFilter.class, filters); checkForDuplicates(BasicProcessingFilter.class, filters); checkForDuplicates(SecurityContextHolderAwareRequestFilter.class, filters); checkForDuplicates(ExceptionTranslationFilter.class, filters); checkForDuplicates(FilterSecurityInterceptor.class, filters); } private void checkForDuplicates(Class clazz, List filters) { for (int i=0; i < filters.size(); i++) { Filter f1 = (Filter)filters.get(i); if (clazz.isAssignableFrom(f1.getClass())) { // Found the first one, check remaining for another for (int j=i+1; j < filters.size(); j++) { Filter f2 = (Filter)filters.get(j); if (clazz.isAssignableFrom(f2.getClass())) { logger.warn("Possible error: Filters at position " + i + " and " + j + " are both " + "instances of " + clazz.getName()); return; } } } } } /* Checks for the common error of having a login page URL protected by the security interceptor */ private void checkLoginPageIsntProtected(FilterChainProxy fcp) { ExceptionTranslationFilter etf = (ExceptionTranslationFilter) beanFactory.getBean(BeanIds.EXCEPTION_TRANSLATION_FILTER); if (etf.getAuthenticationEntryPoint() instanceof AuthenticationProcessingFilterEntryPoint) { String loginPage = ((AuthenticationProcessingFilterEntryPoint)etf.getAuthenticationEntryPoint()).getLoginFormUrl(); List filters = fcp.getFilters(loginPage); logger.info("Checking whether login URL '" + loginPage + "' is accessible with your configuration"); if (filters == null || filters.isEmpty()) { logger.debug("Filter chain is empty for the login page"); return; } if (loginPage.equals(DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL) && beanFactory.containsBean(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER)) { logger.debug("Default generated login page is in use"); return; } FilterSecurityInterceptor fsi = ((FilterSecurityInterceptor)beanFactory.getBean(BeanIds.FILTER_SECURITY_INTERCEPTOR)); DefaultFilterInvocationDefinitionSource fids = (DefaultFilterInvocationDefinitionSource) fsi.getObjectDefinitionSource(); ConfigAttributeDefinition cad = fids.lookupAttributes(loginPage, "POST"); if (cad == null) { logger.debug("No access attributes defined for login page URL"); if (fsi.isRejectPublicInvocations()) { logger.warn("FilterSecurityInterceptor is configured to reject public invocations." + " Your login page may not be accessible."); } return; } if (!beanFactory.containsBean(BeanIds.ANONYMOUS_PROCESSING_FILTER)) { logger.warn("The login page is being protected by the filter chain, but you don't appear to have" + " anonymous authentication enabled. This is almost certainly an error."); return; } // Simulate an anonymous access with the supplied attributes. AnonymousProcessingFilter anonPF = (AnonymousProcessingFilter) beanFactory.getBean(BeanIds.ANONYMOUS_PROCESSING_FILTER); AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", anonPF.getUserAttribute().getPassword(), anonPF.getUserAttribute().getAuthorities()); try { fsi.getAccessDecisionManager().decide(token, new Object(), cad); } catch (Exception e) { logger.warn("Anonymous access to the login page doesn't appear to be enabled. This is almost certainly " + "an error. Please check your configuration allows unauthenticated access to the configured " + "login page. (Simulated access was rejected: " + e + ")"); } } } /** * Returns the delegate filter of a wrapper, or the unchanged filter if it isn't wrapped. */ private Filter unwrapFilter(Object filter) { if (filter instanceof OrderedFilterBeanDefinitionDecorator.OrderedFilterDecorator) { return ((OrderedFilterBeanDefinitionDecorator.OrderedFilterDecorator)filter).getDelegate(); } return (Filter) filter; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = (ListableBeanFactory) beanFactory; } } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/FilterChainMapBeanDefinitionDecorator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/FilterCh0000644000000000000000000000617411623517156030461 0ustar package org.springframework.security.config; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.xml.BeanDefinitionDecorator; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.util.RegexUrlPathMatcher; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; import org.w3c.dom.Node; import java.util.*; /** * Sets the filter chain Map for a FilterChainProxy bean declaration. * * @author Luke Taylor * @version $Id$ */ class FilterChainMapBeanDefinitionDecorator implements BeanDefinitionDecorator { public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) { BeanDefinition filterChainProxy = holder.getBeanDefinition(); Map filterChainMap = new LinkedHashMap(); Element elt = (Element)node; String pathType = elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_TYPE); if (HttpSecurityBeanDefinitionParser.OPT_PATH_TYPE_REGEX.equals(pathType)) { filterChainProxy.getPropertyValues().addPropertyValue("matcher", new RegexUrlPathMatcher()); } Iterator filterChainElts = DomUtils.getChildElementsByTagName(elt, Elements.FILTER_CHAIN).iterator(); while (filterChainElts.hasNext()) { Element chain = (Element) filterChainElts.next(); String path = chain.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN); if(!StringUtils.hasText(path)) { parserContext.getReaderContext().error("The attribute '" + HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN + "' must not be empty", elt); } String filters = chain.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS); if(!StringUtils.hasText(filters)) { parserContext.getReaderContext().error("The attribute '" + HttpSecurityBeanDefinitionParser.ATT_FILTERS + "'must not be empty", elt); } if (filters.equals(HttpSecurityBeanDefinitionParser.OPT_FILTERS_NONE)) { filterChainMap.put(path, Collections.EMPTY_LIST); } else { String[] filterBeanNames = StringUtils.tokenizeToStringArray(filters, ","); ManagedList filterChain = new ManagedList(filterBeanNames.length); for (int i=0; i < filterBeanNames.length; i++) { filterChain.add(new RuntimeBeanReference(filterBeanNames[i])); } filterChainMap.put(path, filterChain); } } ManagedMap map = new ManagedMap(filterChainMap.size()); map.putAll(filterChainMap); filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", map); return holder; } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/LdapProviderBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/LdapProv0000644000000000000000000001341311623517156030502 0ustar package org.springframework.security.config; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Element; /** * Ldap authentication provider namespace configuration. * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser { private Log logger = LogFactory.getLog(getClass()); private static final String ATT_USER_DN_PATTERN = "user-dn-pattern"; private static final String ATT_USER_PASSWORD = "password-attribute"; private static final String ATT_HASH = PasswordEncoderParser.ATT_HASH; private static final String DEF_USER_SEARCH_FILTER = "uid={0}"; private static final String PROVIDER_CLASS = "org.springframework.security.providers.ldap.LdapAuthenticationProvider"; private static final String BIND_AUTH_CLASS = "org.springframework.security.providers.ldap.authenticator.BindAuthenticator"; private static final String PASSWD_AUTH_CLASS = "org.springframework.security.providers.ldap.authenticator.PasswordComparisonAuthenticator"; public BeanDefinition parse(Element elt, ParserContext parserContext) { RuntimeBeanReference contextSource = LdapUserServiceBeanDefinitionParser.parseServerReference(elt, parserContext); BeanDefinition searchBean = LdapUserServiceBeanDefinitionParser.parseSearchBean(elt, parserContext); String userDnPattern = elt.getAttribute(ATT_USER_DN_PATTERN); String[] userDnPatternArray = new String[0]; if (StringUtils.hasText(userDnPattern)) { userDnPatternArray = new String[] {userDnPattern}; // TODO: Validate the pattern and make sure it is a valid DN. } else if (searchBean == null) { logger.info("No search information or DN pattern specified. Using default search filter '" + DEF_USER_SEARCH_FILTER + "'"); BeanDefinitionBuilder searchBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(LdapUserServiceBeanDefinitionParser.LDAP_SEARCH_CLASS); searchBeanBuilder.setSource(elt); searchBeanBuilder.addConstructorArg(""); searchBeanBuilder.addConstructorArg(DEF_USER_SEARCH_FILTER); searchBeanBuilder.addConstructorArg(contextSource); searchBean = searchBeanBuilder.getBeanDefinition(); } BeanDefinitionBuilder authenticatorBuilder = BeanDefinitionBuilder.rootBeanDefinition(BIND_AUTH_CLASS); Element passwordCompareElt = DomUtils.getChildElementByTagName(elt, Elements.LDAP_PASSWORD_COMPARE); if (passwordCompareElt != null) { authenticatorBuilder = BeanDefinitionBuilder.rootBeanDefinition(PASSWD_AUTH_CLASS); String passwordAttribute = passwordCompareElt.getAttribute(ATT_USER_PASSWORD); if (StringUtils.hasText(passwordAttribute)) { authenticatorBuilder.addPropertyValue("passwordAttributeName", passwordAttribute); } Element passwordEncoderElement = DomUtils.getChildElementByTagName(passwordCompareElt, Elements.PASSWORD_ENCODER); String hash = passwordCompareElt.getAttribute(ATT_HASH); if (passwordEncoderElement != null) { if (StringUtils.hasText(hash)) { parserContext.getReaderContext().warning("Attribute 'hash' cannot be used with 'password-encoder' and " + "will be ignored.", parserContext.extractSource(elt)); } PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElement, parserContext); authenticatorBuilder.addPropertyValue("passwordEncoder", pep.getPasswordEncoder()); if (pep.getSaltSource() != null) { parserContext.getReaderContext().warning("Salt source information isn't valid when used with LDAP", passwordEncoderElement); } } else if (StringUtils.hasText(hash)) { Class encoderClass = (Class) PasswordEncoderParser.ENCODER_CLASSES.get(hash); authenticatorBuilder.addPropertyValue("passwordEncoder", new RootBeanDefinition(encoderClass)); } } authenticatorBuilder.addConstructorArg(contextSource); authenticatorBuilder.addPropertyValue("userDnPatterns", userDnPatternArray); if (searchBean != null) { authenticatorBuilder.addPropertyValue("userSearch", searchBean); } BeanDefinitionBuilder ldapProvider = BeanDefinitionBuilder.rootBeanDefinition(PROVIDER_CLASS); ldapProvider.addConstructorArg(authenticatorBuilder.getBeanDefinition()); ldapProvider.addConstructorArg(LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext)); ldapProvider.addPropertyValue("userDetailsContextMapper", LdapUserServiceBeanDefinitionParser.parseUserDetailsClass(elt, parserContext)); parserContext.getRegistry().registerBeanDefinition(BeanIds.LDAP_AUTHENTICATION_PROVIDER, ldapProvider.getBeanDefinition()); ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.LDAP_AUTHENTICATION_PROVIDER); return null; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/NamespaceAuthenticationManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Namespac0000644000000000000000000000370111623517156030501 0ustar package org.springframework.security.config; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.security.providers.ProviderManager; import org.springframework.util.Assert; /** * Extended version of {@link ProviderManager the default authentication manager} which lazily initializes * the list of {@link AuthenticationProvider}s. This prevents some of the issues that have occurred with * namespace configuration where early instantiation of a security interceptor has caused the AuthenticationManager * and thus dependent beans (typically UserDetailsService implementations or DAOs) to be initialized too early. * * @author Luke Taylor * @since 2.0.4 */ public class NamespaceAuthenticationManager extends ProviderManager implements BeanFactoryAware { BeanFactory beanFactory; List providerBeanNames; public void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; } public void afterPropertiesSet() throws Exception { Assert.notNull(providerBeanNames, "provideBeanNames has not been set"); Assert.notEmpty(providerBeanNames, "No authentication providers were found in the application context"); super.afterPropertiesSet(); } /** * Overridden to lazily-initialize the list of providers on first use. */ public List getProviders() { // We use the names array to determine whether the list has been set yet. if (providerBeanNames != null) { List providers = new ArrayList(); Iterator beanNames = providerBeanNames.iterator(); while (beanNames.hasNext()) { providers.add(beanFactory.getBean((String) beanNames.next())); } providerBeanNames = null; setProviders(providers); } return super.getProviders(); } public void setProviderBeanNames(List provideBeanNames) { this.providerBeanNames = provideBeanNames; } } ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/Concurre0000644000000000000000000001301311623517156030527 0ustar package org.springframework.security.config; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.parsing.CompositeComponentDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.concurrent.ConcurrentSessionControllerImpl; import org.springframework.security.concurrent.ConcurrentSessionFilter; import org.springframework.security.concurrent.SessionRegistryImpl; import org.springframework.security.providers.ProviderManager; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * Sets up support for concurrent session support control, creating {@link ConcurrentSessionFilter}, * {@link SessionRegistryImpl} and {@link ConcurrentSessionControllerImpl}. The session controller is also registered * with the default {@link ProviderManager} (which is automatically registered during namespace configuration). * * @author Luke Taylor * @version $Id$ */ public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_EXPIRY_URL = "expired-url"; static final String ATT_MAX_SESSIONS = "max-sessions"; static final String ATT_EXCEPTION_IF_MAX_EXCEEDED = "exception-if-maximum-exceeded"; static final String ATT_SESSION_REGISTRY_ALIAS = "session-registry-alias"; static final String ATT_SESSION_REGISTRY_REF = "session-registry-ref"; public BeanDefinition parse(Element element, ParserContext parserContext) { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); BeanDefinitionRegistry beanRegistry = parserContext.getRegistry(); String sessionRegistryId = element.getAttribute(ATT_SESSION_REGISTRY_REF); if (!StringUtils.hasText(sessionRegistryId)) { RootBeanDefinition sessionRegistry = new RootBeanDefinition(SessionRegistryImpl.class); beanRegistry.registerBeanDefinition(BeanIds.SESSION_REGISTRY, sessionRegistry); parserContext.registerComponent(new BeanComponentDefinition(sessionRegistry, BeanIds.SESSION_REGISTRY)); sessionRegistryId = BeanIds.SESSION_REGISTRY; } else { // Register the default ID as an alias so that things like session fixation filter can access it beanRegistry.registerAlias(sessionRegistryId, BeanIds.SESSION_REGISTRY); } String registryAlias = element.getAttribute(ATT_SESSION_REGISTRY_ALIAS); if (StringUtils.hasText(registryAlias)) { beanRegistry.registerAlias(sessionRegistryId, registryAlias); } BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionFilter.class); filterBuilder.addPropertyValue("sessionRegistry", new RuntimeBeanReference(sessionRegistryId)); Object source = parserContext.extractSource(element); filterBuilder.setSource(source); filterBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); String expiryUrl = element.getAttribute(ATT_EXPIRY_URL); if (StringUtils.hasText(expiryUrl)) { ConfigUtils.validateHttpRedirect(expiryUrl, parserContext, source); filterBuilder.addPropertyValue("expiredUrl", expiryUrl); } BeanDefinitionBuilder controllerBuilder = BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionControllerImpl.class); controllerBuilder.setSource(source); controllerBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); controllerBuilder.addPropertyValue("sessionRegistry", new RuntimeBeanReference(sessionRegistryId)); String maxSessions = element.getAttribute(ATT_MAX_SESSIONS); if (StringUtils.hasText(maxSessions)) { controllerBuilder.addPropertyValue("maximumSessions", maxSessions); } String exceptionIfMaximumExceeded = element.getAttribute(ATT_EXCEPTION_IF_MAX_EXCEEDED); if (StringUtils.hasText(exceptionIfMaximumExceeded)) { controllerBuilder.addPropertyValue("exceptionIfMaximumExceeded", exceptionIfMaximumExceeded); } BeanDefinition controller = controllerBuilder.getBeanDefinition(); beanRegistry.registerBeanDefinition(BeanIds.CONCURRENT_SESSION_CONTROLLER, controller); parserContext.registerComponent(new BeanComponentDefinition(controller, BeanIds.CONCURRENT_SESSION_CONTROLLER)); beanRegistry.registerBeanDefinition(BeanIds.CONCURRENT_SESSION_FILTER, filterBuilder.getBeanDefinition()); parserContext.registerComponent(new BeanComponentDefinition(filterBuilder.getBeanDefinition(), BeanIds.CONCURRENT_SESSION_FILTER)); ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.CONCURRENT_SESSION_FILTER)); ConfigUtils.setSessionControllerOnAuthenticationManager(parserContext, BeanIds.CONCURRENT_SESSION_CONTROLLER, element); parserContext.popAndRegisterContainingComponent(); return null; } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/JdbcUserServiceBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/JdbcUser0000644000000000000000000000457011623517156030460 0ustar package org.springframework.security.config; import org.springframework.util.StringUtils; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; /** * @author Luke Taylor * @version $Id$ */ public class JdbcUserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser { static final String ATT_DATA_SOURCE = "data-source-ref"; static final String ATT_USERS_BY_USERNAME_QUERY = "users-by-username-query"; static final String ATT_AUTHORITIES_BY_USERNAME_QUERY = "authorities-by-username-query"; static final String ATT_GROUP_AUTHORITIES_QUERY = "group-authorities-by-username-query"; static final String ATT_ROLE_PREFIX = "role-prefix"; protected String getBeanClassName(Element element) { return "org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager"; } protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String dataSource = element.getAttribute(ATT_DATA_SOURCE); if (dataSource != null) { builder.addPropertyReference("dataSource", dataSource); } else { parserContext.getReaderContext().error(ATT_DATA_SOURCE + " is required for " + Elements.JDBC_USER_SERVICE, parserContext.extractSource(element)); } String usersQuery = element.getAttribute(ATT_USERS_BY_USERNAME_QUERY); String authoritiesQuery = element.getAttribute(ATT_AUTHORITIES_BY_USERNAME_QUERY); String groupAuthoritiesQuery = element.getAttribute(ATT_GROUP_AUTHORITIES_QUERY); String rolePrefix = element.getAttribute(ATT_ROLE_PREFIX); if (StringUtils.hasText(rolePrefix)) { builder.addPropertyValue("rolePrefix", rolePrefix); } if (StringUtils.hasText(usersQuery)) { builder.addPropertyValue("usersByUsernameQuery", usersQuery); } if (StringUtils.hasText(authoritiesQuery)) { builder.addPropertyValue("authoritiesByUsernameQuery", authoritiesQuery); } if (StringUtils.hasText(groupAuthoritiesQuery)) { builder.addPropertyValue("enableGroups", Boolean.TRUE); builder.addPropertyValue("groupAuthoritiesByUsernameQuery", groupAuthoritiesQuery); } } } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/LogoutBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/LogoutBe0000644000000000000000000000636611623517156030504 0ustar package org.springframework.security.config; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.ui.logout.LogoutFilter; import org.springframework.security.ui.logout.SecurityContextLogoutHandler; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * @author Luke Taylor * @author Ben Alex * @version $Id$ */ public class LogoutBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_LOGOUT_SUCCESS_URL = "logout-success-url"; static final String DEF_LOGOUT_SUCCESS_URL = "/"; static final String ATT_INVALIDATE_SESSION = "invalidate-session"; static final String DEF_INVALIDATE_SESSION = "true"; static final String ATT_LOGOUT_URL = "logout-url"; static final String DEF_LOGOUT_URL = "/j_spring_security_logout"; String rememberMeServices; public LogoutBeanDefinitionParser(String rememberMeServices) { this.rememberMeServices = rememberMeServices; } public BeanDefinition parse(Element element, ParserContext parserContext) { String logoutUrl = null; String logoutSuccessUrl = null; String invalidateSession = null; BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class); if (element != null) { Object source = parserContext.extractSource(element); builder.setSource(source); logoutUrl = element.getAttribute(ATT_LOGOUT_URL); ConfigUtils.validateHttpRedirect(logoutUrl, parserContext, source); logoutSuccessUrl = element.getAttribute(ATT_LOGOUT_SUCCESS_URL); ConfigUtils.validateHttpRedirect(logoutSuccessUrl, parserContext, source); invalidateSession = element.getAttribute(ATT_INVALIDATE_SESSION); } if (!StringUtils.hasText(logoutUrl)) { logoutUrl = DEF_LOGOUT_URL; } builder.addPropertyValue("filterProcessesUrl", logoutUrl); if (!StringUtils.hasText(logoutSuccessUrl)) { logoutSuccessUrl = DEF_LOGOUT_SUCCESS_URL; } builder.addConstructorArg(logoutSuccessUrl); if (!StringUtils.hasText(invalidateSession)) { invalidateSession = DEF_INVALIDATE_SESSION; } ManagedList handlers = new ManagedList(); SecurityContextLogoutHandler sclh = new SecurityContextLogoutHandler(); if ("true".equals(invalidateSession)) { sclh.setInvalidateHttpSession(true); } else { sclh.setInvalidateHttpSession(false); } handlers.add(sclh); if (rememberMeServices != null) { handlers.add(new RuntimeBeanReference(rememberMeServices)); } builder.addConstructorArg(handlers); parserContext.getRegistry().registerBeanDefinition(BeanIds.LOGOUT_FILTER, builder.getBeanDefinition()); ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.LOGOUT_FILTER)); return null; } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/LdapUserServiceBeanDefinitionParser.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/LdapUser0000644000000000000000000001476111623517156030501 0ustar package org.springframework.security.config; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser { public static final String ATT_SERVER = "server-ref"; public static final String ATT_USER_SEARCH_FILTER = "user-search-filter"; public static final String ATT_USER_SEARCH_BASE = "user-search-base"; public static final String DEF_USER_SEARCH_BASE = ""; public static final String ATT_GROUP_SEARCH_FILTER = "group-search-filter"; public static final String ATT_GROUP_SEARCH_BASE = "group-search-base"; public static final String ATT_GROUP_ROLE_ATTRIBUTE = "group-role-attribute"; public static final String DEF_GROUP_SEARCH_FILTER = "(uniqueMember={0})"; public static final String DEF_GROUP_SEARCH_BASE = ""; static final String ATT_ROLE_PREFIX = "role-prefix"; static final String ATT_USER_CLASS = "user-details-class"; static final String OPT_PERSON = "person"; static final String OPT_INETORGPERSON = "inetOrgPerson"; public static final String LDAP_SEARCH_CLASS = "org.springframework.security.ldap.search.FilterBasedLdapUserSearch"; public static final String PERSON_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.PersonContextMapper"; public static final String INET_ORG_PERSON_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.InetOrgPersonContextMapper"; public static final String LDAP_USER_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.LdapUserDetailsMapper"; public static final String LDAP_AUTHORITIES_POPULATOR_CLASS = "org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator"; protected String getBeanClassName(Element element) { return "org.springframework.security.userdetails.ldap.LdapUserDetailsService"; } protected void doParse(Element elt, ParserContext parserContext, BeanDefinitionBuilder builder) { if (!StringUtils.hasText(elt.getAttribute(ATT_USER_SEARCH_FILTER))) { parserContext.getReaderContext().error("User search filter must be supplied", elt); } builder.addConstructorArg(parseSearchBean(elt, parserContext)); builder.addConstructorArg(parseAuthoritiesPopulator(elt, parserContext)); builder.addPropertyValue("userDetailsMapper", parseUserDetailsClass(elt, parserContext)); } static RootBeanDefinition parseSearchBean(Element elt, ParserContext parserContext) { String userSearchFilter = elt.getAttribute(ATT_USER_SEARCH_FILTER); String userSearchBase = elt.getAttribute(ATT_USER_SEARCH_BASE); Object source = parserContext.extractSource(elt); if (StringUtils.hasText(userSearchBase)) { if(!StringUtils.hasText(userSearchFilter)) { parserContext.getReaderContext().error(ATT_USER_SEARCH_BASE + " cannot be used without a " + ATT_USER_SEARCH_FILTER, source); } } else { userSearchBase = DEF_USER_SEARCH_BASE; } if (!StringUtils.hasText(userSearchFilter)) { return null; } BeanDefinitionBuilder searchBuilder = BeanDefinitionBuilder.rootBeanDefinition(LDAP_SEARCH_CLASS); searchBuilder.setSource(source); searchBuilder.addConstructorArg(userSearchBase); searchBuilder.addConstructorArg(userSearchFilter); searchBuilder.addConstructorArg(parseServerReference(elt, parserContext)); return (RootBeanDefinition) searchBuilder.getBeanDefinition(); } static RuntimeBeanReference parseServerReference(Element elt, ParserContext parserContext) { String server = elt.getAttribute(ATT_SERVER); boolean requiresDefaultName = false; if (!StringUtils.hasText(server)) { server = BeanIds.CONTEXT_SOURCE; requiresDefaultName = true; } RuntimeBeanReference contextSource = new RuntimeBeanReference(server); contextSource.setSource(parserContext.extractSource(elt)); LdapConfigUtils.registerPostProcessorIfNecessary(parserContext.getRegistry(), requiresDefaultName); return contextSource; } static RootBeanDefinition parseUserDetailsClass(Element elt, ParserContext parserContext) { String userDetailsClass = elt.getAttribute(ATT_USER_CLASS); if (OPT_PERSON.equals(userDetailsClass)) { return new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null); } else if (OPT_INETORGPERSON.equals(userDetailsClass)) { return new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null); } return new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null); } static RootBeanDefinition parseAuthoritiesPopulator(Element elt, ParserContext parserContext) { String groupSearchFilter = elt.getAttribute(ATT_GROUP_SEARCH_FILTER); String groupSearchBase = elt.getAttribute(ATT_GROUP_SEARCH_BASE); String groupRoleAttribute = elt.getAttribute(ATT_GROUP_ROLE_ATTRIBUTE); String rolePrefix = elt.getAttribute(ATT_ROLE_PREFIX); if (!StringUtils.hasText(groupSearchFilter)) { groupSearchFilter = DEF_GROUP_SEARCH_FILTER; } if (!StringUtils.hasText(groupSearchBase)) { groupSearchBase = DEF_GROUP_SEARCH_BASE; } BeanDefinitionBuilder populator = BeanDefinitionBuilder.rootBeanDefinition(LDAP_AUTHORITIES_POPULATOR_CLASS); populator.setSource(parserContext.extractSource(elt)); populator.addConstructorArg(parseServerReference(elt, parserContext)); populator.addConstructorArg(groupSearchBase); populator.addPropertyValue("groupSearchFilter", groupSearchFilter); populator.addPropertyValue("searchSubtree", Boolean.TRUE); if (StringUtils.hasText(rolePrefix)) { if ("none".equals(rolePrefix)) { rolePrefix = ""; } populator.addPropertyValue("rolePrefix", rolePrefix); } if (StringUtils.hasLength(groupRoleAttribute)) { populator.addPropertyValue("groupRoleAttribute", groupRoleAttribute); } return (RootBeanDefinition) populator.getBeanDefinition(); } } ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/UserDetailsServiceInjectionBeanPostProcessor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/config/UserDeta0000644000000000000000000001375011623517156030473 0ustar package org.springframework.security.config; import java.util.Map; import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.BeansException; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationProvider; import org.springframework.security.ui.rememberme.AbstractRememberMeServices; import org.springframework.security.userdetails.UserDetailsByNameServiceWrapper; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.util.Assert; /** * Registered by {@link HttpSecurityBeanDefinitionParser} to inject a UserDetailsService into * the X509Provider, RememberMeServices and OpenIDAuthenticationProvider instances created by * the namespace. * * @author Luke Taylor * @since 2.0.2 */ public class UserDetailsServiceInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware { private ConfigurableListableBeanFactory beanFactory; public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (BeanIds.X509_AUTH_PROVIDER.equals(beanName)) { injectUserDetailsServiceIntoX509Provider((PreAuthenticatedAuthenticationProvider) bean); } else if (BeanIds.REMEMBER_ME_SERVICES.equals(beanName)) { injectUserDetailsServiceIntoRememberMeServices((AbstractRememberMeServices)bean); } else if (BeanIds.OPEN_ID_PROVIDER.equals(beanName)) { injectUserDetailsServiceIntoOpenIDProvider(bean); } return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } private void injectUserDetailsServiceIntoRememberMeServices(AbstractRememberMeServices services) { BeanDefinition beanDefinition = beanFactory.getBeanDefinition(BeanIds.REMEMBER_ME_SERVICES); PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("userDetailsService"); if (pv == null) { services.setUserDetailsService(getUserDetailsService()); } else { UserDetailsService cachingUserService = getCachingUserService(pv.getValue()); if (cachingUserService != null) { services.setUserDetailsService(cachingUserService); } } } private void injectUserDetailsServiceIntoX509Provider(PreAuthenticatedAuthenticationProvider provider) { BeanDefinition beanDefinition = beanFactory.getBeanDefinition(BeanIds.X509_AUTH_PROVIDER); PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("preAuthenticatedUserDetailsService"); UserDetailsByNameServiceWrapper wrapper = new UserDetailsByNameServiceWrapper(); if (pv == null) { wrapper.setUserDetailsService(getUserDetailsService()); provider.setPreAuthenticatedUserDetailsService(wrapper); } else { RootBeanDefinition preAuthUserService = (RootBeanDefinition) pv.getValue(); Object userService = preAuthUserService.getPropertyValues().getPropertyValue("userDetailsService").getValue(); UserDetailsService cachingUserService = getCachingUserService(userService); if (cachingUserService != null) { wrapper.setUserDetailsService(cachingUserService); provider.setPreAuthenticatedUserDetailsService(wrapper); } } } private void injectUserDetailsServiceIntoOpenIDProvider(Object bean) { BeanDefinition beanDefinition = beanFactory.getBeanDefinition(BeanIds.OPEN_ID_PROVIDER); PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("userDetailsService"); if (pv == null) { BeanWrapperImpl beanWrapper = new BeanWrapperImpl(bean); beanWrapper.setPropertyValue("userDetailsService", getUserDetailsService()); } } /** * Obtains a user details service for use in RememberMeServices etc. Will return a caching version * if available so should not be used for beans which need to separate the two. */ UserDetailsService getUserDetailsService() { Map beans = beanFactory.getBeansOfType(CachingUserDetailsService.class); if (beans.size() == 0) { beans = beanFactory.getBeansOfType(UserDetailsService.class); } if (beans.size() == 0) { throw new SecurityConfigurationException("No UserDetailsService registered."); } else if (beans.size() > 1) { throw new SecurityConfigurationException("More than one UserDetailsService registered. Please " + "use a specific Id in your configuration"); } return (UserDetailsService) beans.values().toArray()[0]; } private UserDetailsService getCachingUserService(Object userServiceRef) { Assert.isInstanceOf(RuntimeBeanReference.class, userServiceRef, "userDetailsService property value must be a RuntimeBeanReference"); String id = ((RuntimeBeanReference)userServiceRef).getBeanName(); // Overwrite with the caching version if available String cachingId = id + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX; if (beanFactory.containsBeanDefinition(cachingId)) { return (UserDetailsService) beanFactory.getBean(cachingId); } return null; } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/wrapper/0000755000000000000000000000000011623517156027241 5ustar ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/wrapper/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/wrapper/package0000644000000000000000000000037411623517156030563 0ustar Populates a Servlet request with a new Spring Security compliant HttpServletRequestWrapper.

To use, simply add the SecurityContextHolderAwareRequestFilter to the Spring Security filter chain. ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/wrapper/SecurityContextHolderAwareRequestWrapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/wrapper/Securit0000644000000000000000000001250111623517156030601 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.wrapper; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationTrustResolver; import org.springframework.security.AuthenticationTrustResolverImpl; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.util.PortResolver; import java.security.Principal; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** * A Spring Security-aware HttpServletRequestWrapper, which uses the * SecurityContext-defined Authentication object for {@link * SecurityContextHolderAwareRequestWrapper#isUserInRole(java.lang.String)} and {@link * javax.servlet.http.HttpServletRequestWrapper#getRemoteUser()} responses. * * @see SecurityContextHolderAwareRequestFilter * * @author Orlando Garcia Carmona * @author Ben Alex * @version $Id$ */ public class SecurityContextHolderAwareRequestWrapper extends HttpServletRequestWrapper { //~ Instance fields ================================================================================================ private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); /** * The prefix passed by the filter. It will be prepended to any supplied role values before * comparing it with the roles obtained from the security context. */ private String rolePrefix; //~ Constructors =================================================================================================== public SecurityContextHolderAwareRequestWrapper( HttpServletRequest request, PortResolver portResolver, String rolePrefix) { super(request); this.rolePrefix = rolePrefix; } //~ Methods ======================================================================================================== /** * Obtain the current active Authentication * * @return the authentication object or null */ private Authentication getAuthentication() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (!authenticationTrustResolver.isAnonymous(auth)) { return auth; } return null; } /** * Returns the principal's name, as obtained from the SecurityContextHolder. Properly handles * both String-based and UserDetails-based principals. * * @return the username or null if unavailable */ public String getRemoteUser() { Authentication auth = getAuthentication(); if ((auth == null) || (auth.getPrincipal() == null)) { return null; } if (auth.getPrincipal() instanceof UserDetails) { return ((UserDetails) auth.getPrincipal()).getUsername(); } return auth.getPrincipal().toString(); } /** * Returns the Authentication (which is a subclass of Principal), or * null if unavailable. * * @return the Authentication, or null */ public Principal getUserPrincipal() { Authentication auth = getAuthentication(); if ((auth == null) || (auth.getPrincipal() == null)) { return null; } return auth; } private boolean isGranted(String role) { Authentication auth = getAuthentication(); if( rolePrefix != null ) { role = rolePrefix + role; } if ((auth == null) || (auth.getPrincipal() == null) || (auth.getAuthorities() == null)) { return false; } for (int i = 0; i < auth.getAuthorities().length; i++) { if (role.equals(auth.getAuthorities()[i].getAuthority())) { return true; } } return false; } /** * Simple searches for an exactly matching {@link org.springframework.security.GrantedAuthority#getAuthority()}.

Will * always return false if the SecurityContextHolder contains an * Authentication with nullprincipal and/or GrantedAuthority[] * objects.

* * @param role the GrantedAuthorityString representation to check for * * @return true if an exact (case sensitive) matching granted authority is located, * false otherwise */ public boolean isUserInRole(String role) { return isGranted(role); } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/wrapper/SavedRequestAwareWrapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/wrapper/SavedRe0000644000000000000000000002606211623517156030523 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.wrapper; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.ui.savedrequest.Enumerator; import org.springframework.security.ui.savedrequest.FastHttpDateFormat; import org.springframework.security.ui.savedrequest.SavedRequest; import org.springframework.security.util.PortResolver; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TimeZone; import java.util.Map.Entry; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * Provides request parameters, headers and cookies from either an original request or a saved request. * *

Note that not all request parameters in the original request are emulated by this wrapper. * Nevertheless, the important data from the original request is emulated and this should prove * adequate for most purposes (in particular standard HTTP GET and POST operations).

* *

Added into a request by {@link org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter}.

* * * @see SecurityContextHolderAwareRequestFilter * * @author Andrey Grebnev * @author Ben Alex * @version $Id$ */ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestWrapper { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(SavedRequestAwareWrapper.class); protected static final TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT"); /** The default Locale if none are specified. */ protected static Locale defaultLocale = Locale.getDefault(); //~ Instance fields ================================================================================================ protected SavedRequest savedRequest = null; /** * The set of SimpleDateFormat formats to use in getDateHeader(). Notice that because SimpleDateFormat is * not thread-safe, we can't declare formats[] as a static variable. */ protected SimpleDateFormat[] formats = new SimpleDateFormat[3]; //~ Constructors =================================================================================================== public SavedRequestAwareWrapper(HttpServletRequest request, PortResolver portResolver, String rolePrefix) { super(request, portResolver, rolePrefix); HttpSession session = request.getSession(false); if (session == null) { if (logger.isDebugEnabled()) { logger.debug("Wrapper not replaced; no session available for SavedRequest extraction"); } return; } SavedRequest saved = (SavedRequest) session.getAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY); if ((saved != null) && saved.doesRequestMatch(request, portResolver)) { if (logger.isDebugEnabled()) { logger.debug("Wrapper replaced; SavedRequest was: " + saved); } savedRequest = saved; session.removeAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY); formats[0] = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); formats[1] = new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US); formats[2] = new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US); formats[0].setTimeZone(GMT_ZONE); formats[1].setTimeZone(GMT_ZONE); formats[2].setTimeZone(GMT_ZONE); } else { if (logger.isDebugEnabled()) { logger.debug("Wrapper not replaced; SavedRequest was: " + saved); } } } //~ Methods ======================================================================================================== public Cookie[] getCookies() { if (savedRequest == null) { return super.getCookies(); } else { List cookies = savedRequest.getCookies(); return (Cookie[]) cookies.toArray(new Cookie[cookies.size()]); } } public long getDateHeader(String name) { if (savedRequest == null) { return super.getDateHeader(name); } else { String value = getHeader(name); if (value == null) { return -1L; } // Attempt to convert the date header in a variety of formats long result = FastHttpDateFormat.parseDate(value, formats); if (result != -1L) { return result; } throw new IllegalArgumentException(value); } } public String getHeader(String name) { if (savedRequest == null) { return super.getHeader(name); } else { String header = null; Iterator iterator = savedRequest.getHeaderValues(name); while (iterator.hasNext()) { header = (String) iterator.next(); break; } return header; } } public Enumeration getHeaderNames() { if (savedRequest == null) { return super.getHeaderNames(); } else { return new Enumerator(savedRequest.getHeaderNames()); } } public Enumeration getHeaders(String name) { if (savedRequest == null) { return super.getHeaders(name); } else { return new Enumerator(savedRequest.getHeaderValues(name)); } } public int getIntHeader(String name) { if (savedRequest == null) { return super.getIntHeader(name); } else { String value = getHeader(name); if (value == null) { return -1; } else { return Integer.parseInt(value); } } } public Locale getLocale() { if (savedRequest == null) { return super.getLocale(); } else { Locale locale = null; Iterator iterator = savedRequest.getLocales(); while (iterator.hasNext()) { locale = (Locale) iterator.next(); break; } if (locale == null) { return defaultLocale; } else { return locale; } } } public Enumeration getLocales() { if (savedRequest == null) { return super.getLocales(); } else { Iterator iterator = savedRequest.getLocales(); if (iterator.hasNext()) { return new Enumerator(iterator); } else { ArrayList results = new ArrayList(); results.add(defaultLocale); return new Enumerator(results.iterator()); } } } public String getMethod() { if (savedRequest == null) { return super.getMethod(); } else { return savedRequest.getMethod(); } } /** * If the parameter is available from the wrapped request then either *
    *
  1. There is no saved request (it a normal request)
  2. *
  3. There is a saved request, but the request has been forwarded/included to a URL with parameters, either * supplementing or overriding the saved request values.
  4. *
* In both cases the value from the wrapped request should be used. *

* If the value from the wrapped request is null, an attempt will be made to retrieve the parameter * from the SavedRequest, if available.. */ public String getParameter(String name) { String value = super.getParameter(name); if (value != null || savedRequest == null) { return value; } String[] values = savedRequest.getParameterValues(name); if (values == null) return null; for (int i = 0; i < values.length; i++) { value = values[i]; break; } return value; } public Map getParameterMap() { if (savedRequest == null) { return super.getParameterMap(); } Set names = getCombinedParameterNames(); Iterator nameIter = names.iterator(); Map parameterMap = new HashMap(names.size()); while (nameIter.hasNext()) { String name = (String) nameIter.next(); parameterMap.put(name, getParameterValues(name)); } return parameterMap; } private Set getCombinedParameterNames() { Set names = new HashSet(); names.addAll(super.getParameterMap().keySet()); if (savedRequest != null) { names.addAll(savedRequest.getParameterMap().keySet()); } return names; } public Enumeration getParameterNames() { return new Enumerator(getCombinedParameterNames()); } public String[] getParameterValues(String name) { if (savedRequest == null) { return super.getParameterValues(name); } String[] savedRequestParams = savedRequest.getParameterValues(name); String[] wrappedRequestParams = super.getParameterValues(name); if (savedRequestParams == null) { return wrappedRequestParams; } if (wrappedRequestParams == null) { return savedRequestParams; } // We have params in both saved and wrapped requests so have to merge them List wrappedParamsList = Arrays.asList(wrappedRequestParams); List combinedParams = new ArrayList(wrappedParamsList); // We want to add all parameters of the saved request *apart from* duplicates of those already added for (int i = 0; i < savedRequestParams.length; i++) { if (!wrappedParamsList.contains(savedRequestParams[i])) { combinedParams.add(savedRequestParams[i]); } } return (String[]) combinedParams.toArray(new String[combinedParams.size()]); } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/wrapper/SecurityContextHolderAwareRequestFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/wrapper/Securit0000644000000000000000000001003611623517156030602 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.wrapper; import java.io.IOException; import java.lang.reflect.Constructor; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.ui.FilterChainOrder; import org.springframework.security.ui.SpringSecurityFilter; import org.springframework.security.util.PortResolver; import org.springframework.security.util.PortResolverImpl; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; /** * A Filter which populates the ServletRequest with a new request wrapper.

Several * request wrappers are included with the framework. The simplest version is {@link * SecurityContextHolderAwareRequestWrapper}. A more complex and powerful request wrapper is {@link * org.springframework.security.wrapper.SavedRequestAwareWrapper}. The latter is also the default.

*

To modify the wrapper used, call {@link #setWrapperClass(Class)}.

*

Any request wrapper configured for instantiation by this class must provide a public constructor that * accepts two arguments, being a HttpServletRequest and a PortResolver.

* * @author Orlando Garcia Carmona * @author Ben Alex * @version $Id$ */ public class SecurityContextHolderAwareRequestFilter extends SpringSecurityFilter { //~ Instance fields ================================================================================================ private Class wrapperClass = SavedRequestAwareWrapper.class; private Constructor constructor; private PortResolver portResolver = new PortResolverImpl(); private String rolePrefix; //~ Methods ======================================================================================================== public void setPortResolver(PortResolver portResolver) { Assert.notNull(portResolver, "PortResolver required"); this.portResolver = portResolver; } public void setWrapperClass(Class wrapperClass) { Assert.notNull(wrapperClass, "WrapperClass required"); Assert.isTrue(HttpServletRequest.class.isAssignableFrom(wrapperClass), "Wrapper must be a HttpServletRequest"); this.wrapperClass = wrapperClass; } public void setRolePrefix(String rolePrefix) { Assert.notNull(rolePrefix, "Role prefix must not be null"); this.rolePrefix = rolePrefix.trim(); } protected void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (!wrapperClass.isAssignableFrom(request.getClass())) { if (constructor == null) { try { constructor = wrapperClass.getConstructor( new Class[] {HttpServletRequest.class, PortResolver.class, String.class}); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } try { request = (HttpServletRequest) constructor.newInstance(new Object[] {request, portResolver, rolePrefix}); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } chain.doFilter(request, response); } public int getOrder() { return FilterChainOrder.SERVLET_API_SUPPORT_FILTER; } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/0000755000000000000000000000000011623517156026536 5ustar ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/FieldUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/FieldUtils0000644000000000000000000001103411623517156030524 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import java.lang.reflect.Field; /** * Offers static methods for directly manipulating static fields. * * @author Ben Alex * @version $Id$ */ public final class FieldUtils { //~ Constructors =================================================================================================== private FieldUtils() { } //~ Methods ======================================================================================================== public static String getAccessorName(String fieldName, Class type) { Assert.hasText(fieldName, "FieldName required"); Assert.notNull(type, "Type required"); if (type.getName().equals("boolean")) { return "is" + org.springframework.util.StringUtils.capitalize(fieldName); } else { return "get" + org.springframework.util.StringUtils.capitalize(fieldName); } } /** * Attempts to locate the specified field on the class. * * @param clazz the class definition containing the field * @param fieldName the name of the field to locate * * @return the Field (never null) * * @throws IllegalStateException if field could not be found */ public static Field getField(Class clazz, String fieldName) throws IllegalStateException { Assert.notNull(clazz, "Class required"); Assert.hasText(fieldName, "Field name required"); try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException nsf) { // Try superclass if (clazz.getSuperclass() != null) { return getField(clazz.getSuperclass(), fieldName); } throw new IllegalStateException("Could not locate field '" + fieldName + "' on class " + clazz); } } /** * Returns the value of a (nested) field on a bean. Intended for testing. * @param bean the object * @param fieldName the field name, with "." separating nested properties * @return the value of the nested field */ public static Object getFieldValue(Object bean, String fieldName) throws IllegalAccessException { Assert.notNull(bean, "Bean cannot be null"); Assert.hasText(fieldName, "Field name required"); String[] nestedFields = StringUtils.tokenizeToStringArray(fieldName, "."); Class componentClass = bean.getClass(); Field field = null; Object value = bean; for (int i=0; i < nestedFields.length; i++) { field = getField(componentClass, nestedFields[i]); field.setAccessible(true); value = field.get(value); componentClass = value.getClass(); } return value; } public static String getMutatorName(String fieldName) { Assert.hasText(fieldName, "FieldName required"); return "set" + org.springframework.util.StringUtils.capitalize(fieldName); } public static Object getProtectedFieldValue(String protectedField, Object object) { Field field = FieldUtils.getField(object.getClass(), protectedField); try { field.setAccessible(true); return field.get(object); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); return null; // unreachable - previous line throws exception } } public static void setProtectedFieldValue(String protectedField, Object object, Object newValue) { Field field = FieldUtils.getField(object.getClass(), protectedField); try { field.setAccessible(true); field.set(object, newValue); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/ThrowableAnalyzer.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/ThrowableA0000644000000000000000000002442411623517156030517 0ustar package org.springframework.security.util; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; /** * Handler for analyzing {@link Throwable} instances. * * Can be subclassed to customize its behavior. * * @author Andreas Senft * @since 2.0 * @version $Id$ */ public class ThrowableAnalyzer { /** * Default extractor for {@link Throwable} instances. * * @see Throwable#getCause() */ public static final ThrowableCauseExtractor DEFAULT_EXTRACTOR = new ThrowableCauseExtractor() { public Throwable extractCause(Throwable throwable) { return throwable.getCause(); } }; /** * Default extractor for {@link InvocationTargetException} instances. * * @see InvocationTargetException#getTargetException() */ public static final ThrowableCauseExtractor INVOCATIONTARGET_EXTRACTOR = new ThrowableCauseExtractor() { public Throwable extractCause(Throwable throwable) { verifyThrowableHierarchy(throwable, InvocationTargetException.class); return ((InvocationTargetException) throwable).getTargetException(); } }; /** * Comparator to order classes ascending according to their hierarchy relation. * If two classes have a hierarchical relation, the "higher" class is considered * to be greater by this comparator.
* For hierarchically unrelated classes their fully qualified name will be compared. */ private static final Comparator CLASS_HIERARCHY_COMPARATOR = new Comparator() { public int compare(Object o1, Object o2) { Class class1 = (Class) o1; Class class2 = (Class) o2; if (class1.isAssignableFrom(class2)) { return 1; } else if (class2.isAssignableFrom(class1)) { return -1; } else { return class1.getName().compareTo(class2.getName()); } } }; /** * Map of registered cause extractors. * key: Class; value: ThrowableCauseExctractor */ private final Map extractorMap; /** * Creates a new ThrowableAnalyzer instance. */ public ThrowableAnalyzer() { this.extractorMap = new TreeMap(CLASS_HIERARCHY_COMPARATOR); initExtractorMap(); } /** * Registers a ThrowableCauseExtractor for the specified type. * Can be used in subclasses overriding {@link #initExtractorMap()}. * * @param throwableType the type (has to be a subclass of Throwable) * @param extractor the associated ThrowableCauseExtractor (not null) * * @throws IllegalArgumentException if one of the arguments is invalid */ protected final void registerExtractor(Class throwableType, ThrowableCauseExtractor extractor) { verifyThrowableType(throwableType); if (extractor == null) { throw new IllegalArgumentException("Invalid extractor: null"); } this.extractorMap.put(throwableType, extractor); } /** * Initializes associations between Throwables and ThrowableCauseExtractors. * The default implementation performs the following registrations: *
  • {@link #DEFAULT_EXTRACTOR} for {@link Throwable}
  • *
  • {@link #INVOCATIONTARGET_EXTRACTOR} for {@link InvocationTargetException}
  • *
    * Subclasses overriding this method are encouraged to invoke the super method to perform the * default registrations. They can register additional extractors as required. *

    * Note: An extractor registered for a specific type is applicable for that type and all subtypes thereof. * However, extractors registered to more specific types are guaranteed to be resolved first. * So in the default case InvocationTargetExceptions will be handled by {@link #INVOCATIONTARGET_EXTRACTOR} * while all other throwables are handled by {@link #DEFAULT_EXTRACTOR}. * * @see #registerExtractor(Class, ThrowableCauseExtractor) */ protected void initExtractorMap() { registerExtractor(InvocationTargetException.class, INVOCATIONTARGET_EXTRACTOR); registerExtractor(Throwable.class, DEFAULT_EXTRACTOR); } /** * Returns an array containing the classes for which extractors are registered. * The order of the classes is the order in which comparisons will occur for * resolving a matching extractor. * * @return the types for which extractors are registered */ final Class[] getRegisteredTypes() { List typeList = new ArrayList(this.extractorMap.keySet()); return (Class[]) typeList.toArray(new Class[typeList.size()]); } /** * Determines the cause chain of the provided Throwable. * The returned array contains all throwables extracted from the stacktrace, using the registered * {@link ThrowableCauseExtractor extractors}. The elements of the array are ordered: * The first element is the passed in throwable itself. The following elements * appear in their order downward the stacktrace. *

    * Note: If no {@link ThrowableCauseExtractor} is registered for this instance * then the returned array will always only contain the passed in throwable. * * @param throwable the Throwable to analyze * @return an array of all determined throwables from the stacktrace * * @throws IllegalArgumentException if the throwable is null * * @see #initExtractorMap() */ public final Throwable[] determineCauseChain(Throwable throwable) { if (throwable == null) { throw new IllegalArgumentException("Invalid throwable: null"); } List chain = new ArrayList(); Throwable currentThrowable = throwable; while (currentThrowable != null) { chain.add(currentThrowable); currentThrowable = extractCause(currentThrowable); } return (Throwable[]) chain.toArray(new Throwable[chain.size()]); } /** * Extracts the cause of the given throwable using an appropriate extractor. * * @param throwable the Throwable (not null * @return the cause, may be null if none could be resolved */ private Throwable extractCause(Throwable throwable) { for (Iterator iter = this.extractorMap.entrySet().iterator(); iter.hasNext(); ) { Map.Entry entry = (Map.Entry) iter.next(); Class throwableType = (Class) entry.getKey(); if (throwableType.isInstance(throwable)) { ThrowableCauseExtractor extractor = (ThrowableCauseExtractor) entry.getValue(); return extractor.extractCause(throwable); } } return null; } /** * Returns the first throwable from the passed in array that is assignable to the provided type. * A returned instance is safe to be cast to the specified type. *

    * If the passed in array is null or empty this method returns null. * * @param throwableType the type to look for * @param chain the array (will be processed in element order) * @return the found Throwable, null if not found * * @throws IllegalArgumentException if the provided type is null * or no subclass of Throwable */ public final Throwable getFirstThrowableOfType(Class throwableType, Throwable[] chain) { verifyThrowableType(throwableType); if (chain != null) { for (int i = 0; i < chain.length; ++i) { Throwable t = chain[i]; if ((t != null) && throwableType.isInstance(t)) { return t; } } } return null; } /** * Convenience method for verifying that the passed in class refers to a valid * subclass of Throwable. * * @param throwableType the type to check * * @throws IllegalArgumentException if typeToCheck is either null * or not assignable to expectedBaseType */ private static void verifyThrowableType(Class throwableType) { if (throwableType == null) { throw new IllegalArgumentException("Invalid type: null"); } if (!Throwable.class.isAssignableFrom(throwableType)) { throw new IllegalArgumentException("Invalid type: '" + throwableType.getName() + "'. Has to be a subclass of '" + Throwable.class.getName() + "'"); } } /** * Verifies that the provided throwable is a valid subclass of the provided type (or of the type itself). * If expectdBaseType is null, no check will be performed. *

    * Can be used for verification purposes in implementations * of {@link ThrowableCauseExtractor extractors}. * * @param throwable the Throwable to check * @param expectedBaseType the type to check against * * @throws IllegalArgumentException if throwable is either null * or its type is not assignable to expectedBaseType */ public static final void verifyThrowableHierarchy(Throwable throwable, Class expectedBaseType) { if (expectedBaseType == null) { return; } if (throwable == null) { throw new IllegalArgumentException("Invalid throwable: null"); } Class throwableType = throwable.getClass(); if (!expectedBaseType.isAssignableFrom(throwableType)) { throw new IllegalArgumentException("Invalid type: '" + throwableType.getName() + "'. Has to be a subclass of '" + expectedBaseType.getName() + "'"); } } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/PortResolverImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/PortResolv0000644000000000000000000000514111623517156030601 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import org.springframework.util.Assert; import javax.servlet.ServletRequest; /** * Concrete implementation of {@link PortResolver} that obtains the port from ServletRequest.getServerPort(). *

    * This class is capable of handling the IE bug which results in an * incorrect URL being presented in the header subsequent to a redirect to a different scheme and port where the port * is not a well-known number (ie 80 or 443). Handling involves detecting an incorrect response from * ServletRequest.getServerPort() for the scheme (eg a HTTP request on 8443) and then determining the * real server port (eg HTTP request is really on 8080). The map of valid ports is obtained from the configured * {@link PortMapper}. * * @author Ben Alex * @version $Id$ */ public class PortResolverImpl implements PortResolver { //~ Instance fields ================================================================================================ private PortMapper portMapper = new PortMapperImpl(); //~ Methods ======================================================================================================== public PortMapper getPortMapper() { return portMapper; } public int getServerPort(ServletRequest request) { int serverPort = request.getServerPort(); Integer portLookup = null; String scheme = request.getScheme().toLowerCase(); if ("http".equals(scheme)) { portLookup = portMapper.lookupHttpPort(new Integer(serverPort)); } else if ("https".equals(scheme)) { portLookup = portMapper.lookupHttpsPort(new Integer(serverPort)); } if (portLookup != null) { // IE 6 bug serverPort = portLookup.intValue(); } return serverPort; } public void setPortMapper(PortMapper portMapper) { Assert.notNull(portMapper, "portMapper cannot be null"); this.portMapper = portMapper; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/TextUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/TextUtils.0000644000000000000000000000160111623517156030502 0ustar package org.springframework.security.util; /** * Utilities for working with Strings and text. * * @author Luke Taylor * @version $Id$ */ public abstract class TextUtils { public static String escapeEntities(String s) { if (s == null || s.length() == 0) { return s; } StringBuffer sb = new StringBuffer(); for (int i=0; i < s.length(); i++) { char c = s.charAt(i); if(c == '<') { sb.append("<"); } else if (c == '>') { sb.append(">"); } else if (c == '"') { sb.append("""); } else if (c == '\'') { sb.append("'"); } else if (c == '&') { sb.append("&"); } else { sb.append(c); } } return sb.toString(); } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/InMemoryXmlApplicationContext.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/InMemoryXm0000644000000000000000000000314311623517156030526 0ustar package org.springframework.security.util; import org.springframework.context.support.AbstractXmlApplicationContext; import org.springframework.core.io.Resource; /** * @author Luke Taylor * @version $Id$ */ public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext { private static final String BEANS_OPENING = "\n"; private static final String BEANS_CLOSE = "\n"; Resource inMemoryXml; public InMemoryXmlApplicationContext(String xml) { this(xml, true); } public InMemoryXmlApplicationContext(String xml, boolean addBeansTags) { String fullXml = addBeansTags ? BEANS_OPENING + xml + BEANS_CLOSE : xml; inMemoryXml = new InMemoryResource(fullXml); refresh(); } protected Resource[] getConfigResources() { return new Resource[] {inMemoryXml}; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/Sha512DigestUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/Sha512Dige0000644000000000000000000000437711623517156030230 0ustar package org.springframework.security.util; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import org.apache.commons.codec.binary.Hex; /** * Provides SHA512 digest methods. * *

    * Based on Commons Codec, which does not presently provide SHA512 support. *

    * * @author Ben Alex * @since 2.0.1 * */ public abstract class Sha512DigestUtils { /** * Returns a MessageDigest for the given algorithm. * * @param algorithm The MessageDigest algorithm name. * @return An MD5 digest instance. * @throws RuntimeException when a {@link java.security.NoSuchAlgorithmException} is caught, */ static MessageDigest getDigest(String algorithm) { try { return MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e.getMessage()); } } /** * Returns an SHA digest. * * @return An SHA digest instance. * @throws RuntimeException when a {@link java.security.NoSuchAlgorithmException} is caught, */ private static MessageDigest getSha512Digest() { return getDigest("SHA-512"); } /** * Calculates the SHA digest and returns the value as a * byte[]. * * @param data Data to digest * @return SHA digest */ public static byte[] sha(byte[] data) { return getSha512Digest().digest(data); } /** * Calculates the SHA digest and returns the value as a * byte[]. * * @param data Data to digest * @return SHA digest */ public static byte[] sha(String data) { return sha(data.getBytes()); } /** * Calculates the SHA digest and returns the value as a hex string. * * @param data Data to digest * @return SHA digest as a hex string */ public static String shaHex(byte[] data) { return new String(Hex.encodeHex(sha(data))); } /** * Calculates the SHA digest and returns the value as a hex string. * * @param data Data to digest * @return SHA digest as a hex string */ public static String shaHex(String data) { return new String(Hex.encodeHex(sha(data))); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/package.ht0000644000000000000000000000014511623517156030466 0ustar General utility classes used throughout the Spring Security framework. ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/InMemoryResource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/InMemoryRe0000644000000000000000000000453011623517156030511 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import org.springframework.core.io.AbstractResource; import org.springframework.util.Assert; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; /** * An in memory implementation of Spring's {@link org.springframework.core.io.Resource} interface. *

    Used to create a bean factory from an XML string, rather than a file.

    * * @author Luke Taylor * @version $Id$ */ public class InMemoryResource extends AbstractResource { //~ Instance fields ================================================================================================ private byte[] source; private String description; //~ Constructors =================================================================================================== public InMemoryResource(String source) { this(source.getBytes()); } public InMemoryResource(byte[] source) { this(source, null); } public InMemoryResource(byte[] source, String description) { Assert.notNull(source); this.source = source; this.description = description; } //~ Methods ======================================================================================================== public String getDescription() { return description; } public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(source); } public int hashCode() { return source.hashCode(); } public boolean equals(Object res) { if (res instanceof InMemoryResource) { return false; } return Arrays.equals(source, ((InMemoryResource)res).source); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/RedirectUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/RedirectUt0000644000000000000000000000413411623517156030535 0ustar package org.springframework.security.util; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.ui.logout.LogoutFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author Luke Taylor * @version $Id$ */ public abstract class RedirectUtils { //~ Constructors =================================================================================================== private RedirectUtils() { } //~ Methods ======================================================================================================== /** * Encapsulates the redirect logic used in classes like {@link AbstractProcessingFilter} and {@link LogoutFilter}. * * @param request the incoming request * @param response the response to redirect * @param url the target url to redirect to * @param useRelativeContext if true, causes any redirection URLs to be calculated minus the protocol * and context path. * * @see AbstractProcessingFilter#setUseRelativeContext(boolean) */ public static final void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url, boolean useRelativeContext) throws IOException { String finalUrl; if (!url.startsWith("http://") && !url.startsWith("https://")) { if (useRelativeContext) { finalUrl = url; } else { finalUrl = request.getContextPath() + url; } } else if (useRelativeContext) { // Calculate the relative URL from the fully qualifed URL, minus the protocol and base context. int len = request.getContextPath().length(); int index = url.indexOf(request.getContextPath()) + len; finalUrl = url.substring(index); if (finalUrl.length() > 1 && finalUrl.charAt(0) == '/') { finalUrl = finalUrl.substring(1); } } else { finalUrl = url; } response.sendRedirect(response.encodeRedirectURL(finalUrl)); } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/FilterInvocationUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/FilterInvo0000644000000000000000000000766311623517156030556 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import org.springframework.security.intercept.web.FilterInvocation; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.util.Assert; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Static utility methods for creating FilterInvocations usable within Spring Security.

    The generated * FilterInvocation objects are not intended for use with AbstractSecurityInterceptor * subclasses. Instead they are generally used by WebInvocationPrivilegeEvaluator.

    * * @author Ben Alex * @version $Id$ */ public final class FilterInvocationUtils { //~ Constructors =================================================================================================== private FilterInvocationUtils() { } //~ Methods ======================================================================================================== /** * Creates a FilterInvocation for the specified contextPath and Uri. * Note the normal subclasses of DefaultFilterInvocationDefinitionSource disregard the * contextPath when evaluating which secure object metadata applies to a given * FilterInvocation, so generally the contextPath is unimportant unless you are using a * custom FilterInvocationDefinitionSource. * * @param contextPath the contextPath that will be contained within the * FilterInvocationHttpServletRequest * @param uri the URI of the request, such as /foo/default.jsp * * @return a fully-formed FilterInvocation (never null) * * @throws UnsupportedOperationException DOCUMENT ME! */ public static FilterInvocation create(String contextPath, String uri) { Assert.hasText(contextPath, "contextPath required"); Assert.hasText(uri, "URI required"); MockHttpServletRequest req = new MockHttpServletRequest(); req.setRequestURI(contextPath + uri); req.setContextPath(contextPath); req.setServletPath(null); FilterInvocation fi = new FilterInvocation(req, new MockHttpServletResponse(), new FilterChain() { public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException { throw new UnsupportedOperationException( "WebInvocationPrivilegeEvaluator does not support filter chains"); } }); return fi; } /** * Creates a FilterInvocation for the specified Uri. The contextPath * is set to a default value. * * @param uri the URI of the request, such as /foo/default.jsp * * @return a fully-formed FilterInvocation (never null) */ public static FilterInvocation create(String uri) { return create("/notused", uri); } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/SimpleMethodInvocation.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/SimpleMeth0000644000000000000000000000413511623517156030533 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import org.aopalliance.intercept.MethodInvocation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; /** * Represents the AOP Alliance MethodInvocation. * * @author Ben Alex * @version $Id$ */ public class SimpleMethodInvocation implements MethodInvocation { //~ Instance fields ================================================================================================ private Method method; private Object[] arguments; private Object targetObject; //~ Constructors =================================================================================================== public SimpleMethodInvocation(Object targetObject, Method method, Object[] arguments) { this.targetObject = targetObject; this.method = method; this.arguments = arguments; } public SimpleMethodInvocation() {} //~ Methods ======================================================================================================== public Object[] getArguments() { return arguments; } public Method getMethod() { return method; } public AccessibleObject getStaticPart() { throw new UnsupportedOperationException("mock method not implemented"); } public Object getThis() { return targetObject; } public Object proceed() throws Throwable { throw new UnsupportedOperationException("mock method not implemented"); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/RegexUrlPathMatcher.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/RegexUrlPa0000644000000000000000000000170511623517156030502 0ustar package org.springframework.security.util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.regex.Pattern; /** * @author Luke Taylor * @version $Id$ */ public class RegexUrlPathMatcher implements UrlMatcher { private static final Log logger = LogFactory.getLog(RegexUrlPathMatcher.class); private boolean requiresLowerCaseUrl = false; public Object compile(String path) { return Pattern.compile(path); } public void setRequiresLowerCaseUrl(boolean requiresLowerCaseUrl) { this.requiresLowerCaseUrl = requiresLowerCaseUrl; } public boolean pathMatchesUrl(Object compiledPath, String url) { Pattern pattern = (Pattern)compiledPath; return pattern.matcher(url).matches(); } public String getUniversalMatchPattern() { return "/.*"; } public boolean requiresLowerCaseUrl() { return requiresLowerCaseUrl; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/AntUrlPathMatcher.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/AntUrlPath0000644000000000000000000000241311623517156030503 0ustar package org.springframework.security.util; import org.springframework.util.PathMatcher; import org.springframework.util.AntPathMatcher; /** * Ant path strategy for URL matching. * * @author Luke Taylor * @version $Id$ */ public class AntUrlPathMatcher implements UrlMatcher { private boolean requiresLowerCaseUrl = true; private PathMatcher pathMatcher = new AntPathMatcher(); public AntUrlPathMatcher() { this(true); } public AntUrlPathMatcher(boolean requiresLowerCaseUrl) { this.requiresLowerCaseUrl = requiresLowerCaseUrl; } public Object compile(String path) { if (requiresLowerCaseUrl) { return path.toLowerCase(); } return path; } public void setRequiresLowerCaseUrl(boolean requiresLowerCaseUrl) { this.requiresLowerCaseUrl = requiresLowerCaseUrl; } public boolean pathMatchesUrl(Object path, String url) { return pathMatcher.match((String)path, url); } public String getUniversalMatchPattern() { return "/**"; } public boolean requiresLowerCaseUrl() { return requiresLowerCaseUrl; } public String toString() { return getClass().getName() + "[requiresLowerCase='" + requiresLowerCaseUrl + "']"; } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/AuthorityUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/AuthorityU0000644000000000000000000000630211623517156030577 0ustar package org.springframework.security.util; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthorityImpl; import org.springframework.security.context.SecurityContextHolder; import org.springframework.util.StringUtils; import java.util.HashSet; import java.util.Set; /** * @author Luke Taylor * @version $Id$ */ public abstract class AuthorityUtils { public static final GrantedAuthority[] NO_AUTHORITIES = new GrantedAuthority[0]; /** * Returns true if the current user has the specified authority. * * @param authority the authority to test for (e.g. "ROLE_A"). * @return true if a GrantedAuthority object with the same string representation as the supplied authority * name exists in the current user's list of authorities. False otherwise, or if the user in not authenticated. */ public static boolean userHasAuthority(String authority) { GrantedAuthority[] authorities = getUserAuthorities(); for (int i = 0; i < authorities.length; i++) { if (authority.equals(authorities[i].getAuthority())) { return true; } } return false; } /** * Returns the authorities of the current user. * * @return an array containing the current user's authorities (or an empty array if not authenticated), never null. */ private static GrantedAuthority[] getUserAuthorities() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth == null || auth.getAuthorities() == null) { return NO_AUTHORITIES; } return auth.getAuthorities(); } /** * Creates a array of GrantedAuthority objects from a comma-separated string * representation (e.g. "ROLE_A, ROLE_B, ROLE_C"). * * @param authorityString the comma-separated string * @return the authorities created by tokenizing the string */ public static GrantedAuthority[] commaSeparatedStringToAuthorityArray(String authorityString) { String[] authorityStrings = StringUtils.tokenizeToStringArray(authorityString, ","); GrantedAuthority[] authorities = new GrantedAuthority[authorityStrings.length]; for (int i=0; i < authorityStrings.length; i++) { authorities[i] = new GrantedAuthorityImpl(authorityStrings[i]); } return authorities; } /** * Converts an array of GrantedAuthority objects to a Set. * @return a Set of the Strings obtained from each call to GrantedAuthority.getAuthority() */ public static Set authorityArrayToSet(GrantedAuthority[] authorities) { Set set = new HashSet(authorities.length); for (int i = 0; i < authorities.length; i++) { set.add(authorities[i].getAuthority()); } return set; } public static GrantedAuthority[] stringArrayToAuthorityArray(String[] roles) { GrantedAuthority[] authorities = new GrantedAuthority[roles.length]; for (int i=0; i < roles.length; i++) { authorities[i] = new GrantedAuthorityImpl(roles[i]); } return authorities; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/UrlUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/UrlUtils.j0000644000000000000000000001040711623517156030476 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import org.springframework.security.intercept.web.FilterInvocation; import org.springframework.security.ui.savedrequest.SavedRequest; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; /** * Provides static methods for composing URLs.

    Placed into a separate class for visibility, so that changes to * URL formatting conventions will affect all users.

    * * @author Ben Alex * @version $Id$ */ public final class UrlUtils { //~ Constructors =================================================================================================== private UrlUtils() { } //~ Methods ======================================================================================================== /** * Obtains the full URL the client used to make the request.

    Note that the server port will not be shown * if it is the default server port for HTTP or HTTPS (ie 80 and 443 respectively).

    * * @return the full URL */ private static String buildFullRequestUrl(String scheme, String serverName, int serverPort, String contextPath, String requestUrl, String servletPath, String requestURI, String pathInfo, String queryString) { boolean includePort = true; if ("http".equals(scheme.toLowerCase()) && (serverPort == 80)) { includePort = false; } if ("https".equals(scheme.toLowerCase()) && (serverPort == 443)) { includePort = false; } return scheme + "://" + serverName + ((includePort) ? (":" + serverPort) : "") + contextPath + buildRequestUrl(servletPath, requestURI, contextPath, pathInfo, queryString); } /** * Obtains the web application-specific fragment of the URL. * * @return the URL, excluding any server name, context path or servlet path */ private static String buildRequestUrl(String servletPath, String requestURI, String contextPath, String pathInfo, String queryString) { String uri = servletPath; if (uri == null) { uri = requestURI; uri = uri.substring(contextPath.length()); } return uri + ((pathInfo == null) ? "" : pathInfo) + ((queryString == null) ? "" : ("?" + queryString)); } public static String getFullRequestUrl(FilterInvocation fi) { HttpServletRequest r = fi.getHttpRequest(); return buildFullRequestUrl(r.getScheme(), r.getServerName(), r.getServerPort(), r.getContextPath(), r.getRequestURL().toString(), r.getServletPath(), r.getRequestURI(), r.getPathInfo(), r.getQueryString()); } public static String getFullRequestUrl(SavedRequest sr) { return buildFullRequestUrl(sr.getScheme(), sr.getServerName(), sr.getServerPort(), sr.getContextPath(), sr.getRequestURL(), sr.getServletPath(), sr.getRequestURI(), sr.getPathInfo(), sr.getQueryString()); } public static String getRequestUrl(FilterInvocation fi) { HttpServletRequest r = fi.getHttpRequest(); return buildRequestUrl(r.getServletPath(), r.getRequestURI(), r.getContextPath(), r.getPathInfo(), r.getQueryString()); } public static String getRequestUrl(SavedRequest sr) { return buildRequestUrl(sr.getServletPath(), sr.getRequestURI(), sr.getContextPath(), sr.getPathInfo(), sr.getQueryString()); } public static boolean isValidRedirectUrl(String url) { return !StringUtils.hasText(url) || url.startsWith("/") || url.toLowerCase().startsWith("http"); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/SessionUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/SessionUti0000644000000000000000000000510711623517156030571 0ustar package org.springframework.security.util; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.security.concurrent.SessionRegistry; import org.springframework.security.concurrent.SessionRegistryUtils; import org.springframework.security.context.SecurityContextHolder; /** * @author Luke Taylor * @version $Id$ * @since 2.0 */ public final class SessionUtils { private final static Log logger = LogFactory.getLog(SessionUtils.class); SessionUtils() {} public static void startNewSessionIfRequired(HttpServletRequest request, boolean migrateAttributes, SessionRegistry sessionRegistry) { HttpSession session = request.getSession(false); if (session == null) { return; } String originalSessionId = session.getId(); if (logger.isDebugEnabled()) { logger.debug("Invalidating session with Id '" + originalSessionId +"' " + (migrateAttributes ? "and" : "without") + " migrating attributes."); } HashMap attributesToMigrate = null; if (migrateAttributes) { attributesToMigrate = new HashMap(); Enumeration enumer = session.getAttributeNames(); while (enumer.hasMoreElements()) { String key = (String) enumer.nextElement(); attributesToMigrate.put(key, session.getAttribute(key)); } } session.invalidate(); session = request.getSession(true); // we now have a new session if (logger.isDebugEnabled()) { logger.debug("Started new session: " + session.getId()); } if (attributesToMigrate != null) { Iterator iter = attributesToMigrate.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); session.setAttribute((String) entry.getKey(), entry.getValue()); } } if (sessionRegistry != null) { sessionRegistry.removeSessionInformation(originalSessionId); Object principal = SessionRegistryUtils.obtainPrincipalFromAuthentication( SecurityContextHolder.getContext().getAuthentication()); sessionRegistry.registerNewSession(session.getId(), principal); } } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/FilterToBeanProxy.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/FilterToBe0000644000000000000000000001741011623517156030463 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import java.io.IOException; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** *

    Delegates Filter requests to a Spring-managed bean.

    * *

    This class acts as a proxy on behalf of a * target Filter that is defined in the Spring bean context. It is necessary to specify which target * Filter should be proxied as a filter initialization parameter.

    * *

    On filter initialisation, the class will use Spring's {@link * WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)} method to obtain an * ApplicationContext instance. It will expect to find the target Filter in this * ApplicationContext.

    * *

    To use this filter, it is necessary to specify one of the following filter initialization parameters: *

      *
    • targetClass indicates the class of the target Filter defined in the bean * context. The only requirements are that this target class implements the javax.servlet.Filter * interface and at least one instance is available in the ApplicationContext.
    • *
    • targetBean indicates the bean name of the target class.
    • *
    * If both initialization parameters are specified, targetBean takes priority.

    * *

    An additional * initialization parameter, init, is also supported. If set to "lazy" the initialization * will take place on the first HTTP request, rather than at filter creation time. This makes it possible to use * FilterToBeanProxy with the Spring ContextLoaderServlet. Where possible you should not use * this initialization parameter, instead using ContextLoaderListener.

    * *

    A final optional initialization parameter, lifecycle, determines whether the servlet container * or the IoC container manages the lifecycle of the proxied filter. When possible you should write your filters to be * managed via the IoC container interfaces such as {@link org.springframework.beans.factory.InitializingBean} and * {@link org.springframework.beans.factory.DisposableBean}. If you cannot control the filters you wish to proxy (eg * you do not have their source code) you might need to allow the servlet container to manage lifecycle via the {@link * javax.servlet.Filter#init(javax.servlet.FilterConfig)} and {@link javax.servlet.Filter#destroy()} methods. If this * case, set the lifecycle initialization parameter to servlet-container-managed. If the * parameter is any other value, servlet container lifecycle methods will not be delegated through to the proxy.

    * * @deprecated use DelegatingFilterProxy instead * @author Ben Alex * @version $Id$ */ public class FilterToBeanProxy implements Filter { //~ Instance fields ================================================================================================ private Filter delegate; private FilterConfig filterConfig; private boolean initialized = false; private boolean servletContainerManaged = false; //~ Methods ======================================================================================================== public void destroy() { if ((delegate != null) && servletContainerManaged) { delegate.destroy(); } } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!initialized) { doInit(); } delegate.doFilter(request, response, chain); } private synchronized void doInit() throws ServletException { if (initialized) { // already initialized, so don't re-initialize return; } String targetBean = filterConfig.getInitParameter("targetBean"); if ("".equals(targetBean)) { targetBean = null; } String lifecycle = filterConfig.getInitParameter("lifecycle"); if ("servlet-container-managed".equals(lifecycle)) { servletContainerManaged = true; } ApplicationContext ctx = this.getContext(filterConfig); String beanName = null; if ((targetBean != null) && ctx.containsBean(targetBean)) { beanName = targetBean; } else if (targetBean != null) { throw new ServletException("targetBean '" + targetBean + "' not found in context"); } else { String targetClassString = filterConfig.getInitParameter("targetClass"); if ((targetClassString == null) || "".equals(targetClassString)) { throw new ServletException("targetClass or targetBean must be specified"); } Class targetClass; try { targetClass = Thread.currentThread().getContextClassLoader().loadClass(targetClassString); } catch (ClassNotFoundException ex) { throw new ServletException("Class of type " + targetClassString + " not found in classloader"); } Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx, targetClass, true, true); if (beans.size() == 0) { throw new ServletException("Bean context must contain at least one bean of type " + targetClassString); } beanName = (String) beans.keySet().iterator().next(); } Object object = ctx.getBean(beanName); if (!(object instanceof Filter)) { throw new ServletException("Bean '" + beanName + "' does not implement javax.servlet.Filter"); } delegate = (Filter) object; if (servletContainerManaged) { delegate.init(filterConfig); } // Set initialized to true at the end of the synchronized method, so // that invocations of doFilter() before this method has completed will not // cause NullPointerException initialized = true; } /** * Allows test cases to override where application context obtained from. * * @param filterConfig which can be used to find the ServletContext * * @return the Spring application context */ protected ApplicationContext getContext(FilterConfig filterConfig) { return WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext()); } public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; String strategy = filterConfig.getInitParameter("init"); if ((strategy != null) && strategy.toLowerCase().equals("lazy")) { return; } doInit(); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/PortMapperImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/PortMapper0000644000000000000000000001064611623517156030561 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import org.springframework.util.Assert; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * Concrete implementation of {@link PortMapper} that obtains HTTP:HTTPS pairs from the application context. *

    * By default the implementation will assume 80:443 and 8080:8443 are HTTP:HTTPS pairs respectively. If different pairs * are required, use {@link #setPortMappings(Map)}. * * @author Ben Alex * @author colin sampaleanu * @version $Id$ */ public class PortMapperImpl implements PortMapper { //~ Instance fields ================================================================================================ private Map httpsPortMappings; //~ Constructors =================================================================================================== public PortMapperImpl() { httpsPortMappings = new HashMap(); httpsPortMappings.put(new Integer(80), new Integer(443)); httpsPortMappings.put(new Integer(8080), new Integer(8443)); } //~ Methods ======================================================================================================== /** * Returns the translated (Integer -> Integer) version of the original port mapping specified via * setHttpsPortMapping() * * @return DOCUMENT ME! */ public Map getTranslatedPortMappings() { return httpsPortMappings; } public Integer lookupHttpPort(Integer httpsPort) { Iterator iter = httpsPortMappings.keySet().iterator(); while (iter.hasNext()) { Integer httpPort = (Integer) iter.next(); if (httpsPortMappings.get(httpPort).equals(httpsPort)) { return httpPort; } } return null; } public Integer lookupHttpsPort(Integer httpPort) { return (Integer) httpsPortMappings.get(httpPort); } /** * Set to override the default HTTP port to HTTPS port mappings of 80:443, and 8080:8443. * In a Spring XML ApplicationContext, a definition would look something like this: *

         *  <property name="portMappings">
         *      <map>
         *          <entry key="80"><value>443</value></entry>
         *          <entry key="8080"><value>8443</value></entry>
         *      </map>
         * </property>
    * * @param newMappings A Map consisting of String keys and String values, where for each entry the key is the string * representation of an integer HTTP port number, and the value is the string representation of the * corresponding integer HTTPS port number. * * @throws IllegalArgumentException if input map does not consist of String keys and values, each representing an * integer port number in the range 1-65535 for that mapping. */ public void setPortMappings(Map newMappings) { Assert.notNull(newMappings, "A valid list of HTTPS port mappings must be provided"); httpsPortMappings.clear(); Iterator it = newMappings.entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); Integer httpPort = new Integer((String) entry.getKey()); Integer httpsPort = new Integer((String) entry.getValue()); if ((httpPort.intValue() < 1) || (httpPort.intValue() > 65535) || (httpsPort.intValue() < 1) || (httpsPort.intValue() > 65535)) { throw new IllegalArgumentException("one or both ports out of legal range: " + httpPort + ", " + httpsPort); } httpsPortMappings.put(httpPort, httpsPort); } if (httpsPortMappings.size() < 1) { throw new IllegalArgumentException("must map at least one port"); } } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/PortMapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/PortMapper0000644000000000000000000000307511623517156030557 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; /** * PortMapper implementations provide callers with information * about which HTTP ports are associated with which HTTPS ports on the system, * and vice versa. * * @author Ben Alex * @version $Id$ */ public interface PortMapper { //~ Methods ======================================================================================================== /** * Locates the HTTP port associated with the specified HTTPS port.

    Returns null if unknown.

    * * @param httpsPort * * @return the HTTP port or null if unknown */ Integer lookupHttpPort(Integer httpsPort); /** * Locates the HTTPS port associated with the specified HTTP port.

    Returns null if unknown.

    * * @param httpPort * * @return the HTTPS port or null if unknown */ Integer lookupHttpsPort(Integer httpPort); } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/EncryptionUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/Encryption0000644000000000000000000001424111623517156030615 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import java.io.UnsupportedEncodingException; import java.security.spec.KeySpec; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESedeKeySpec; import org.springframework.security.SpringSecurityException; import org.apache.commons.codec.binary.Base64; import org.springframework.util.Assert; /** * A static utility class that can encrypt and decrypt text. * *

    This class is useful if you have simple needs and wish to use the DESede * encryption cipher. More sophisticated requirements will need to use the * Java crypto libraries directly. * * @author Alan Stewart * @author Ben Alex * @version $Id$ */ public final class EncryptionUtils { /** * This is a static class that should not be instantiated. */ private EncryptionUtils() {} /** * Converts a String into a byte array using UTF-8, falling back to the * platform's default character set if UTF-8 fails. * * @param input the input (required) * @return a byte array representation of the input string */ public static byte[] stringToByteArray(String input) { Assert.hasLength(input, "Input required"); try { return input.getBytes("UTF-8"); } catch (UnsupportedEncodingException fallbackToDefault) { return input.getBytes(); } } /** * Converts a byte array into a String using UTF-8, falling back to the * platform's default character set if UTF-8 fails. * * @param byteArray the byte array to convert (required) * @return a string representation of the byte array */ public static String byteArrayToString(byte[] byteArray) { Assert.notNull(byteArray, "ByteArray required"); Assert.isTrue(byteArray.length > 0, "ByteArray cannot be empty"); try { return new String(byteArray, "UTF8"); } catch (final UnsupportedEncodingException e) { return new String(byteArray); } } private static byte[] cipher(String key, byte[] passedBytes, int cipherMode) throws EncryptionException { try { final KeySpec keySpec = new DESedeKeySpec(stringToByteArray(key)); final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede"); final Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); final SecretKey secretKey = keyFactory.generateSecret(keySpec); cipher.init(cipherMode, secretKey); return cipher.doFinal(passedBytes); } catch (final Exception e) { throw new EncryptionException(e.getMessage(), e); } } /** * Encrypts the inputString using the key. * * @param key at least 24 character long key (required) * @param inputString the string to encrypt (required) * @return the encrypted version of the inputString * @throws EncryptionException in the event of an encryption failure */ public static String encrypt(String key, String inputString) throws EncryptionException { isValidKey(key); final byte[] cipherText = cipher(key, stringToByteArray(inputString), Cipher.ENCRYPT_MODE); return byteArrayToString(Base64.encodeBase64(cipherText)); } /** * Encrypts the inputBytes using the key. * * @param key at least 24 character long key (required) * @param inputBytes the bytes to encrypt (required) * @return the encrypted version of the inputBytes * @throws EncryptionException in the event of an encryption failure */ public static byte[] encrypt(String key, byte[] inputBytes) throws EncryptionException { isValidKey(key); return Base64.encodeBase64(cipher(key, inputBytes, Cipher.ENCRYPT_MODE)); } /** * Decrypts the inputString using the key. * * @param key the key used to originally encrypt the string (required) * @param inputString the encrypted string (required) * @return the decrypted version of inputString * @throws EncryptionException in the event of an encryption failure */ public static String decrypt(String key, String inputString) throws EncryptionException { Assert.hasText(key, "A key is required to attempt decryption"); final byte[] cipherText = cipher(key, Base64.decodeBase64(stringToByteArray(inputString)), Cipher.DECRYPT_MODE); return byteArrayToString(cipherText); } /** * Decrypts the inputBytes using the key. * * @param key the key used to originally encrypt the string (required) * @param inputBytes the encrypted bytes (required) * @return the decrypted version of inputBytes * @throws EncryptionException in the event of an encryption failure */ public static byte[] decrypt(String key, byte[] inputBytes) throws EncryptionException { Assert.hasText(key, "A key is required to attempt decryption"); return cipher(key, Base64.decodeBase64(inputBytes), Cipher.DECRYPT_MODE); } private static void isValidKey(String key) { Assert.hasText(key, "A key to perform the encryption is required"); Assert.isTrue(key.length() >= 24, "Key must be at least 24 characters long"); } public static class EncryptionException extends SpringSecurityException { private static final long serialVersionUID = 1L; public EncryptionException(String message, Throwable t) { super(message, t); } public EncryptionException(String message) { super(message); } } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/MethodInvocationUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/MethodInvo0000644000000000000000000001256411623517156030545 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.framework.Advised; import org.springframework.aop.support.AopUtils; import org.springframework.util.Assert; /** * Static utility methods for creating MethodInvocations usable within Spring Security. *

    All methods of this class return a {@link org.springframework.security.util.SimpleMethodInvocation}.

    * * @author Ben Alex * @version $Id$ */ public final class MethodInvocationUtils { //~ Constructors =================================================================================================== private MethodInvocationUtils() { } //~ Methods ======================================================================================================== /** * Generates a MethodInvocation for specified methodName on the passed object. * * @param object the object that will be used to find the relevant Method * @param methodName the name of the method to find * * @return a MethodInvocation, or null if there was a problem */ public static MethodInvocation create(Object object, String methodName) { return create(object, methodName, null); } /** * Generates a MethodInvocation for specified methodName on the passed object, * using the args to locate the method. * * @param object the object that will be used to find the relevant Method * @param methodName the name of the method to find * @param args arguments that are required as part of the method signature * * @return a MethodInvocation, or null if there was a problem */ public static MethodInvocation create(Object object, String methodName, Object[] args) { Assert.notNull(object, "Object required"); Class[] classArgs = null; if (args != null) { List list = new ArrayList(); for (int i = 0; i < args.length; i++) { list.add(args[i].getClass()); } classArgs = (Class[]) list.toArray(new Class[] {}); } // Determine the type that declares the requested method, taking into account proxies Class target = AopUtils.getTargetClass(object); if (object instanceof Advised) { Advised a = (Advised) object; if (!a.isProxyTargetClass()) { Class[] possibleInterfaces = a.getProxiedInterfaces(); for (int i = 0; i < possibleInterfaces.length; i++) { try { possibleInterfaces[i].getMethod(methodName, classArgs); // to get here means no exception happened target = possibleInterfaces[i]; break; } catch (Exception tryTheNextOne) {} } } } return createFromClass(object, target, methodName, classArgs, args); } /** * Generates a MethodInvocation for specified methodName on the passed class. * * @param clazz the class of object that will be used to find the relevant Method * @param methodName the name of the method to find * * @return a MethodInvocation, or null if there was a problem */ public static MethodInvocation createFromClass(Class clazz, String methodName) { return createFromClass(null, clazz, methodName, null, null); } /** * Generates a MethodInvocation for specified methodName on the passed class, * using the args to locate the method. * * @param targetObject the object being invoked * @param clazz the class of object that will be used to find the relevant Method * @param methodName the name of the method to find * @param classArgs arguments that are required to locate the relevant method signature * @param args the actual arguments that should be passed to SimpleMethodInvocation * @return a MethodInvocation, or null if there was a problem */ public static MethodInvocation createFromClass(Object targetObject, Class clazz, String methodName, Class[] classArgs, Object[] args) { Assert.notNull(clazz, "Class required"); Assert.hasText(methodName, "MethodName required"); Method method; try { method = clazz.getMethod(methodName, classArgs); } catch (Exception e) { return null; } return new SimpleMethodInvocation(targetObject, method, args); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/RedirectUrlBuilder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/RedirectUr0000644000000000000000000000377611623517156030546 0ustar package org.springframework.security.util; import org.springframework.util.Assert; /** * Internal class for building redirect URLs. * * Could probably make more use of the classes in java.net for this. * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class RedirectUrlBuilder { private String scheme; private String serverName; private int port; private String contextPath; private String servletPath; private String pathInfo; private String query; public void setScheme(String scheme) { if(! ("http".equals(scheme) | "https".equals(scheme)) ) { throw new IllegalArgumentException("Unsupported scheme '" + scheme + "'"); } this.scheme = scheme; } public void setServerName(String serverName) { this.serverName = serverName; } public void setPort(int port) { this.port = port; } public void setContextPath(String contextPath) { this.contextPath = contextPath; } public void setServletPath(String servletPath) { this.servletPath = servletPath; } public void setPathInfo(String pathInfo) { this.pathInfo = pathInfo; } public void setQuery(String query) { this.query = query; } public String getUrl() { StringBuffer sb = new StringBuffer(); Assert.notNull(scheme); Assert.notNull(serverName); sb.append(scheme).append("://").append(serverName); // Append the port number if it's not standard for the scheme if (port != (scheme.equals("http") ? 80 : 443)) { sb.append(":").append(Integer.toString(port)); } if (contextPath != null) { sb.append(contextPath); } if (servletPath != null) { sb.append(servletPath); } if (pathInfo != null) { sb.append(pathInfo); } if (query != null) { sb.append("?").append(query); } return sb.toString(); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/StringSplitUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/StringSpli0000644000000000000000000001514511623517156030565 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import java.util.HashMap; import java.util.Map; import java.util.ArrayList; import java.util.List; /** * Provides several String manipulation methods. * * @author Ben Alex * @version $Id$ */ public final class StringSplitUtils { //~ Static fields/initializers ===================================================================================== private static final String[] EMPTY_STRING_ARRAY = new String[0]; //~ Constructors =================================================================================================== private StringSplitUtils() { } //~ Methods ======================================================================================================== /** * Splits a String at the first instance of the delimiter.

    Does not include the delimiter in * the response.

    * * @param toSplit the string to split * @param delimiter to split the string up with * @return a two element array with index 0 being before the delimiter, and index 1 being after the delimiter * (neither element includes the delimiter) * @throws IllegalArgumentException if an argument was invalid */ public static String[] split(String toSplit, String delimiter) { Assert.hasLength(toSplit, "Cannot split a null or empty string"); Assert.hasLength(delimiter, "Cannot use a null or empty delimiter to split a string"); if (delimiter.length() != 1) { throw new IllegalArgumentException("Delimiter can only be one character in length"); } int offset = toSplit.indexOf(delimiter); if (offset < 0) { return null; } String beforeDelimiter = toSplit.substring(0, offset); String afterDelimiter = toSplit.substring(offset + 1); return new String[]{beforeDelimiter, afterDelimiter}; } /** * Takes an array of Strings, and for each element removes any instances of * removeCharacter, and splits the element based on the delimiter. A Map is * then generated, with the left of the delimiter providing the key, and the right of the delimiter providing the * value.

    Will trim both the key and value before adding to the Map.

    * * @param array the array to process * @param delimiter to split each element using (typically the equals symbol) * @param removeCharacters one or more characters to remove from each element prior to attempting the split * operation (typically the quotation mark symbol) or null if no removal should occur * @return a Map representing the array contents, or null if the array to process was * null or empty */ public static Map splitEachArrayElementAndCreateMap(String[] array, String delimiter, String removeCharacters) { if ((array == null) || (array.length == 0)) { return null; } Map map = new HashMap(); for (int i = 0; i < array.length; i++) { String postRemove; if (removeCharacters == null) { postRemove = array[i]; } else { postRemove = StringUtils.replace(array[i], removeCharacters, ""); } String[] splitThisArrayElement = split(postRemove, delimiter); if (splitThisArrayElement == null) { continue; } map.put(splitThisArrayElement[0].trim(), splitThisArrayElement[1].trim()); } return map; } public static String substringBeforeLast(String str, String separator) { if (str == null || separator == null || str.length() == 0 || separator.length() == 0) { return str; } int pos = str.lastIndexOf(separator); if (pos == -1) { return str; } return str.substring(0, pos); } public static String substringAfterLast(String str, String separator) { if (str == null || str.length() == 0) { return str; } if (separator == null || separator.length() == 0) { return ""; } int pos = str.lastIndexOf(separator); if (pos == -1 || pos == (str.length() - separator.length())) { return ""; } return str.substring(pos + separator.length()); } /** * Splits a given string on the given separator character, skips the contents of quoted substrings * when looking for separators. * Introduced for use in DigestProcessingFilter (see SEC-506). *

    * This was copied and modified from commons-lang StringUtils */ public static String[] splitIgnoringQuotes(String str, char separatorChar) { if (str == null) { return null; } int len = str.length(); if (len == 0) { return EMPTY_STRING_ARRAY; } List list = new ArrayList(); int i = 0; int start = 0; boolean match = false; while (i < len) { if (str.charAt(i) == '"') { i++; while (i < len) { if (str.charAt(i) == '"') { i++; break; } i++; } match = true; continue; } if (str.charAt(i) == separatorChar) { if (match) { list.add(str.substring(start, i)); match = false; } start = ++i; continue; } match = true; i++; } if (match) { list.add(str.substring(start, i)); } return (String[]) list.toArray(new String[list.size()]); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/FilterChainProxy.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/FilterChai0000644000000000000000000004407111623517156030501 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.security.firewall.DefaultHttpFirewall; import org.springframework.security.firewall.FirewalledRequest; import org.springframework.security.firewall.HttpFirewall; import org.springframework.security.intercept.web.*; import org.springframework.util.Assert; import org.springframework.web.filter.DelegatingFilterProxy; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.*; /** * Delegates Filter requests to a list of Spring-managed beans. * As of version 2.0, you shouldn't need to explicitly configure a FilterChainProxy bean in your application * context unless you need very fine control over the filter chain contents. Most cases should be adequately covered * by the default <security:http /> namespace configuration options. * *

    The FilterChainProxy is loaded via a standard Spring {@link DelegatingFilterProxy} declaration in * web.xml. FilterChainProxy will then pass {@link #init(FilterConfig)}, {@link #destroy()} * and {@link #doFilter(ServletRequest, ServletResponse, FilterChain)} invocations through to each Filter * defined against FilterChainProxy. * *

    As of version 2.0, FilterChainProxy is configured using an ordered Map of path patterns to Lists * of Filter objects. In previous * versions, a {@link FilterInvocationDefinitionSource} was used. This is now deprecated in favour of namespace-based * configuration which provides a more robust and simplfied syntax. The Map instance will normally be * created while parsing the namespace configuration, so doesn't have to be set explicitly. * Instead the <filter-chain-map> element should be used within the FilterChainProxy bean declaration. * This in turn should have a list of child <filter-chain> elements which each define a URI pattern and the list * of filters (as comma-separated bean names) which should be applied to requests which match the pattern. * An example configuration might look like this: * *

     <bean id="myfilterChainProxy" class="org.springframework.security.util.FilterChainProxy">
         <security:filter-chain-map pathType="ant">
             <security:filter-chain pattern="/do/not/filter" filters="none"/>
             <security:filter-chain pattern="/**" filters="filter1,filter2,filter3"/>
         </security:filter-chain-map>
     </bean>
     * 
    * * The names "filter1", "filter2", "filter3" should be the bean names of Filter instances defined in the * application context. The order of the names defines the order in which the filters will be applied. As shown above, * use of the value "none" for the "filters" can be used to exclude * Please consult the security namespace schema file for a full list of available configuration options. * *

    * Each possible URI pattern that FilterChainProxy should service must be entered. * The first matching URI pattern for a given request will be used to define all of the * Filters that apply to that request. NB: This means you must put most specific URI patterns at the top * of the list, and ensure all Filters that should apply for a given URI pattern are entered against the * respective entry. The FilterChainProxy will not iterate the remainder of the URI patterns to locate * additional Filters. * *

    FilterChainProxy respects normal handling of Filters that elect not to call {@link * javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, * javax.servlet.FilterChain)}, in that the remainder of the original or FilterChainProxy-declared filter * chain will not be called. * *

    Note the Filter lifecycle mismatch between the servlet container and IoC * container. As described in the {@link DelegatingFilterProxy} JavaDocs, we recommend you allow the IoC * container to manage the lifecycle instead of the servlet container. By default the DelegatingFilterProxy * will never call this class' {@link #init(FilterConfig)} and {@link #destroy()} methods, which in turns means that * the corresponding methods on the filter beans managed by this class will never be called. If you do need your filters to be * initialized and destroyed, please set the targetFilterLifecycle initialization parameter against the * DelegatingFilterProxy to specify that servlet container lifecycle management should be used. You don't * need to worry about this in most cases. * * @author Carlos Sanchez * @author Ben Alex * @author Luke Taylor * @author Rob Winch * * @version $Id$ */ public class FilterChainProxy implements Filter, InitializingBean, ApplicationContextAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(FilterChainProxy.class); public static final String TOKEN_NONE = "#NONE#"; //~ Instance fields ================================================================================================ private ApplicationContext applicationContext; /** Map of the original pattern Strings to filter chains */ private Map uncompiledFilterChainMap; /** Compiled pattern version of the filter chain map */ private Map filterChainMap; private UrlMatcher matcher = new AntUrlPathMatcher(); private boolean stripQueryStringFromUrls = true; private DefaultFilterInvocationDefinitionSource fids; private HttpFirewall firewall = new DefaultHttpFirewall(); //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { // Convert the FilterDefinitionSource to a filterChainMap if set if (fids != null) { Assert.isNull(uncompiledFilterChainMap, "Set the filterChainMap or FilterInvocationDefinitionSource but not both"); FIDSToFilterChainMapConverter converter = new FIDSToFilterChainMapConverter(fids, applicationContext); setMatcher(converter.getMatcher()); setFilterChainMap(converter.getFilterChainMap()); fids = null; } Assert.notNull(uncompiledFilterChainMap, "filterChainMap must be set"); } public void init(FilterConfig filterConfig) throws ServletException { Filter[] filters = obtainAllDefinedFilters(); for (int i = 0; i < filters.length; i++) { if (filters[i] != null) { if (logger.isDebugEnabled()) { logger.debug("Initializing Filter defined in ApplicationContext: '" + filters[i].toString() + "'"); } filters[i].init(filterConfig); } } } public void destroy() { Filter[] filters = obtainAllDefinedFilters(); for (int i = 0; i < filters.length; i++) { if (filters[i] != null) { if (logger.isDebugEnabled()) { logger.debug("Destroying Filter defined in ApplicationContext: '" + filters[i].toString() + "'"); } filters[i].destroy(); } } } public void doFilter(ServletRequest servletRequest, ServletResponse response, FilterChain chain) throws IOException, ServletException { FirewalledRequest fwRequest = firewall.getFirewalledRequest((HttpServletRequest) servletRequest); HttpServletResponse fwResponse = firewall.getFirewalledResponse((HttpServletResponse) response); FilterInvocation fi = new FilterInvocation(fwRequest, fwResponse, chain); List filters = getFilters(fi.getRequestUrl()); if (filters == null || filters.size() == 0) { if (logger.isDebugEnabled()) { logger.debug(fi.getRequestUrl() + filters == null ? " has no matching filters" : " has an empty filter list"); } fwRequest.reset(); chain.doFilter(fwRequest, response); return; } VirtualFilterChain virtualFilterChain = new VirtualFilterChain(fi, filters, fwRequest); virtualFilterChain.doFilter(fi.getRequest(), fi.getResponse()); } /** * Returns the first filter chain matching the supplied URL. * * @param url the request URL * @return an ordered array of Filters defining the filter chain */ public List getFilters(String url) { if (stripQueryStringFromUrls) { // String query string - see SEC-953 int firstQuestionMarkIndex = url.indexOf("?"); if (firstQuestionMarkIndex != -1) { url = url.substring(0, firstQuestionMarkIndex); } } Iterator filterChains = filterChainMap.entrySet().iterator(); while (filterChains.hasNext()) { Map.Entry entry = (Map.Entry) filterChains.next(); Object path = entry.getKey(); if (matcher.requiresLowerCaseUrl()) { url = url.toLowerCase(); if (logger.isDebugEnabled()) { logger.debug("Converted URL to lowercase, from: '" + url + "'; to: '" + url + "'"); } } boolean matched = matcher.pathMatchesUrl(path, url); if (logger.isDebugEnabled()) { logger.debug("Candidate is: '" + url + "'; pattern is " + path + "; matched=" + matched); } if (matched) { return (List) entry.getValue(); } } return null; } /** * Obtains all of the uniqueFilter instances registered in the map of * filter chains. *

    This is useful in ensuring a Filter is not initialized or destroyed twice.

    * * @return all of the Filter instances in the application context which have an entry * in the map (only one entry is included in the array for * each Filter that actually exists in application context, even if a given * Filter is defined multiples times in the filter chain map) */ protected Filter[] obtainAllDefinedFilters() { Set allFilters = new LinkedHashSet(); Iterator it = filterChainMap.values().iterator(); while (it.hasNext()) { allFilters.addAll((List) it.next()); } return (Filter[]) new ArrayList(allFilters).toArray(new Filter[0]); } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } /** * * @deprecated Use namespace configuration or call setFilterChainMap instead. */ public void setFilterInvocationDefinitionSource(FilterInvocationDefinitionSource fids) { Assert.isInstanceOf(DefaultFilterInvocationDefinitionSource.class, fids, "Must be a DefaultFilterInvocationDefinitionSource"); this.fids = (DefaultFilterInvocationDefinitionSource) fids; } /** * Sets the mapping of URL patterns to filter chains. * * The map keys should be the paths and the values should be arrays of Filter objects. * It's VERY important that the type of map used preserves ordering - the order in which the iterator * returns the entries must be the same as the order they were added to the map, otherwise you have no way * of guaranteeing that the most specific patterns are returned before the more general ones. So make sure * the Map used is an instance of LinkedHashMap or an equivalent, rather than a plain HashMap, for * example. * * @param filterChainMap the map of path Strings to Filter[]s. */ public void setFilterChainMap(Map filterChainMap) { uncompiledFilterChainMap = new LinkedHashMap(filterChainMap); checkPathOrder(); createCompiledMap(); } private void checkPathOrder() { // Check that the universal pattern is listed at the end, if at all String[] paths = (String[]) uncompiledFilterChainMap.keySet().toArray(new String[0]); String universalMatch = matcher.getUniversalMatchPattern(); for (int i=0; i < paths.length-1; i++) { if (paths[i].equals(universalMatch)) { throw new IllegalArgumentException("A universal match pattern " + universalMatch + " is defined " + " before other patterns in the filter chain, causing them to be ignored. Please check the " + "ordering in your namespace or FilterChainProxy bean configuration"); } } } private void createCompiledMap() { Iterator paths = uncompiledFilterChainMap.keySet().iterator(); filterChainMap = new LinkedHashMap(uncompiledFilterChainMap.size()); while (paths.hasNext()) { Object path = paths.next(); Assert.isInstanceOf(String.class, path, "Path pattern must be a String"); Object compiledPath = matcher.compile((String)path); Object filters = uncompiledFilterChainMap.get(path); Assert.isInstanceOf(List.class, filters); // Check the contents Iterator filterIterator = ((List)filters).iterator(); while (filterIterator.hasNext()) { Object filter = filterIterator.next(); Assert.isInstanceOf(Filter.class, filter, "Objects in filter chain must be of type Filter. "); } filterChainMap.put(compiledPath, filters); } } /** * Returns a copy of the underlying filter chain map. Modifications to the map contents * will not affect the FilterChainProxy state - to change the map call setFilterChainMap. * * @return the map of path pattern Strings to filter chain arrays (with ordering guaranteed). */ public Map getFilterChainMap() { return new LinkedHashMap(uncompiledFilterChainMap); } public void setMatcher(UrlMatcher matcher) { this.matcher = matcher; } public UrlMatcher getMatcher() { return matcher; } public void setFirewall(HttpFirewall firewall) { this.firewall = firewall; } /** * If set to 'true', the query string will be stripped from the request URL before * attempting to find a matching filter chain. This is the default value. */ public void setStripQueryStringFromUrls(boolean stripQueryStringFromUrls) { this.stripQueryStringFromUrls = stripQueryStringFromUrls; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("FilterChainProxy["); sb.append(" UrlMatcher = ").append(matcher); sb.append("; Filter Chains: "); sb.append(uncompiledFilterChainMap); sb.append("]"); return sb.toString(); } //~ Inner Classes ================================================================================================== /** * A FilterChain that records whether or not {@link * FilterChain#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} is called.

    This * FilterChain is used by FilterChainProxy to determine if the next Filter * should be called or not.

    */ private static class VirtualFilterChain implements FilterChain { private FilterInvocation fi; private List additionalFilters; private FirewalledRequest firewalledRequest; private int currentPosition = 0; private VirtualFilterChain(FilterInvocation filterInvocation, List additionalFilters, FirewalledRequest firewalledRequest) { this.fi = filterInvocation; this.additionalFilters = additionalFilters; this.firewalledRequest = firewalledRequest; } public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (currentPosition == additionalFilters.size()) { if (logger.isDebugEnabled()) { logger.debug(fi.getRequestUrl() + " reached end of additional filter chain; proceeding with original chain"); } // Deactivate path stripping as we exit the security filter chain this.firewalledRequest.reset(); fi.getChain().doFilter(request, response); } else { currentPosition++; Filter nextFilter = (Filter) additionalFilters.get(currentPosition - 1); if (logger.isDebugEnabled()) { logger.debug(fi.getRequestUrl() + " at position " + currentPosition + " of " + additionalFilters.size() + " in additional filter chain; firing Filter: '" + nextFilter + "'"); } nextFilter.doFilter(request, response, this); } } } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/UrlMatcher.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/UrlMatcher0000644000000000000000000000115611623517156030532 0ustar package org.springframework.security.util; /** * Strategy for deciding whether configured path matches a submitted candidate URL. * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public interface UrlMatcher { Object compile(String urlPattern); boolean pathMatchesUrl(Object compiledUrlPattern, String url); /** Returns the path which matches every URL */ String getUniversalMatchPattern(); /** * Returns true if the matcher expects the URL to be converted to lower case before * calling {@link #pathMatchesUrl(Object, String)}. */ boolean requiresLowerCaseUrl(); } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/PortResolver.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/PortResolv0000644000000000000000000000275211623517156030606 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.util; import javax.servlet.ServletRequest; /** * A PortResolver determines the port a web request was received * on. * *

    * This interface is necessary because * ServletRequest.getServerPort() may not return the correct port * in certain circumstances. For example, if the browser does not construct * the URL correctly after a redirect. *

    * * @author Ben Alex * @version $Id$ */ public interface PortResolver { //~ Methods ======================================================================================================== /** * Indicates the port the ServletRequest was received on. * * @param request that the method should lookup the port for * * @return the port the request was received on */ int getServerPort(ServletRequest request); } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/ThrowableCauseExtractor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/util/ThrowableC0000644000000000000000000000126111623517156030513 0ustar package org.springframework.security.util; /** * Interface for handlers extracting the cause out of a specific {@link Throwable} type. * * @author Andreas Senft * @since 2.0 * @version $Id$ * * @see ThrowableAnalyzer */ public interface ThrowableCauseExtractor { /** * Extracts the cause from the provided Throwable. * * @param throwable the Throwable * @return the extracted cause (maybe null) * * @throws IllegalArgumentException if throwable is null * or otherwise considered invalid for the implementation */ Throwable extractCause(Throwable throwable); } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/0000755000000000000000000000000011623517156026536 5ustar ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/LabeledData.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/LabeledDat0000644000000000000000000000250411623517156030443 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; /** * This interface indicates data objects that carry a label. The purpose is to support * the {@link LabelBasedAclVoter}. When it votes, it evaluates all method arguments * tagged with this interface, and votes if they match the user's granted authorities list. * * @author Greg Turnquist */ public interface LabeledData { //~ Methods ======================================================================================================== /** * Retrieve the domain object's data label. NOTE: This implementation only supports one data label per * object. * * @return The label value of data object as a string. */ String getLabel(); } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/AbstractAccessDecisionManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/AbstractAc0000644000000000000000000001072011623517156030470 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import java.util.Iterator; import java.util.List; import org.springframework.security.AccessDecisionManager; import org.springframework.security.AccessDeniedException; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.ConfigAttribute; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * Abstract implementation of {@link AccessDecisionManager}. *

    * Handles configuration of a bean context defined list of * {@link AccessDecisionVoter}s and the access control behaviour if all voters * abstain from voting (defaults to deny access). *

    */ public abstract class AbstractAccessDecisionManager implements AccessDecisionManager, InitializingBean, MessageSourceAware { //~ Instance fields ================================================================================================ private List decisionVoters; protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private boolean allowIfAllAbstainDecisions = false; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notEmpty(this.decisionVoters, "A list of AccessDecisionVoters is required"); Assert.notNull(this.messages, "A message source must be set"); } protected final void checkAllowIfAllAbstainDecisions() { if (!this.isAllowIfAllAbstainDecisions()) { throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); } } public List getDecisionVoters() { return this.decisionVoters; } public boolean isAllowIfAllAbstainDecisions() { return allowIfAllAbstainDecisions; } public void setAllowIfAllAbstainDecisions(boolean allowIfAllAbstainDecisions) { this.allowIfAllAbstainDecisions = allowIfAllAbstainDecisions; } public void setDecisionVoters(List newList) { Assert.notEmpty(newList); Iterator iter = newList.iterator(); while (iter.hasNext()) { Object currentObject = iter.next(); Assert.isInstanceOf(AccessDecisionVoter.class, currentObject, "AccessDecisionVoter " + currentObject.getClass().getName() + " must implement AccessDecisionVoter"); } this.decisionVoters = newList; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public boolean supports(ConfigAttribute attribute) { Iterator iter = this.decisionVoters.iterator(); while (iter.hasNext()) { AccessDecisionVoter voter = (AccessDecisionVoter) iter.next(); if (voter.supports(attribute)) { return true; } } return false; } /** * Iterates through all AccessDecisionVoters and ensures each can support the presented class. *

    * If one or more voters cannot support the presented class, false is returned. *

    * * @param clazz the type of secured object being presented * @return true if this type is supported */ public boolean supports(Class clazz) { Iterator iter = this.decisionVoters.iterator(); while (iter.hasNext()) { AccessDecisionVoter voter = (AccessDecisionVoter) iter.next(); if (!voter.supports(clazz)) { return false; } } return true; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/LabelBasedAclVoter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/LabelBased0000644000000000000000000002733311623517156030447 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import java.util.Iterator; import java.util.List; import java.util.Vector; import java.util.Map; /** *

    This Acl voter will evaluate methods based on labels applied to incoming arguments. It will only check * methods that have been properly tagged in the MethodSecurityInterceptor with the value stored in * attributeIndicatingLabeledOperation. If a method has been tagged, then it examines each argument, and if the * argument implements {@link LabeledData}, then it will asses if the user's list of granted authorities matches. *

    * *

    By default, if none of the arguments are labeled, then the access will be granted. This can be overridden by * setting allowAccessIfNoAttributesAreLabeled to false in the Spring context file.

    * *

    In many situations, different values are linked together to define a common label, it is necessary to * define a map in the application context that links user-assigned label access to domain object labels. This is done * by setting up the labelMap in the application context.

    * * @author Greg Turnquist * @version $Id$ * * @see org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor * @deprecated Use new spring-security-acl module instead */ public class LabelBasedAclVoter extends AbstractAclVoter { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(LabelBasedAclVoter.class); //~ Instance fields ================================================================================================ private Map labelMap = null; private String attributeIndicatingLabeledOperation = null; private boolean allowAccessIfNoAttributesAreLabeled = true; //~ Methods ======================================================================================================== /** * Set whether or not to allow the user to run methods in which none of the incoming arguments are labeled. * *

    Default value: true, users can run such methods.

    * * @param allowAccessIfNoAttributesAreLabeled boolean */ public void setAllowAccessIfNoAttributesAreLabeled(boolean allowAccessIfNoAttributesAreLabeled) { this.allowAccessIfNoAttributesAreLabeled = allowAccessIfNoAttributesAreLabeled; } /** * Each method intended for evaluation by this voter must include this tag name in the definition of the * MethodSecurityInterceptor, indicating if this voter should evaluate the arguments and compare them against the * label map. * * @param attributeIndicatingLabeledOperation string */ public void setAttributeIndicatingLabeledOperation(String attributeIndicatingLabeledOperation) { this.attributeIndicatingLabeledOperation = attributeIndicatingLabeledOperation; } /** * Set the map that correlate a user's assigned label against domain object values that are considered data * labels. An example application context configuration of a labelMap: * *
         * <bean id="accessDecisionManager" class="org.springframework.security.vote.UnanimousBased">
         *     <property name="allowIfAllAbstainDecisions"><value>false</value></property>
         *     <property name="decisionVoters">
         *       <list>
         *         <bean class="org.springframework.security.vote.RoleVoter"/>
         *         <bean class="org.springframework.security.vote.LabelBasedAclVoter">
         *           <property name="attributeIndicatingLabeledOperation">
         *             <value>LABELED_OPERATION</value>
         *           </property>
         *           <property name="labelMap">
         *             <map>
         *               <entry key="DATA_LABEL_BLUE">
         *                 <list>
         *                   <value>blue</value>
         *                   <value>indigo</value>
         *                   <value>purple</value>
         *                 </list>
         *               </entry>
         *               <entry key="LABEL_ORANGE">
         *                 <list>
         *                   <value>orange</value>
         *                   <value>sunshine</value>
         *                   <value>amber</value>
         *                 </list>
         *               </entry>
         *               <entry key="LABEL_ADMIN">
         *                 <list>
         *                   <value>blue</value>
         *                   <value>indigo</value>
         *                   <value>purple</value>
         *                   <value>orange</value>
         *                   <value>sunshine</value>
         *                   <value>amber</value>
         *                 </list>
         *               </entry>
         *             </map>
         *           </property>
         *         </bean>
         *       </list>
         *     </property>
         *   </bean>
         * 
    * * @param labelMap a map structured as in the above example. * */ public void setLabelMap(Map labelMap) { this.labelMap = labelMap; } /** * This acl voter will only evaluate labeled methods if they are marked in the security interceptor's * configuration with the attribute stored in attributeIndicatingLabeledOperation. * * @param attribute DOCUMENT ME! * * @return DOCUMENT ME! * * @see org.springframework.security.vote.AbstractAclVoter * @see org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor */ public boolean supports(ConfigAttribute attribute) { if (attribute.getAttribute().equals(attributeIndicatingLabeledOperation)) { logger.debug(attribute + " is supported."); return true; } if (logger.isDebugEnabled()) { logger.debug(attribute + " is unsupported."); } return false; } /** * Vote on whether or not the user has all the labels necessary to match the method argument's labeled * data. * * @param authentication DOCUMENT ME! * @param object DOCUMENT ME! * @param config DOCUMENT ME! * * @return ACCESS_ABSTAIN, ACCESS_GRANTED, or ACCESS_DENIED. */ public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { int result = ACCESS_ABSTAIN; if (logger.isDebugEnabled()) { logger.debug("=========================================================="); } if (this.supports((ConfigAttribute) config.getConfigAttributes().iterator().next())) { result = ACCESS_DENIED; /* Parse out the user's labels by examining the security context, and checking * for matches against the label map. */ List userLabels = new Vector(); for (int i = 0; i < authentication.getAuthorities().length; i++) { if (labelMap.containsKey(authentication.getAuthorities()[i].getAuthority())) { String userLabel = authentication.getAuthorities()[i].getAuthority(); userLabels.add(userLabel); logger.debug("Adding " + userLabel + " to <<<" + authentication.getName() + "'s>>> authorized label list"); } } MethodInvocation invocation = (MethodInvocation) object; int matches = 0; int misses = 0; int labeledArguments = 0; for (int j = 0; j < invocation.getArguments().length; j++) { if (invocation.getArguments()[j] instanceof LabeledData) { labeledArguments++; boolean matched = false; String argumentDataLabel = ((LabeledData) invocation.getArguments()[j]).getLabel(); logger.debug("Argument[" + j + "/" + invocation.getArguments()[j].getClass().getName() + "] has a data label of " + argumentDataLabel); List validDataLabels = new Vector(); for (int i = 0; i < userLabels.size(); i++) { validDataLabels.addAll((List) labelMap.get(userLabels.get(i))); } logger.debug("The valid labels for user label " + userLabels + " are " + validDataLabels); Iterator dataLabelIter = validDataLabels.iterator(); while (dataLabelIter.hasNext()) { String validDataLabel = (String) dataLabelIter.next(); if (argumentDataLabel.equals(validDataLabel)) { logger.debug(userLabels + " maps to " + validDataLabel + " which matches the argument"); matched = true; } } if (matched) { logger.debug("We have a match!"); matches++; } else { logger.debug("We have a miss!"); misses++; } } } Assert.isTrue((matches + misses) == labeledArguments, "The matches (" + matches + ") and misses (" + misses + " ) don't add up (" + labeledArguments + ")"); logger.debug("We have " + matches + " matches and " + misses + " misses and " + labeledArguments + " labeled arguments."); /* The result has already been set to ACCESS_DENIED. Only if there is a proper match of * labels will this be overturned. However, if none of the attributes are actually labeled, * the result is dependent on allowAccessIfNoAttributesAreLabeled. */ if ((matches > 0) && (misses == 0)) { result = ACCESS_GRANTED; } else if (labeledArguments == 0) { if (allowAccessIfNoAttributesAreLabeled) { result = ACCESS_GRANTED; } else { result = ACCESS_DENIED; } } } if (logger.isDebugEnabled()) { switch (result) { case ACCESS_GRANTED: logger.debug("===== Access is granted ====="); break; case ACCESS_DENIED: logger.debug("===== Access is denied ====="); break; case ACCESS_ABSTAIN: logger.debug("===== Abstaining ====="); break; } } return result; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/AffirmativeBased.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/Affirmativ0000644000000000000000000000562311623517156030557 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import org.springframework.security.AccessDeniedException; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttributeDefinition; import java.util.Iterator; /** * Simple concrete implementation of {@link org.springframework.security.AccessDecisionManager} that grants access if any * AccessDecisionVoter returns an affirmative response. */ public class AffirmativeBased extends AbstractAccessDecisionManager { //~ Methods ======================================================================================================== /** * This concrete implementation simply polls all configured {@link AccessDecisionVoter}s and grants access * if any AccessDecisionVoter voted affirmatively. Denies access only if there was a deny vote AND no * affirmative votes.

    If every AccessDecisionVoter abstained from voting, the decision will * be based on the {@link #isAllowIfAllAbstainDecisions()} property (defaults to false).

    * * @param authentication the caller invoking the method * @param object the secured object * @param config the configuration attributes associated with the method being invoked * * @throws AccessDeniedException if access is denied */ public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException { Iterator iter = this.getDecisionVoters().iterator(); int deny = 0; while (iter.hasNext()) { AccessDecisionVoter voter = (AccessDecisionVoter) iter.next(); int result = voter.vote(authentication, object, config); switch (result) { case AccessDecisionVoter.ACCESS_GRANTED: return; case AccessDecisionVoter.ACCESS_DENIED: deny++; break; default: break; } } if (deny > 0) { throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); } // To get this far, every AccessDecisionVoter abstained checkAllowIfAllAbstainDecisions(); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/package.ht0000644000000000000000000000013711623517156030467 0ustar Implements a vote-based approach to authorization decisions.

    ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/UnanimousBased.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/UnanimousB0000644000000000000000000000715111623517156030545 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import org.springframework.security.AccessDeniedException; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import java.util.Iterator; /** * Simple concrete implementation of {@link org.springframework.security.AccessDecisionManager} that requires all voters to * abstain or grant access. */ public class UnanimousBased extends AbstractAccessDecisionManager { //~ Methods ======================================================================================================== /** * This concrete implementation polls all configured {@link AccessDecisionVoter}s for each {@link * ConfigAttribute} and grants access if only grant votes were received. *

    * Other voting implementations usually pass the entire list of {@link ConfigAttributeDefinition}s to the * AccessDecisionVoter. This implementation differs in that each AccessDecisionVoter * knows only about a single ConfigAttribute at a time.

    *

    If every AccessDecisionVoter abstained from voting, the decision will be based on the * {@link #isAllowIfAllAbstainDecisions()} property (defaults to false).

    * * @param authentication the caller invoking the method * @param object the secured object * @param config the configuration attributes associated with the method being invoked * * @throws AccessDeniedException if access is denied */ public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException { int grant = 0; int abstain = 0; Iterator configIter = config.getConfigAttributes().iterator(); while (configIter.hasNext()) { ConfigAttributeDefinition singleAttrDef = new ConfigAttributeDefinition((ConfigAttribute) configIter.next()); Iterator voters = this.getDecisionVoters().iterator(); while (voters.hasNext()) { AccessDecisionVoter voter = (AccessDecisionVoter) voters.next(); int result = voter.vote(authentication, object, singleAttrDef); switch (result) { case AccessDecisionVoter.ACCESS_GRANTED: grant++; break; case AccessDecisionVoter.ACCESS_DENIED: throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); default: abstain++; break; } } } // To get this far, there were no deny votes if (grant > 0) { return; } // To get this far, every AccessDecisionVoter abstained checkAllowIfAllAbstainDecisions(); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/RoleVoter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/RoleVoter.0000644000000000000000000001105011623517156030455 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import java.util.Iterator; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.GrantedAuthority; /** * Votes if any {@link ConfigAttribute#getAttribute()} starts with a prefix * indicating that it is a role. The default prefix string is ROLE_, * but this may be overridden to any value. It may also be set to empty, which * means that essentially any attribute will be voted on. As described further * below, the effect of an empty prefix may not be quite desirable. *

    * Abstains from voting if no configuration attribute commences with the role * prefix. Votes to grant access if there is an exact matching * {@link org.springframework.security.GrantedAuthority} to a ConfigAttribute * starting with the role prefix. Votes to deny access if there is no exact * matching GrantedAuthority to a ConfigAttribute * starting with the role prefix. *

    * An empty role prefix means that the voter will vote for every * ConfigAttribute. When there are different categories of ConfigAttributes * used, this will not be optimal since the voter will be voting for attributes * which do not represent roles. However, this option may be of some use when * using pre-existing role names without a prefix, and no ability exists to * prefix them with a role prefix on reading them in, such as provided for * example in {@link org.springframework.security.userdetails.jdbc.JdbcDaoImpl}. *

    * All comparisons and prefixes are case sensitive. * * @author Ben Alex * @author colin sampaleanu * @version $Id$ */ public class RoleVoter implements AccessDecisionVoter { //~ Instance fields ================================================================================================ private String rolePrefix = "ROLE_"; //~ Methods ======================================================================================================== public String getRolePrefix() { return rolePrefix; } /** * Allows the default role prefix of ROLE_ to be overridden. * May be set to an empty value, although this is usually not desirable. * * @param rolePrefix the new prefix */ public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getRolePrefix())) { return true; } else { return false; } } /** * This implementation supports any type of class, because it does not query * the presented secure object. * * @param clazz the secure object * * @return always true */ public boolean supports(Class clazz) { return true; } public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { int result = ACCESS_ABSTAIN; Iterator iter = config.getConfigAttributes().iterator(); GrantedAuthority[] authorities = extractAuthorities(authentication); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (this.supports(attribute)) { result = ACCESS_DENIED; // Attempt to find a matching granted authority for (int i = 0; i < authorities.length; i++) { if (attribute.getAttribute().equals(authorities[i].getAuthority())) { return ACCESS_GRANTED; } } } } return result; } GrantedAuthority[] extractAuthorities(Authentication authentication) { return authentication.getAuthorities(); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/AccessDecisionVoter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/AccessDeci0000644000000000000000000001034011623517156030445 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; /** * Indicates a class is responsible for voting on authorization decisions. * *

    * The coordination of voting (ie polling AccessDecisionVoters, * tallying their responses, and making the final authorization decision) is * performed by an {@link org.springframework.security.AccessDecisionManager}. *

    * * @author Ben Alex * @version $Id$ */ public interface AccessDecisionVoter { //~ Static fields/initializers ===================================================================================== int ACCESS_GRANTED = 1; int ACCESS_ABSTAIN = 0; int ACCESS_DENIED = -1; //~ Methods ======================================================================================================== /** * Indicates whether this AccessDecisionVoter is able to vote on the passed * ConfigAttribute.

    This allows the AbstractSecurityInterceptor to check every * configuration attribute can be consumed by the configured AccessDecisionManager and/or * RunAsManager and/or AfterInvocationManager.

    * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor * * @return true if this AccessDecisionVoter can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); /** * Indicates whether the AccessDecisionVoter implementation is able to provide access control * votes for the indicated secured object type. * * @param clazz the class that is being queried * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); /** * Indicates whether or not access is granted. *

    The decision must be affirmative (ACCESS_GRANTED), negative (ACCESS_DENIED) * or the AccessDecisionVoter can abstain (ACCESS_ABSTAIN) from voting. * Under no circumstances should implementing classes return any other value. If a weighting of results is desired, * this should be handled in a custom {@link org.springframework.security.AccessDecisionManager} instead. *

    *

    Unless an AccessDecisionVoter is specifically intended to vote on an access control * decision due to a passed method invocation or configuration attribute parameter, it must return * ACCESS_ABSTAIN. This prevents the coordinating AccessDecisionManager from counting * votes from those AccessDecisionVoters without a legitimate interest in the access control * decision. *

    *

    Whilst the method invocation is passed as a parameter to maximise flexibility in making access * control decisions, implementing classes must never modify the behaviour of the method invocation (such as * calling MethodInvocation.proceed()).

    * * @param authentication the caller invoking the method * @param object the secured object * @param config the configuration attributes associated with the method being invoked * * @return either {@link #ACCESS_GRANTED}, {@link #ACCESS_ABSTAIN} or {@link #ACCESS_DENIED} */ int vote(Authentication authentication, Object object, ConfigAttributeDefinition config); } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/AbstractAclVoter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/AbstractAc0000644000000000000000000000636311623517156030500 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import org.springframework.security.AuthorizationServiceException; import org.aopalliance.intercept.MethodInvocation; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.CodeSignature; import org.springframework.util.Assert; /** *

    Provides helper methods for writing domain object ACL voters. Is not bound to any particular ACL system.

    * * @author Ben Alex * @version $Id$ */ public abstract class AbstractAclVoter implements AccessDecisionVoter { //~ Instance fields ================================================================================================ private Class processDomainObjectClass; //~ Methods ======================================================================================================== protected Object getDomainObjectInstance(Object secureObject) { Object[] args; Class[] params; if (secureObject instanceof MethodInvocation) { MethodInvocation invocation = (MethodInvocation) secureObject; params = invocation.getMethod().getParameterTypes(); args = invocation.getArguments(); } else { JoinPoint jp = (JoinPoint) secureObject; params = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes(); args = jp.getArgs(); } for (int i = 0; i < params.length; i++) { if (processDomainObjectClass.isAssignableFrom(params[i])) { return args[i]; } } throw new AuthorizationServiceException("Secure object: " + secureObject + " did not provide any argument of type: " + processDomainObjectClass); } public Class getProcessDomainObjectClass() { return processDomainObjectClass; } public void setProcessDomainObjectClass(Class processDomainObjectClass) { Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null"); this.processDomainObjectClass = processDomainObjectClass; } /** * This implementation supports only MethodSecurityInterceptor, because it queries the * presented MethodInvocation. * * @param clazz the secure object * * @return true if the secure object is MethodInvocation, false otherwise */ public boolean supports(Class clazz) { if (MethodInvocation.class.isAssignableFrom(clazz)) { return true; } else if (JoinPoint.class.isAssignableFrom(clazz)) { return true; } else { return false; } } } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/InterfaceBasedLabelParameterStrategy.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/InterfaceB0000644000000000000000000000504411623517156030466 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import java.lang.reflect.Method; /** * This is a very useful implementation of the LabelParameterStrategy. Data objects which are meant to be labeled * should implement the LabeledData interface. This strategy will then castdown to that interface for either testing * or retrieval of the label. * * @author Greg Turnquist * @version $Id$ */ public class InterfaceBasedLabelParameterStrategy implements LabelParameterStrategy { //~ Instance fields ================================================================================================ private String noLabel = ""; //~ Methods ======================================================================================================== /** * Test if the argument is labeled, and if so, downcast to LabeledData and retrieve the domain object's * labeled value. Otherwise, return an empty string. NOTE: The default for no label is an empty string. If somehow * the user wants to make that a label itself, he or she must inject an alternate value to the noLabel property. * * @param method DOCUMENT ME! * @param arg DOCUMENT ME! * * @return DOCUMENT ME! */ public String getLabel(Method method, Object arg) { if (isLabeled(method, arg)) { return ((LabeledData) arg).getLabel(); } else { return noLabel; } } public String getNoLabel() { return noLabel; } /** * Test if the argument implemented the LabeledData interface. NOTE: The invoking method has no bearing for * this strategy, only the argument itself. * * @param method DOCUMENT ME! * @param arg DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean isLabeled(Method method, Object arg) { return (arg instanceof LabeledData); } public void setNoLabel(String noLabel) { this.noLabel = noLabel; } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/ConsensusBased.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/ConsensusB0000644000000000000000000000766511623517156030561 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import org.springframework.security.AccessDeniedException; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttributeDefinition; import java.util.Iterator; /** * Simple concrete implementation of {@link org.springframework.security.AccessDecisionManager} that uses a consensus-based * approach. */ public class ConsensusBased extends AbstractAccessDecisionManager { //~ Instance fields ================================================================================================ private boolean allowIfEqualGrantedDeniedDecisions = true; //~ Methods ======================================================================================================== /** * This concrete implementation simply polls all configured {@link AccessDecisionVoter}s and upon * completion determines the consensus of granted vs denied responses.

    If there were an equal number of * grant and deny votes, the decision will be based on the {@link #isAllowIfEqualGrantedDeniedDecisions()} * property (defaults to true).

    *

    If every AccessDecisionVoter abstained from voting, the decision will be based on the * {@link #isAllowIfAllAbstainDecisions()} property (defaults to false).

    * * @param authentication the caller invoking the method * @param object the secured object * @param config the configuration attributes associated with the method being invoked * * @throws AccessDeniedException if access is denied */ public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException { Iterator iter = this.getDecisionVoters().iterator(); int grant = 0; int deny = 0; int abstain = 0; while (iter.hasNext()) { AccessDecisionVoter voter = (AccessDecisionVoter) iter.next(); int result = voter.vote(authentication, object, config); switch (result) { case AccessDecisionVoter.ACCESS_GRANTED: grant++; break; case AccessDecisionVoter.ACCESS_DENIED: deny++; break; default: abstain++; break; } } if (grant > deny) { return; } if (deny > grant) { throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); } if ((grant == deny) && (grant != 0)) { if (this.allowIfEqualGrantedDeniedDecisions) { return; } else { throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); } } // To get this far, every AccessDecisionVoter abstained checkAllowIfAllAbstainDecisions(); } public boolean isAllowIfEqualGrantedDeniedDecisions() { return allowIfEqualGrantedDeniedDecisions; } public void setAllowIfEqualGrantedDeniedDecisions(boolean allowIfEqualGrantedDeniedDecisions) { this.allowIfEqualGrantedDeniedDecisions = allowIfEqualGrantedDeniedDecisions; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/RoleHierarchyVoter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/RoleHierar0000644000000000000000000000177411623517156030526 0ustar package org.springframework.security.vote; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; import org.springframework.security.userdetails.hierarchicalroles.RoleHierarchy; import org.springframework.util.Assert; /** * Extended RoleVoter which uses a {@link RoleHierarchy} definition to determine the * roles allocated to the current user before voting. * * @author Luke Taylor * @since 2.0.4 */ public class RoleHierarchyVoter extends RoleVoter { private RoleHierarchy roleHierarchy = null; public RoleHierarchyVoter(RoleHierarchy roleHierarchy) { Assert.notNull(roleHierarchy, "RoleHierarchy must not be null"); this.roleHierarchy = roleHierarchy; } /** * Calls the RoleHierarchy to obtain the complete set of user authorities. */ GrantedAuthority[] extractAuthorities(Authentication authentication) { return roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities()); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/BasicAclEntryVoter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/BasicAclEn0000644000000000000000000003110511623517156030405 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import org.springframework.security.Authentication; import org.springframework.security.AuthorizationServiceException; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.acl.AclEntry; import org.springframework.security.acl.AclManager; import org.springframework.security.acl.basic.BasicAclEntry; import org.springframework.security.acl.basic.SimpleAclEntry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Iterator; /** *

    Given a domain object instance passed as a method argument, ensures the principal has appropriate permission * as defined by the {@link AclManager}.

    *

    The AclManager is used to retrieve the access control list (ACL) permissions associated with a * domain object instance for the current Authentication object. This class is designed to process {@link * AclEntry}s that are subclasses of {@link org.springframework.security.acl.basic.BasicAclEntry} only. Generally these are * obtained by using the {@link org.springframework.security.acl.basic.BasicAclProvider}.

    *

    The voter will vote if any {@link ConfigAttribute#getAttribute()} matches the {@link * #processConfigAttribute}. The provider will then locate the first method argument of type {@link * #processDomainObjectClass}. Assuming that method argument is non-null, the provider will then lookup the ACLs from * the AclManager and ensure the principal is {@link * org.springframework.security.acl.basic.BasicAclEntry#isPermitted(int)} for at least one of the {@link #requirePermission}s.

    *

    If the method argument is null, the voter will abstain from voting. If the method argument * could not be found, an {@link org.springframework.security.AuthorizationServiceException} will be thrown.

    *

    In practical terms users will typically setup a number of BasicAclEntryVoters. Each will have a * different {@link #processDomainObjectClass}, {@link #processConfigAttribute} and {@link #requirePermission} * combination. For example, a small application might employ the following instances of * BasicAclEntryVoter: *

      *
    • Process domain object class BankAccount, configuration attribute * VOTE_ACL_BANK_ACCONT_READ, require permission SimpleAclEntry.READ
    • *
    • Process domain object class BankAccount, configuration attribute * VOTE_ACL_BANK_ACCOUNT_WRITE, require permission list SimpleAclEntry.WRITE and * SimpleAclEntry.CREATE (allowing the principal to have either of these two permissions
    • *
    • Process domain object class Customer, configuration attribute * VOTE_ACL_CUSTOMER_READ, require permission SimpleAclEntry.READ
    • *
    • Process domain object class Customer, configuration attribute * VOTE_ACL_CUSTOMER_WRITE, require permission list SimpleAclEntry.WRITE and * SimpleAclEntry.CREATE
    • *
    * Alternatively, you could have used a common superclass or interface for the {@link #processDomainObjectClass} * if both BankAccount and Customer had common parents.

    *

    If the principal does not have sufficient permissions, the voter will vote to deny access.

    *

    The AclManager is allowed to return any implementations of AclEntry it wishes. * However, this provider will only be able to validate against AbstractBasicAclEntrys, and thus a vote * to deny access will be made if no AclEntry is of type AbstractBasicAclEntry.

    *

    All comparisons and prefixes are case sensitive.

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public class BasicAclEntryVoter extends AbstractAclVoter implements InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(BasicAclEntryVoter.class); //~ Instance fields ================================================================================================ private AclManager aclManager; private String internalMethod; private String processConfigAttribute; private int[] requirePermission; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.notNull(aclManager, "An aclManager is mandatory"); if ((requirePermission == null) || (requirePermission.length == 0)) { throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); } } public AclManager getAclManager() { return aclManager; } /** * Optionally specifies a method of the domain object that will be used to obtain a contained domain * object. That contained domain object will be used for the ACL evaluation. This is useful if a domain object * contains a parent that an ACL evaluation should be targeted for, instead of the child domain object (which * perhaps is being created and as such does not yet have any ACL permissions) * * @return null to use the domain object, or the name of a method (that requires no arguments) that * should be invoked to obtain an Object which will be the domain object used for ACL * evaluation */ public String getInternalMethod() { return internalMethod; } public String getProcessConfigAttribute() { return processConfigAttribute; } public int[] getRequirePermission() { return requirePermission; } public void setAclManager(AclManager aclManager) { this.aclManager = aclManager; } public void setInternalMethod(String internalMethod) { this.internalMethod = internalMethod; } public void setProcessConfigAttribute(String processConfigAttribute) { this.processConfigAttribute = processConfigAttribute; } public void setRequirePermission(int[] requirePermission) { this.requirePermission = requirePermission; } /** * Allow setting permissions with String literals instead of integers as {@link #setRequirePermission(int[])} * * @param requirePermission Permission literals * @see SimpleAclEntry#parsePermissions(String[]) for valid values */ public void setRequirePermissionFromString(String[] requirePermission) { setRequirePermission(SimpleAclEntry.parsePermissions(requirePermission)); } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) { return true; } else { return false; } } public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { Iterator iter = config.getConfigAttributes().iterator(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (this.supports(attr)) { // Need to make an access decision on this invocation // Attempt to locate the domain object instance to process Object domainObject = getDomainObjectInstance(object); // If domain object is null, vote to abstain if (domainObject == null) { if (logger.isDebugEnabled()) { logger.debug("Voting to abstain - domainObject is null"); } return AccessDecisionVoter.ACCESS_ABSTAIN; } // Evaluate if we are required to use an inner domain object if ((internalMethod != null) && !"".equals(internalMethod)) { try { Class clazz = domainObject.getClass(); Method method = clazz.getMethod(internalMethod, new Class[] {}); domainObject = method.invoke(domainObject, new Object[] {}); } catch (NoSuchMethodException nsme) { throw new AuthorizationServiceException("Object of class '" + domainObject.getClass() + "' does not provide the requested internalMethod: " + internalMethod); } catch (IllegalAccessException iae) { if (logger.isDebugEnabled()) { logger.debug("IllegalAccessException", iae); if (iae.getCause() != null) { logger.debug("Cause: " + iae.getCause().getMessage(), iae.getCause()); } } throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod + " for object: " + domainObject); } catch (InvocationTargetException ite) { if (logger.isDebugEnabled()) { logger.debug("InvocationTargetException", ite); if (ite.getCause() != null) { logger.debug("Cause: " + ite.getCause().getMessage(), ite.getCause()); } } throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod + " for object: " + domainObject); } } // Obtain the ACLs applicable to the domain object AclEntry[] acls = aclManager.getAcls(domainObject, authentication); // If principal has no permissions for domain object, deny if ((acls == null) || (acls.length == 0)) { if (logger.isDebugEnabled()) { logger.debug("Voting to deny access - no ACLs returned for this principal"); } return AccessDecisionVoter.ACCESS_DENIED; } // Principal has some permissions for domain object, check them for (int i = 0; i < acls.length; i++) { // Locate processable AclEntrys if (acls[i] instanceof BasicAclEntry) { BasicAclEntry processableAcl = (BasicAclEntry) acls[i]; // See if principal has any of the required permissions for (int y = 0; y < requirePermission.length; y++) { if (processableAcl.isPermitted(requirePermission[y])) { if (logger.isDebugEnabled()) { logger.debug("Voting to grant access"); } return AccessDecisionVoter.ACCESS_GRANTED; } } } } // No permissions match if (logger.isDebugEnabled()) { logger.debug( "Voting to deny access - ACLs returned, but insufficient permissions for this principal"); } return AccessDecisionVoter.ACCESS_DENIED; } } // No configuration attribute matched, so abstain return AccessDecisionVoter.ACCESS_ABSTAIN; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/AuthenticatedVoter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/Authentica0000644000000000000000000001263311623517156030553 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationTrustResolver; import org.springframework.security.AuthenticationTrustResolverImpl; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.util.Assert; import java.util.Iterator; /** *

    Votes if a {@link ConfigAttribute#getAttribute()} of IS_AUTHENTICATED_FULLY or * IS_AUTHENTICATED_REMEMBERED or IS_AUTHENTICATED_ANONYMOUSLY is present. This list is in * order of most strict checking to least strict checking.

    *

    The current Authentication will be inspected to determine if the principal has a particular * level of authentication. The "FULLY" authenticated option means the user is authenticated fully (ie {@link * org.springframework.security.AuthenticationTrustResolver#isAnonymous(Authentication)} is false and {@link * org.springframework.security.AuthenticationTrustResolver#isRememberMe(Authentication)} is false. The "REMEMBERED" will grant * access if the principal was either authenticated via remember-me OR is fully authenticated. The "ANONYMOUSLY" will * grant access if the principal was authenticated via remember-me, OR anonymously, OR via full authentication.

    *

    All comparisons and prefixes are case sensitive.

    * * @author Ben Alex * @version $Id$ */ public class AuthenticatedVoter implements AccessDecisionVoter { //~ Static fields/initializers ===================================================================================== public static final String IS_AUTHENTICATED_FULLY = "IS_AUTHENTICATED_FULLY"; public static final String IS_AUTHENTICATED_REMEMBERED = "IS_AUTHENTICATED_REMEMBERED"; public static final String IS_AUTHENTICATED_ANONYMOUSLY = "IS_AUTHENTICATED_ANONYMOUSLY"; //~ Instance fields ================================================================================================ private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); //~ Methods ======================================================================================================== private boolean isFullyAuthenticated(Authentication authentication) { return (!authenticationTrustResolver.isAnonymous(authentication) && !authenticationTrustResolver.isRememberMe(authentication)); } public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver) { Assert.notNull(authenticationTrustResolver, "AuthenticationTrustResolver cannot be set to null"); this.authenticationTrustResolver = authenticationTrustResolver; } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute()) || IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute()) || IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute()))) { return true; } else { return false; } } /** * This implementation supports any type of class, because it does not query the presented secure object. * * @param clazz the secure object * * @return always true */ public boolean supports(Class clazz) { return true; } public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { int result = ACCESS_ABSTAIN; Iterator iter = config.getConfigAttributes().iterator(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (this.supports(attribute)) { result = ACCESS_DENIED; if (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())) { if (isFullyAuthenticated(authentication)) { return ACCESS_GRANTED; } } if (IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())) { if (authenticationTrustResolver.isRememberMe(authentication) || isFullyAuthenticated(authentication)) { return ACCESS_GRANTED; } } if (IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute())) { if (authenticationTrustResolver.isAnonymous(authentication) || isFullyAuthenticated(authentication) || authenticationTrustResolver.isRememberMe(authentication)) { return ACCESS_GRANTED; } } } } return result; } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/LabelParameterStrategy.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/vote/LabelParam0000644000000000000000000000325211623517156030463 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import java.lang.reflect.Method; /** * This is a strategy interface for determining which parts of a method invocation * are labeled. Not all arguments are necessarily labeled. This offers a plugabble * mechanism to define various ways to label data. * * @author Greg Turnquist * @version $Id$ */ public interface LabelParameterStrategy { //~ Methods ======================================================================================================== /** * Get the actual label associated with the argument. NOTE: This currently only supports one label per * argument. * * @param method * @param arg * * @return string value of the label */ String getLabel(Method method, Object arg); /** * Evaluate if one particular argument is labeled. The context of the method is also provided should that * have bearing on the label. * * @param method * @param arg * * @return boolean */ boolean isLabeled(Method method, Object arg); } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthenticationTrustResolver.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthenticationT0000644000000000000000000000525011623517156030611 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Evaluates Authentication tokens * * @author Ben Alex * @version $Id$ */ public interface AuthenticationTrustResolver { //~ Methods ======================================================================================================== /** * Indicates whether the passed Authentication token represents an anonymous user. Typically * the framework will call this method if it is trying to decide whether an AccessDeniedException * should result in a final rejection (ie as would be the case if the principal was non-anonymous/fully * authenticated) or direct the principal to attempt actual authentication (ie as would be the case if the * Authentication was merely anonymous). * * @param authentication to test (may be null in which case the method will always return * false) * * @return true the passed authentication token represented an anonymous principal, false * otherwise */ boolean isAnonymous(Authentication authentication); /** * Indicates whether the passed Authentication token represents user that has been remembered * (ie not a user that has been fully authenticated).

    No part of the framework uses this method, * as it is a weak definition of trust levels. The method is provided simply to assist with custom * AccessDecisionVoters and the like that you might develop. Of course, you don't need to use this * method either and can develop your own "trust level" hierarchy instead.

    * * @param authentication to test (may be null in which case the method will always return * false) * * @return true the passed authentication token represented a principal authenticated using a * remember-me token, false otherwise */ boolean isRememberMe(Authentication authentication); } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_de.propertiesspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_de.pro0000644000000000000000000001060311623517156030562 0ustar AuthByAdapterProvider.incorrectKey=Die angegebene AuthByAdapter-Implementierung enthält nicht den erwarteten Schlüssel BasicAclEntryAfterInvocationProvider.noPermission=Authentifikation {0} hat KEINE Berechtigungen bezüglich des Domänen-Objekts {1} BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentifikation {0} hat keine ausreichenden ACL-Berechtigungen bezüglich des Domänen-Objekts {1} ConcurrentSessionControllerImpl.exceededAllowed=Die maximale Sitzungs-Anzahl von {0} für diesen Nutzer wurde überschritten ProviderManager.providerNotFound=Für {0} wurde kein AuthenticationProvider gefunden AnonymousAuthenticationProvider.incorrectKey=Das angegebene AnonymousAuthenticationToken enthält nicht den erwarteten Schlüssel CasAuthenticationProvider.incorrectKey=Das angegebene CasAuthenticationToken enthält nicht den erwarteten Schlüssel CasAuthenticationProvider.noServiceTicket=Es konnte kein CAS Service-Ticket zur Prüfung geliefert werden NamedCasProxyDecider.untrusted=Der nächste Proxy {0} ist nicht vertrauenswürdig RejectProxyTickets.reject=Proxy-Tickets sind abgelehnt AbstractSecurityInterceptor.authenticationNotFound=Im SecurityContext wurde keine Authentifikation gefunden AbstractUserDetailsAuthenticationProvider.onlySupports=Nur UsernamePasswordAuthenticationToken wird unterstützt AbstractUserDetailsAuthenticationProvider.locked=Das Benutzerkonto ist gesperrt AbstractUserDetailsAuthenticationProvider.disabled=Der Benutzer ist deaktiviert AbstractUserDetailsAuthenticationProvider.expired=Die Gültigkeit des Benutzerkontos ist abgelaufen AbstractUserDetailsAuthenticationProvider.credentialsExpired=Die Gültigkeit der Benutzerberechtigungen ist abgelaufen AbstractUserDetailsAuthenticationProvider.badCredentials=Ungültige Benutzerberechtigungen X509AuthenticationProvider.certificateNull=Zertifikat ist nicht gesetzt DaoX509AuthoritiesPopulator.noMatching=Kein passendes Muster gefunden in subjectDN: {0} RememberMeAuthenticationProvider.incorrectKey=Das angegebene RememberMeAuthenticationToken enthält nicht den erwarteten Schlüssel RunAsImplAuthenticationProvider.incorrectKey=Das angegebene RunAsUserToken enthält nicht den erwarteten Schlüssel DigestProcessingFilter.missingMandatory=Erforderlicher Digest-Wert fehlt; Empfangener Header {0} DigestProcessingFilter.missingAuth=Erforderlicher Digest-Wert fehlt für 'auth' QOP; Empfangener Header {0} DigestProcessingFilter.incorrectRealm=Realm-Name in Antwort {0} entspricht nicht dem Namen des System-Realms {1} DigestProcessingFilter.nonceExpired=Die Nonce ist nicht mehr gültig DigestProcessingFilter.nonceEncoding=Die Nonce ist nicht in Base64 kodiert; Empfangene Nonce {0} DigestProcessingFilter.nonceNotTwoTokens=Nonce sollte zwei Elemente beinhalten. Gefundener Inhalt: {0} DigestProcessingFilter.nonceNotNumeric=Das erste Element der Nonce sollte numerisch sein. Gefundener Inhalt: {0} DigestProcessingFilter.nonceCompromised=Das Nonce-Element ist kompromittiert {0} DigestProcessingFilter.usernameNotFound=Benutzername {0} wurde nicht gefunden DigestProcessingFilter.incorrectResponse=Fehlerhafte Antwort SwitchUserProcessingFilter.noCurrentUser=Mit dieser Anfrage ist kein aktueller Benutzer assoziiert SwitchUserProcessingFilter.noOriginalAuthentication=Kann das ursprüngliche Authentifikationsobjekt nicht finden SwitchUserProcessingFilter.usernameNotFound=Benutzername {0} wurde nicht gefunden SwitchUserProcessingFilter.locked=Das Benutzerkonto ist gesperrt SwitchUserProcessingFilter.disabled=Der Benutzer ist deaktiviert SwitchUserProcessingFilter.expired=Die Gültigkeit des Benutzerkontos ist abgelaufen SwitchUserProcessingFilter.credentialsExpired=Die Gültigkeit der Benutzerberechtigungen ist abgelaufen AbstractAccessDecisionManager.accessDenied=Zugriff verweigert LdapAuthenticationProvider.emptyUsername=Ein leerer Benutzername ist nicht erlaubt LdapAuthenticationProvider.emptyPassword=Ungültige Benutzerberechtigungen DefaultIntitalDirContextFactory.communicationFailure=Kann keine Verbindung zum LDAP-Server herstellen DefaultIntitalDirContextFactory.badCredentials=Ungültige Benutzerberechtigungen DefaultIntitalDirContextFactory.unexpectedException=Auf den InitialDirContext kann aufgrund eines unerwarteten Fehlers nicht zugegriffen werden PasswordComparisonAuthenticator.badCredentials=Ungültige Benutzerberechtigungen BindAuthenticator.badCredentials=Ungültige Benutzerberechtigungen BindAuthenticator.failedToLoadAttributes=Ungültige Benutzerberechtigungen ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation0000755000000000000000000000000011623517156030675 5ustar ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation/AfterInvocationProviderManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation0000644000000000000000000001233211623517156030700 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.afterinvocation; import org.springframework.security.AccessDeniedException; import org.springframework.security.AfterInvocationManager; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.util.Iterator; import java.util.List; /** * Provider-based implementation of {@link AfterInvocationManager}.

    Handles configuration of a bean context * defined list of {@link AfterInvocationProvider}s.

    *

    Every AfterInvocationProvider will be polled when the {@link #decide(Authentication, Object, * ConfigAttributeDefinition, Object)} method is called. The Object returned from each provider will be * presented to the successive provider for processing. This means each provider must ensure they return the * Object, even if they are not interested in the "after invocation" decision (perhaps as the secure * object invocation did not include a configuration attribute a given provider is configured to respond to).

    * * @author Ben Alex * @version $Id$ */ public class AfterInvocationProviderManager implements AfterInvocationManager, InitializingBean { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(AfterInvocationProviderManager.class); //~ Instance fields ================================================================================================ private List providers; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { checkIfValidList(this.providers); } private void checkIfValidList(List listToCheck) { if ((listToCheck == null) || (listToCheck.size() == 0)) { throw new IllegalArgumentException("A list of AfterInvocationProviders is required"); } } public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { Iterator iter = this.providers.iterator(); Object result = returnedObject; while (iter.hasNext()) { AfterInvocationProvider provider = (AfterInvocationProvider) iter.next(); result = provider.decide(authentication, object, config, result); } return result; } public List getProviders() { return this.providers; } public void setProviders(List newList) { checkIfValidList(newList); Iterator iter = newList.iterator(); while (iter.hasNext()) { Object currentObject = iter.next(); Assert.isInstanceOf(AfterInvocationProvider.class, currentObject, "AfterInvocationProvider " + currentObject.getClass().getName() + " must implement AfterInvocationProvider"); } this.providers = newList; } public boolean supports(ConfigAttribute attribute) { Iterator iter = this.providers.iterator(); while (iter.hasNext()) { AfterInvocationProvider provider = (AfterInvocationProvider) iter.next(); if (logger.isDebugEnabled()) { logger.debug("Evaluating " + attribute + " against " + provider); } if (provider.supports(attribute)) { return true; } } return false; } /** * Iterates through all AfterInvocationProviders and ensures each can support the presented * class.

    If one or more providers cannot support the presented class, false is returned.

    * * @param clazz the secure object class being queries * * @return if the AfterInvocationProviderManager can support the secure object class, which requires * every one of its AfterInvocationProviders to support the secure object class */ public boolean supports(Class clazz) { Iterator iter = this.providers.iterator(); while (iter.hasNext()) { AfterInvocationProvider provider = (AfterInvocationProvider) iter.next(); if (!provider.supports(clazz)) { return false; } } return true; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation0000644000000000000000000000015611623517156030701 0ustar Used for post-processing of an object returned from a secure object invocation. ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation/Filterer.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation0000644000000000000000000000257611623517156030711 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.afterinvocation; import java.util.Iterator; /** * Filter strategy interface. * * @author Ben Alex * @author Paulo Neves * @version $Id$ */ interface Filterer { //~ Methods ======================================================================================================== /** * Gets the filtered collection or array. * * @return the filtered collection or array */ Object getFilteredObject(); /** * Returns an iterator over the filtered collection or array. * * @return an Iterator */ Iterator iterator(); /** * Removes the the given object from the resulting list. * * @param object the object to be removed */ void remove(Object object); } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation/CollectionFilterer.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation0000644000000000000000000000671711623517156030712 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.afterinvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * A filter used to filter Collections. * * @author Ben Alex * @author Paulo Neves * @version $Id$ */ class CollectionFilterer implements Filterer { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(CollectionFilterer.class); //~ Instance fields ================================================================================================ private Collection collection; // collectionIter offers significant performance optimisations (as // per security-developer mailing list conversation 19/5/05) private Iterator collectionIter; private Set removeList; //~ Constructors =================================================================================================== CollectionFilterer(Collection collection) { this.collection = collection; // We create a Set of objects to be removed from the Collection, // as ConcurrentModificationException prevents removal during // iteration, and making a new Collection to be returned is // problematic as the original Collection implementation passed // to the method may not necessarily be re-constructable (as // the Collection(collection) constructor is not guaranteed and // manually adding may lose sort order or other capabilities) removeList = new HashSet(); } //~ Methods ======================================================================================================== /** * * @see org.springframework.security.afterinvocation.Filterer#getFilteredObject() */ public Object getFilteredObject() { // Now the Iterator has ended, remove Objects from Collection Iterator removeIter = removeList.iterator(); int originalSize = collection.size(); while (removeIter.hasNext()) { collection.remove(removeIter.next()); } if (logger.isDebugEnabled()) { logger.debug("Original collection contained " + originalSize + " elements; now contains " + collection.size() + " elements"); } return collection; } /** * * @see org.springframework.security.afterinvocation.Filterer#iterator() */ public Iterator iterator() { collectionIter = collection.iterator(); return collectionIter; } /** * * @see org.springframework.security.afterinvocation.Filterer#remove(java.lang.Object) */ public void remove(Object object) { removeList.add(object); } } ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation/BasicAclEntryAfterInvocationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation0000644000000000000000000002371311623517156030705 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.afterinvocation; import org.springframework.security.AccessDeniedException; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.acl.AclEntry; import org.springframework.security.acl.AclManager; import org.springframework.security.acl.basic.BasicAclEntry; import org.springframework.security.acl.basic.SimpleAclEntry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.util.Iterator; /** *

    Given a domain object instance returned from a secure object invocation, ensures the principal has * appropriate permission as defined by the {@link AclManager}.

    *

    The AclManager is used to retrieve the access control list (ACL) permissions associated with a * domain object instance for the current Authentication object. This class is designed to process {@link * AclEntry}s that are subclasses of {@link org.springframework.security.acl.basic.BasicAclEntry} only. Generally these are * obtained by using the {@link org.springframework.security.acl.basic.BasicAclProvider}.

    *

    This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link * #processConfigAttribute}. The provider will then lookup the ACLs from the AclManager and ensure the * principal is {@link org.springframework.security.acl.basic.BasicAclEntry#isPermitted(int)} for at least one of the {@link * #requirePermission}s.

    *

    Often users will setup a BasicAclEntryAfterInvocationProvider with a {@link * #processConfigAttribute} of AFTER_ACL_READ and a {@link #requirePermission} of * SimpleAclEntry.READ. These are also the defaults.

    *

    If the principal does not have sufficient permissions, an AccessDeniedException will be thrown.

    *

    The AclManager is allowed to return any implementations of AclEntry it wishes. * However, this provider will only be able to validate against BasicAclEntrys, and thus access will be * denied if no AclEntry is of type BasicAclEntry.

    *

    If the provided returnObject is null, permission will always be granted and * null will be returned.

    *

    All comparisons and prefixes are case sensitive.

    * * @deprecated Use new spring-security-acl module instead */ public class BasicAclEntryAfterInvocationProvider implements AfterInvocationProvider, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationProvider.class); //~ Instance fields ================================================================================================ private AclManager aclManager; private Class processDomainObjectClass = Object.class; protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private String processConfigAttribute = "AFTER_ACL_READ"; private int[] requirePermission = {SimpleAclEntry.READ}; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.notNull(aclManager, "An aclManager is mandatory"); Assert.notNull(messages, "A message source must be set"); if ((requirePermission == null) || (requirePermission.length == 0)) { throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); } } public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { Iterator iter = config.getConfigAttributes().iterator(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (this.supports(attr)) { // Need to make an access decision on this invocation if (returnedObject == null) { // AclManager interface contract prohibits nulls // As they have permission to null/nothing, grant access if (logger.isDebugEnabled()) { logger.debug("Return object is null, skipping"); } return null; } if (!processDomainObjectClass.isAssignableFrom(returnedObject.getClass())) { if (logger.isDebugEnabled()) { logger.debug("Return object is not applicable for this provider, skipping"); } return null; } AclEntry[] acls = aclManager.getAcls(returnedObject, authentication); if ((acls == null) || (acls.length == 0)) { throw new AccessDeniedException(messages.getMessage( "BasicAclEntryAfterInvocationProvider.noPermission", new Object[] {authentication.getName(), returnedObject}, "Authentication {0} has NO permissions at all to the domain object {1}", LocaleContextHolder.getLocale())); } for (int i = 0; i < acls.length; i++) { // Locate processable AclEntrys if (acls[i] instanceof BasicAclEntry) { BasicAclEntry processableAcl = (BasicAclEntry) acls[i]; // See if principal has any of the required permissions for (int y = 0; y < requirePermission.length; y++) { if (processableAcl.isPermitted(requirePermission[y])) { if (logger.isDebugEnabled()) { logger.debug("Principal DOES have permission to return object: " + returnedObject + " due to ACL: " + processableAcl.toString()); } return returnedObject; } } } } // No permissions match throw new AccessDeniedException(messages.getMessage( "BasicAclEntryAfterInvocationProvider.insufficientPermission", new Object[] {authentication.getName(), returnedObject}, "Authentication {0} has ACL permissions to the domain object, " + "but not the required ACL permission to the domain object {1}", LocaleContextHolder.getLocale())); } } return returnedObject; } public AclManager getAclManager() { return aclManager; } public String getProcessConfigAttribute() { return processConfigAttribute; } public int[] getRequirePermission() { return requirePermission; } public void setAclManager(AclManager aclManager) { this.aclManager = aclManager; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setProcessConfigAttribute(String processConfigAttribute) { this.processConfigAttribute = processConfigAttribute; } public void setProcessDomainObjectClass(Class processDomainObjectClass) { Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null"); this.processDomainObjectClass = processDomainObjectClass; } public void setRequirePermission(int[] requirePermission) { this.requirePermission = requirePermission; } /** * Allow setting permissions with String literals instead of integers as {@link #setRequirePermission(int[])} * * @param requiredPermissions Permission literals * @see SimpleAclEntry#parsePermissions(String[]) for valid values */ public void setRequirePermissionFromString(String[] requiredPermissions) { setRequirePermission(SimpleAclEntry.parsePermissions(requiredPermissions)); } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) { return true; } else { return false; } } /** * This implementation supports any type of class, because it does not query the presented secure object. * * @param clazz the secure object * * @return always true */ public boolean supports(Class clazz) { return true; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation/ArrayFilterer.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation0000644000000000000000000000633511623517156030706 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.afterinvocation; import org.apache.commons.collections.iterators.ArrayIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.lang.reflect.Array; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * A filter used to filter arrays. * * @author Ben Alex * @author Paulo Neves * @version $Id$ */ class ArrayFilterer implements Filterer { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class); //~ Instance fields ================================================================================================ private Set removeList; private Object[] list; //~ Constructors =================================================================================================== ArrayFilterer(Object[] list) { this.list = list; // Collect the removed objects to a HashSet so that // it is fast to lookup them when a filtered array // is constructed. removeList = new HashSet(); } //~ Methods ======================================================================================================== /** * * @see org.springframework.security.afterinvocation.Filterer#getFilteredObject() */ public Object getFilteredObject() { // Recreate an array of same type and filter the removed objects. int originalSize = list.length; int sizeOfResultingList = originalSize - removeList.size(); Object[] filtered = (Object[]) Array.newInstance(list.getClass().getComponentType(), sizeOfResultingList); for (int i = 0, j = 0; i < list.length; i++) { Object object = list[i]; if (!removeList.contains(object)) { filtered[j] = object; j++; } } if (logger.isDebugEnabled()) { logger.debug("Original array contained " + originalSize + " elements; now contains " + sizeOfResultingList + " elements"); } return filtered; } /** * * @see org.springframework.security.afterinvocation.Filterer#iterator() */ public Iterator iterator() { return new ArrayIterator(list); } /** * * @see org.springframework.security.afterinvocation.Filterer#remove(java.lang.Object) */ public void remove(Object object) { removeList.add(object); } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation/AfterInvocationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation0000644000000000000000000000473311623517156030706 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.afterinvocation; import org.springframework.security.AccessDeniedException; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; /** * Indicates a class is responsible for participating in an {@link AfterInvocationProviderManager} decision. * * @author Ben Alex * @version $Id$ */ public interface AfterInvocationProvider { //~ Methods ======================================================================================================== Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException; /** * Indicates whether this AfterInvocationProvider is able to participate in a decision * involving the passed ConfigAttribute.

    This allows the * AbstractSecurityInterceptor to check every configuration attribute can be consumed by the * configured AccessDecisionManager and/or RunAsManager and/or * AccessDecisionManager.

    * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor * * @return true if this AfterInvocationProvider can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); /** * Indicates whether the AfterInvocationProvider is able to provide "after invocation" * processing for the indicated secured object type. * * @param clazz the class of secure object that is being queried * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); } ././@LongLink0000000000000000000000000000024200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation/BasicAclEntryAfterInvocationCollectionFilteringProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/afterinvocation0000644000000000000000000002475011623517156030707 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.afterinvocation; import org.springframework.security.AccessDeniedException; import org.springframework.security.Authentication; import org.springframework.security.AuthorizationServiceException; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.acl.AclEntry; import org.springframework.security.acl.AclManager; import org.springframework.security.acl.basic.BasicAclEntry; import org.springframework.security.acl.basic.SimpleAclEntry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.util.Collection; import java.util.Iterator; /** *

    Given a Collection of domain object instances returned from a secure object invocation, remove * any Collection elements the principal does not have appropriate permission to access as defined by the * {@link AclManager}.

    *

    The AclManager is used to retrieve the access control list (ACL) permissions associated with * each Collection domain object instance element for the current Authentication object. * This class is designed to process {@link AclEntry}s that are subclasses of {@link * org.springframework.security.acl.basic.BasicAclEntry} only. Generally these are obtained by using the {@link * org.springframework.security.acl.basic.BasicAclProvider}.

    *

    This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link * #processConfigAttribute}. The provider will then lookup the ACLs from the AclManager and ensure the * principal is {@link org.springframework.security.acl.basic.BasicAclEntry#isPermitted(int)} for at least one of the {@link * #requirePermission}s for each Collection element. If the principal does not have at least one of the * permissions, that element will not be included in the returned Collection.

    *

    Often users will setup a BasicAclEntryAfterInvocationProvider with a {@link * #processConfigAttribute} of AFTER_ACL_COLLECTION_READ and a {@link #requirePermission} of * SimpleAclEntry.READ. These are also the defaults.

    *

    The AclManager is allowed to return any implementations of AclEntry it wishes. * However, this provider will only be able to validate against BasicAclEntrys, and thus a * Collection element will be filtered from the resulting Collection if no * AclEntry is of type BasicAclEntry.

    *

    If the provided returnObject is null, a nullCollection * will be returned. If the provided returnObject is not a Collection, an {@link * AuthorizationServiceException} will be thrown.

    *

    All comparisons and prefixes are case sensitive.

    * * @author Ben Alex * @author Paulo Neves * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public class BasicAclEntryAfterInvocationCollectionFilteringProvider implements AfterInvocationProvider, InitializingBean { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class); //~ Instance fields ================================================================================================ private AclManager aclManager; private Class processDomainObjectClass = Object.class; private String processConfigAttribute = "AFTER_ACL_COLLECTION_READ"; private int[] requirePermission = {SimpleAclEntry.READ}; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.notNull(aclManager, "An aclManager is mandatory"); if ((requirePermission == null) || (requirePermission.length == 0)) { throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); } } public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { Iterator iter = config.getConfigAttributes().iterator(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (this.supports(attr)) { // Need to process the Collection for this invocation if (returnedObject == null) { if (logger.isDebugEnabled()) { logger.debug("Return object is null, skipping"); } return null; } Filterer filterer = null; if (returnedObject instanceof Collection) { Collection collection = (Collection) returnedObject; filterer = new CollectionFilterer(collection); } else if (returnedObject.getClass().isArray()) { Object[] array = (Object[]) returnedObject; filterer = new ArrayFilterer(array); } else { throw new AuthorizationServiceException("A Collection or an array (or null) was required as the " + "returnedObject, but the returnedObject was: " + returnedObject); } // Locate unauthorised Collection elements Iterator collectionIter = filterer.iterator(); while (collectionIter.hasNext()) { Object domainObject = collectionIter.next(); boolean hasPermission = false; if (domainObject == null) { hasPermission = true; } else if (!processDomainObjectClass.isAssignableFrom(domainObject.getClass())) { hasPermission = true; } else { AclEntry[] acls = aclManager.getAcls(domainObject, authentication); if ((acls != null) && (acls.length != 0)) { for (int i = 0; i < acls.length; i++) { // Locate processable AclEntrys if (acls[i] instanceof BasicAclEntry) { BasicAclEntry processableAcl = (BasicAclEntry) acls[i]; // See if principal has any of the required permissions for (int y = 0; y < requirePermission.length; y++) { if (processableAcl.isPermitted(requirePermission[y])) { hasPermission = true; if (logger.isDebugEnabled()) { logger.debug("Principal is authorised for element: " + domainObject + " due to ACL: " + processableAcl.toString()); } } } } } } if (!hasPermission) { filterer.remove(domainObject); if (logger.isDebugEnabled()) { logger.debug("Principal is NOT authorised for element: " + domainObject); } } } } return filterer.getFilteredObject(); } } return returnedObject; } public AclManager getAclManager() { return aclManager; } public String getProcessConfigAttribute() { return processConfigAttribute; } public int[] getRequirePermission() { return requirePermission; } public void setAclManager(AclManager aclManager) { this.aclManager = aclManager; } public void setProcessConfigAttribute(String processConfigAttribute) { this.processConfigAttribute = processConfigAttribute; } public void setProcessDomainObjectClass(Class processDomainObjectClass) { Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null"); this.processDomainObjectClass = processDomainObjectClass; } public void setRequirePermission(int[] requirePermission) { this.requirePermission = requirePermission; } /** * Allow setting permissions with String literals instead of integers as {@link * #setRequirePermission(int[])} * * @param requiredPermissions permission literals * * @see SimpleAclEntry#parsePermissions(String[]) for valid values */ public void setRequirePermissionFromString(String[] requiredPermissions) { setRequirePermission(SimpleAclEntry.parsePermissions(requiredPermissions)); } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) { return true; } else { return false; } } /** * This implementation supports any type of class, because it does not query the presented secure object. * * @param clazz the secure object * * @return always true */ public boolean supports(Class clazz) { return true; } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/CredentialsExpiredException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/CredentialsExpi0000644000000000000000000000330111623517156030564 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Thrown if an authentication request is rejected because the account's credentials have expired. Makes no * assertion as to whether or not the credentials were valid. * * @author Ben Alex * @version $Id$ */ public class CredentialsExpiredException extends AccountStatusException { //~ Constructors =================================================================================================== /** * Constructs a CredentialsExpiredException with the specified * message. * * @param msg the detail message */ public CredentialsExpiredException(String msg) { super(msg); } /** * Constructs a CredentialsExpiredException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public CredentialsExpiredException(String msg, Throwable t) { super(msg, t); } public CredentialsExpiredException(String msg, Object extraInformation) { super(msg, extraInformation); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/SpringSecurityException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/SpringSecurityE0000644000000000000000000000331311623517156030603 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; import org.springframework.core.NestedRuntimeException; /** * Abstract superclass for all exceptions thrown in the security package and subpackages.

    Note that this is a * runtime (unchecked) exception. Security exceptions are usually fatal; there is no reason for them to be checked.

    * * @author Ben Alex * @version $Id$ */ public abstract class SpringSecurityException extends NestedRuntimeException { //~ Constructors =================================================================================================== /** * Constructs an SpringSecurityException with the specified * message and root cause. * * @param msg the detail message * @param t the root cause */ public SpringSecurityException(String msg, Throwable t) { super(msg, t); } /** * Constructs an SpringSecurityException with the specified * message and no root cause. * * @param msg the detail message */ public SpringSecurityException(String msg) { super(msg); } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/InsufficientAuthenticationException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/InsufficientAut0000644000000000000000000000401611623517156030605 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Thrown if an authentication request is rejected because the credentials are not sufficiently trusted.

    {{@link * org.springframework.security.vote.AccessDecisionVoter}s will typically throw this exception if they are dissatisfied with the * level of the authentication, such as if performed using a remember-me mechanism or anonymously. The commonly used * {@link org.springframework.security.ui.ExceptionTranslationFilter} will thus cause the AuthenticationEntryPoint * to be called, allowing the principal to authenticate with a stronger level of authentication.}

    * * @author Ben Alex * @version $Id$ */ public class InsufficientAuthenticationException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs an InsufficientAuthenticationException with the * specified message. * * @param msg the detail message */ public InsufficientAuthenticationException(String msg) { super(msg); } /** * Constructs an InsufficientAuthenticationException with the * specified message and root cause. * * @param msg the detail message * @param t root cause */ public InsufficientAuthenticationException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthenticationTrustResolverImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthenticationT0000644000000000000000000000503511623517156030612 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; import org.springframework.security.providers.rememberme.RememberMeAuthenticationToken; /** * Basic implementation of {@link AuthenticationTrustResolver}.

    Makes trust decisions based on whether the passed * Authentication is an instance of a defined class.

    *

    If {@link #anonymousClass} or {@link #rememberMeClass} is null, the corresponding method will * always return false.

    * * @author Ben Alex * @version $Id$ */ public class AuthenticationTrustResolverImpl implements AuthenticationTrustResolver { //~ Instance fields ================================================================================================ private Class anonymousClass = AnonymousAuthenticationToken.class; private Class rememberMeClass = RememberMeAuthenticationToken.class; //~ Methods ======================================================================================================== public Class getAnonymousClass() { return anonymousClass; } public Class getRememberMeClass() { return rememberMeClass; } public boolean isAnonymous(Authentication authentication) { if ((anonymousClass == null) || (authentication == null)) { return false; } return anonymousClass.isAssignableFrom(authentication.getClass()); } public boolean isRememberMe(Authentication authentication) { if ((rememberMeClass == null) || (authentication == null)) { return false; } return rememberMeClass.isAssignableFrom(authentication.getClass()); } public void setAnonymousClass(Class anonymousClass) { this.anonymousClass = anonymousClass; } public void setRememberMeClass(Class rememberMeClass) { this.rememberMeClass = rememberMeClass; } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/0000755000000000000000000000000011623517156027364 5ustar ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/AbstractAdapterAuthenticationToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/Abstra0000644000000000000000000000667011623517156030534 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.adapters; import org.springframework.security.GrantedAuthority; import org.springframework.security.providers.AbstractAuthenticationToken; /** * Convenience superclass for {@link AuthByAdapter} implementations. * * @author Ben Alex * @version $Id$ */ public abstract class AbstractAdapterAuthenticationToken extends AbstractAuthenticationToken implements AuthByAdapter { //~ Instance fields ================================================================================================ private int keyHash; //~ Constructors =================================================================================================== protected AbstractAdapterAuthenticationToken() { super(null); } /** * The only way an AbstractAdapterAuthentication should be * constructed. * * @param key the key that is hashed and made available via {@link * #getKeyHash()} * @param authorities the authorities granted to this principal */ protected AbstractAdapterAuthenticationToken(String key, GrantedAuthority[] authorities) { super(authorities); this.keyHash = key.hashCode(); } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (obj instanceof AbstractAdapterAuthenticationToken) { if (!super.equals(obj)) { return false; } AbstractAdapterAuthenticationToken test = (AbstractAdapterAuthenticationToken) obj; return (this.getKeyHash() == test.getKeyHash()); } return false; } public int getKeyHash() { return this.keyHash; } /** * Always returns true. * * @return DOCUMENT ME! */ public boolean isAuthenticated() { return true; } /** * Iterates the granted authorities and indicates whether or not the specified role is held.

    Comparison * is based on the String returned by {@link GrantedAuthority#getAuthority}.

    * * @param role the role being searched for in this object's granted authorities list * * @return true if the granted authority is held, or false otherwise */ public boolean isUserInRole(String role) { GrantedAuthority[] authorities = super.getAuthorities(); for (int i = 0; i < authorities.length; i++) { if (role.equals(authorities[i].getAuthority())) { return true; } } return false; } /** * Setting is ignored. Always considered authenticated. * * @param ignored DOCUMENT ME! */ public void setAuthenticated(boolean ignored) { // ignored } } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/PrincipalSpringSecurityUserToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/Princi0000644000000000000000000000410211623517156030530 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.adapters; import org.springframework.security.GrantedAuthority; import java.security.Principal; /** * A {@link Principal} compatible {@link org.springframework.security.Authentication} object. * * @author Ben Alex * @version $Id$ */ public class PrincipalSpringSecurityUserToken extends AbstractAdapterAuthenticationToken implements Principal { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Object principal; private String password; private String username; //~ Constructors =================================================================================================== public PrincipalSpringSecurityUserToken(String key, String username, String password, GrantedAuthority[] authorities, Object principal) { super(key, authorities); this.username = username; this.password = password; this.principal = principal; } //~ Methods ======================================================================================================== public Object getCredentials() { return this.password; } public String getName() { return this.username; } public Object getPrincipal() { if (this.principal == null) { return this.username; } return this.principal; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/HttpRequestIntegrationFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/HttpRe0000644000000000000000000000676611623517156030534 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.adapters; import org.springframework.security.Authentication; import org.springframework.security.context.SecurityContextHolder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.IOException; import java.security.Principal; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; /** * Populates SecurityContext with the Authentication obtained from the container's * HttpServletRequest.getUserPrincipal().

    Use this filter with container adapters only.

    *

    This filter never preserves the Authentication on the SecurityContext - it * is replaced every request.

    *

    See {@link org.springframework.security.context.HttpSessionContextIntegrationFilter} for further information.

    * * @author Ben Alex * @version $Id$ */ public class HttpRequestIntegrationFilter implements Filter { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(HttpRequestIntegrationFilter.class); //~ Methods ======================================================================================================== /** * Does nothing. We use IoC container lifecycle services instead. */ public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (request instanceof HttpServletRequest) { Principal principal = ((HttpServletRequest) request).getUserPrincipal(); if ((principal != null) && principal instanceof Authentication) { SecurityContextHolder.getContext().setAuthentication((Authentication) principal); if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder updated with Authentication from container: '" + principal + "'"); } } else { if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder not set with new Authentication as Principal was: '" + principal + "'"); } } } else { throw new IllegalArgumentException("Only HttpServletRequest is acceptable"); } chain.doFilter(request, response); } /** * Does nothing. We use IoC container lifecycle services instead. * * @param arg0 ignored * * @throws ServletException ignored */ public void init(FilterConfig arg0) throws ServletException {} } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/adaptertest-invalid.xmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/adapte0000644000000000000000000000236211623517156030550 0ustar rod=koala,ROLE_TELLER,ROLE_SUPERVISOR dianne=emu,ROLE_TELLER scott=wombat,ROLE_TELLER peter=opal,disabled,ROLE_TELLER ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/packag0000644000000000000000000000043711623517156030541 0ustar Allows external containers to obtain authentication information from the system.

    It is recommended to use the org.springframework.security.ui.webapp package for standard web applications, as it has much lower configuration complexity.

    ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/acegisecurity.xmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/acegis0000644000000000000000000000346111623517156030546 0ustar rod=koala,ROLE_TELLER,ROLE_SUPERVISOR dianne=emu,ROLE_TELLER scott=wombat,ROLE_TELLER peter=opal,disabled,ROLE_TELLER true ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/adaptertest-valid.xmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/adapte0000644000000000000000000000346111623517156030551 0ustar rod=koala,ROLE_TELLER,ROLE_SUPERVISOR dianne=emu,ROLE_TELLER scott=wombat,ROLE_TELLER peter=opal,disabled,ROLE_TELLER true ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/AuthByAdapterProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/AuthBy0000644000000000000000000000647711623517156030521 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.adapters; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.BadCredentialsException; import org.springframework.security.providers.AuthenticationProvider; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that can authenticate an {@link AuthByAdapter}.

    Configured in * the bean context with a key that should match the key used by adapters to generate AuthByAdapter * instances. It treats as valid any such instance presenting a hash code that matches the * AuthByAdapterProvider-configured key.

    *

    If the key does not match, a BadCredentialsException is thrown.

    */ public class AuthByAdapterProvider implements InitializingBean, AuthenticationProvider, MessageSourceAware { //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private String key; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(key, "A Key is required and should match that configured for the adapters"); Assert.notNull(messages, "A message source must be set"); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { AuthByAdapter token = (AuthByAdapter) authentication; if (token.getKeyHash() == key.hashCode()) { return authentication; } else { throw new BadCredentialsException(messages.getMessage("AuthByAdapterProvider.incorrectKey", "The presented AuthByAdapter implementation does not contain the expected key")); } } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public boolean supports(Class authentication) { if (AuthByAdapter.class.isAssignableFrom(authentication)) { return true; } else { return false; } } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/AuthByAdapter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/adapters/AuthBy0000644000000000000000000000315011623517156030502 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.adapters; import org.springframework.security.Authentication; /** * Indicates a specialized, immutable, server-side only {@link Authentication} * class. * *

    * Automatically considered valid by the {@link AuthByAdapterProvider}, * provided the hash code presented by the implementation objects matches that * expected by the AuthByAdapterProvider. *

    * * @author Ben Alex * @version $Id$ */ public interface AuthByAdapter extends Authentication { //~ Methods ======================================================================================================== /** * Returns the hash code of the key that was passed to the constructor of the AuthByAdapter * implementation. The implementation should convert the value to a hash code at construction time, rather than * storing the key itself. * * @return the hash code of the key used when the object was created. */ int getKeyHash(); } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AccountExpiredException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AccountExpiredE0000644000000000000000000000323211623517156030526 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Thrown if an authentication request is rejected because the account has expired. Makes no assertion as to * whether or not the credentials were valid. * * @author Ben Alex * @version $Id$ */ public class AccountExpiredException extends AccountStatusException { //~ Constructors =================================================================================================== /** * Constructs a AccountExpiredException with the specified * message. * * @param msg the detail message */ public AccountExpiredException(String msg) { super(msg); } /** * Constructs a AccountExpiredException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public AccountExpiredException(String msg, Throwable t) { super(msg, t); } public AccountExpiredException(String msg, Object extraInformation) { super(msg, extraInformation); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_it.propertiesspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_it.pro0000644000000000000000000000771011623517156030613 0ustar AbstractAccessDecisionManager.accessDenied=Accesso negato AbstractSecurityInterceptor.authenticationNotFound=Nessuna autenticazione trovata dentro il Security Context AbstractUserDetailsAuthenticationProvider.badCredentials=Credenziali non valide AbstractUserDetailsAuthenticationProvider.credentialsExpired=Credenziali dell'utente scadute AbstractUserDetailsAuthenticationProvider.disabled=Utente disabilitato AbstractUserDetailsAuthenticationProvider.expired=Account dell'utente scadute AbstractUserDetailsAuthenticationProvider.locked=Account dell'utente bloccato AbstractUserDetailsAuthenticationProvider.onlySupports=Solo UsernamePasswordAuthenticationToken è supportata AnonymousAuthenticationProvider.incorrectKey=AnonymousAuthenticationToken non contiene la chiave prevista AuthByAdapterProvider.incorrectKey=AuthByAdapter non contiene la chiave prevista BasicAclEntryAfterInvocationProvider.noPermission=L'autenticazione {0} non ha nessun permesso sull'oggetto di dominio {1} BasicAclEntryAfterInvocationProvider.insufficientPermission=L'autenticazione {0} ha permessi ACL sull'oggetto di dominio, ma non il permesso ACL richiesto dall'oggetto {1} BindAuthenticator.badCredentials=Credenziali non valide BindAuthenticator.failedToLoadAttributes=Credenziali non valide CasAuthenticationProvider.incorrectKey=CasAuthenticationToken non contiene la chiave prevista CasAuthenticationProvider.noServiceTicket=Non e' stato fornito un CAS service ticket valido ConcurrentSessionControllerImpl.exceededAllowed=Il numero massimo delle sessioni ({0}) per questo utente sono state superate DaoX509AuthoritiesPopulator.noMatching=Non e' stato validato correttamente il subjectDN: {0} DefaultIntitalDirContextFactory.communicationFailure=Impossibile connettersi al server LDAP DefaultIntitalDirContextFactory.badCredentials=Credenziali non valide DefaultIntitalDirContextFactory.unexpectedException=Impossibile creare l'InitialDirContext a causa di un errore imprevisto DigestProcessingFilter.missingMandatory=Valore digest obbligatorio mancante; ricevuto header {0} DigestProcessingFilter.missingAuth=Valore digest obbligatorio mancante per 'auth' QOP; ricevuto header {0} DigestProcessingFilter.incorrectRealm=Il response realm name {0} non corrisponde al realm name di sistema {1} DigestProcessingFilter.nonceExpired=Nonce scaduto/in timeout DigestProcessingFilter.nonceEncoding=Nonce non codificato in Base64; ricevuto nonce {0} DigestProcessingFilter.nonceNotTwoTokens=Nonce avrebbe dovuto dare due token invece di {0} DigestProcessingFilter.nonceNotNumeric=Nonce token avrebbe dovuto dare un primo token numerico invece di {0} DigestProcessingFilter.nonceCompromised=Nonce token corrotto {0} DigestProcessingFilter.usernameNotFound=Username {0} non trovato DigestProcessingFilter.incorrectResponse=Replica non corretta LdapAuthenticationProvider.emptyUsername=Username vuoto non consentito LdapAuthenticationProvider.emptyPassword=Credenziali non valide NamedCasProxyDecider.untrusted=Il Proxy piu' vicino {0} non e' trusted PasswordComparisonAuthenticator.badCredentials=Credenziali non valide ProviderManager.providerNotFound=Nessun Provider di autenticazione trovato per {0} RejectProxyTickets.reject=Proxy tickets rifiutati RememberMeAuthenticationProvider.incorrectKey=RememberMeAuthenticationToken non contiene la chiave prevista RunAsImplAuthenticationProvider.incorrectKey=RunAsUserToken non contiene la chiave prevista SwitchUserProcessingFilter.noCurrentUser=Nessun utente corrente associato con questa richiesta SwitchUserProcessingFilter.noOriginalAuthentication=Impossibile trovare l'Authentication object originale SwitchUserProcessingFilter.usernameNotFound=Username {0} non trovato SwitchUserProcessingFilter.locked=Account dell'utente bloccato SwitchUserProcessingFilter.disabled=Account dell'utente disabilitato SwitchUserProcessingFilter.expired=Account dell'utente scaduto SwitchUserProcessingFilter.credentialsExpired=Credenziali dell'utente scadute X509AuthenticationProvider.certificateNull=Il certificato e' nullo ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/MockAuthenticationManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/MockAuthenticat0000644000000000000000000000342611623517156030574 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Simply accepts as valid whatever is passed to it, if grantAccess is set to true. * * @author Ben Alex * @author Wesley Hall * @version $Id$ */ public class MockAuthenticationManager extends AbstractAuthenticationManager { //~ Instance fields ================================================================================================ private boolean grantAccess = true; //~ Constructors =================================================================================================== public MockAuthenticationManager(boolean grantAccess) { this.grantAccess = grantAccess; } public MockAuthenticationManager() { super(); } //~ Methods ======================================================================================================== public Authentication doAuthentication(Authentication authentication) throws AuthenticationException { if (grantAccess) { return authentication; } else { throw new BadCredentialsException("MockAuthenticationManager instructed to deny access"); } } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_fr.propertiesspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_fr.pro0000644000000000000000000000767411623517156030617 0ustar # Spring security # Messages in French # Translation by Laurent Pireyn (laurent.pireyn@pisolutions.eu) AuthByAdapterProvider.incorrectKey = L'implémentation de AuthByAdapter présentée ne contient pas la clé attendue BasicAclEntryAfterInvocationProvider.noPermission = L'authentification {0} n'a AUCUNE permission pour l'objet domaine {1} BasicAclEntryAfterInvocationProvider.insufficientPermission = L'authentification {0} a des permissions ACL pour l'objet domaine, mais pas la permission ACL requise pour l'objet domaine {1} ConcurrentSessionControllerImpl.exceededAllowed = Le maximum de {0} sessions a été dépassé pour cet utilisateur ProviderManager.providerNotFound = Aucun AuthenticationProvider n'a été trouvé pour {0} AnonymousAuthenticationProvider.incorrectKey = L'AnonymousAuthenticationToken présenté ne contient pas la clé attendue CasAuthenticationProvider.incorrectKey = Le CasAuthenticationToken présenté ne contient pas la clé attendue CasAuthenticationProvider.noServiceTicket = Echec d'obtention d'un ticket CAS à valider NamedCasProxyDecider.untrusted = Le proxy {0} le plus proche n'est pas fiable RejectProxyTickets.reject = Des tickets proxy ont été rejetés AbstractSecurityInterceptor.authenticationNotFound = Aucun objet Authentication n'a été trouvé dans le SecurityContext AbstractUserDetailsAuthenticationProvider.onlySupports = Seul UsernamePasswordAuthenticationToken est pris en charge AbstractUserDetailsAuthenticationProvider.locked = Le compte utilisateur est bloqué AbstractUserDetailsAuthenticationProvider.disabled = Le compte utilisateur est désactivé AbstractUserDetailsAuthenticationProvider.expired = Le compte utilisateur a expiré AbstractUserDetailsAuthenticationProvider.credentialsExpired = Les créances de l'utilisateur ont expiré AbstractUserDetailsAuthenticationProvider.badCredentials = Les créances sont erronées X509AuthenticationProvider.certificateNull = Le certificat est null DaoX509AuthoritiesPopulator.noMatching = Aucun motif concordant n'a été trouvé dans le subjectDN: {0} RememberMeAuthenticationProvider.incorrectKey = Le RememberMeAuthenticationToken présenté ne contient pas la clé attendue RunAsImplAuthenticationProvider.incorrectKey = Le RunAsUserToken présenté ne contient pas la clé attendue DigestProcessingFilter.missingMandatory = Une valeur obligatoire manque au condensé; reçu l'entête {0} DigestProcessingFilter.missingAuth = Une valeur obligatoire manque au condensé pour 'auth' QOP; reçu l'entête {0} DigestProcessingFilter.incorrectRealm = Le nom de domaine de la réponse {0} ne correspond pas au nom de domaine du système {1} DigestProcessingFilter.nonceExpired = Le nonce a expiré DigestProcessingFilter.nonceEncoding = Le nonce n'est pas encodé en Base64; reçu le nonce {0} DigestProcessingFilter.nonceNotTwoTokens = Le nonce aurait dû générer deux jetons, mais était {0} DigestProcessingFilter.nonceNotNumeric = Le jeton nonce aurait dû générer d'abord un jeton numérique, mais était {0} DigestProcessingFilter.nonceCompromised = Le jeton nonce est compromis {0} DigestProcessingFilter.usernameNotFound = Le nom d'utilisateur {0} n'a pas été trouvé DigestProcessingFilter.incorrectResponse = Réponse incorrecte JdbcDaoImpl.notFound=Le nom d'utilisateur {0} n'a pas été trouvé JdbcDaoImpl.noAuthority=Le compte utilisateur {0} n'a pas de permissions SwitchUserProcessingFilter.noCurrentUser = Aucun utilisateur n'est associé à la requête en cours SwitchUserProcessingFilter.noOriginalAuthentication = L'objet Authentication original n'a pas été trouvé SwitchUserProcessingFilter.usernameNotFound = Le nom d'utilisateur {0} n'a pas été trouvé SwitchUserProcessingFilter.locked = Le compte utilisateur est bloqué SwitchUserProcessingFilter.disabled = Le compte utilisateur est désactivé SwitchUserProcessingFilter.expired = Le compte utilisateur a expiré SwitchUserProcessingFilter.credentialsExpired = Les créances de l'utilisateur ont expiré AbstractAccessDecisionManager.accessDenied = Accès refusé ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/LockedException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/LockedException0000644000000000000000000000314311623517156030565 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Thrown if an authentication request is rejected because the account is locked. Makes no assertion as to whether * or not the credentials were valid. * * @author Ben Alex * @version $Id$ */ public class LockedException extends AccountStatusException { //~ Constructors =================================================================================================== /** * Constructs a LockedException with the specified message. * * @param msg the detail message. */ public LockedException(String msg) { super(msg); } /** * Constructs a LockedException with the specified message and * root cause. * * @param msg the detail message. * @param t root cause */ public LockedException(String msg, Throwable t) { super(msg, t); } public LockedException(String msg, Object extraInformation) { super(msg, extraInformation); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/0000755000000000000000000000000011623517156030105 5ustar ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/UserDetailsChecker.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/Use0000644000000000000000000000027611623517156030571 0ustar package org.springframework.security.userdetails; /** * @author Luke Taylor * @version $Id$ * @since 2.0 */ public interface UserDetailsChecker { void check(UserDetails toCheck); } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/UserDetails.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/Use0000644000000000000000000000713711623517156030574 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; import java.io.Serializable; /** * Provides core user information. * *

    * Implementations are not used directly by Spring Security for security * purposes. They simply store user information which is later encapsulated * into {@link Authentication} objects. This allows non-security related user * information (such as email addresses, telephone numbers etc) to be stored * in a convenient location. *

    * *

    * Concrete implementations must take particular care to ensure the non-null * contract detailed for each method is enforced. See * {@link org.springframework.security.userdetails.User} for a * reference implementation (which you might like to extend). *

    * *

    * Concrete implementations should be immutable (value object semantics, * like a String). This is because the UserDetails will be * stored in caches and as such multiple threads may use the same instance. *

    * * @author Ben Alex * @version $Id$ */ public interface UserDetails extends Serializable { //~ Methods ======================================================================================================== /** * Returns the authorities granted to the user. Cannot return null. * * @return the authorities, sorted by natural key (never null) */ GrantedAuthority[] getAuthorities(); /** * Returns the password used to authenticate the user. Cannot return null. * * @return the password (never null) */ String getPassword(); /** * Returns the username used to authenticate the user. Cannot return null. * * @return the username (never null) */ String getUsername(); /** * Indicates whether the user's account has expired. An expired account cannot be authenticated. * * @return true if the user's account is valid (ie non-expired), false if no longer valid * (ie expired) */ boolean isAccountNonExpired(); /** * Indicates whether the user is locked or unlocked. A locked user cannot be authenticated. * * @return true if the user is not locked, false otherwise */ boolean isAccountNonLocked(); /** * Indicates whether the user's credentials (password) has expired. Expired credentials prevent * authentication. * * @return true if the user's credentials are valid (ie non-expired), false if no longer * valid (ie expired) */ boolean isCredentialsNonExpired(); /** * Indicates whether the user is enabled or disabled. A disabled user cannot be authenticated. * * @return true if the user is enabled, false otherwise */ boolean isEnabled(); } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/UserDetailsService.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/Use0000644000000000000000000000416011623517156030565 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails; import org.springframework.security.providers.dao.DaoAuthenticationProvider; import org.springframework.dao.DataAccessException; /** * Defines an interface for implementations that wish to provide data access * services to the {@link DaoAuthenticationProvider}. * *

    * The interface requires only one read-only method, which simplifies support * of new data access strategies. *

    * * @author Ben Alex * @version $Id$ */ public interface UserDetailsService { //~ Methods ======================================================================================================== /** * Locates the user based on the username. In the actual implementation, the search may possibly be case * insensitive, or case insensitive depending on how the implementaion instance is configured. In this case, the * UserDetails object that comes back may have a username that is of a different case than what was * actually requested.. * * @param username the username presented to the {@link DaoAuthenticationProvider} * * @return a fully populated user record (never null) * * @throws UsernameNotFoundException if the user could not be found or the user has no GrantedAuthority * @throws DataAccessException if user could not be found for a repository-specific reason */ UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException; } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/UserDetailsByNameServiceWrapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/Use0000644000000000000000000000311611623517156030565 0ustar package org.springframework.security.userdetails; import org.springframework.security.Authentication; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataAccessException; import org.springframework.util.Assert; /** * This implementation for AuthenticationUserDetailsService wraps a regular * Spring Security UserDetailsService implementation, to retrieve a UserDetails object * based on the user name contained in a PreAuthenticatedAuthenticationToken. * * @author Ruud Senden * @since 2.0 */ public class UserDetailsByNameServiceWrapper implements AuthenticationUserDetailsService, InitializingBean { private UserDetailsService userDetailsService = null; /** * Check whether all required properties have been set. * * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ public void afterPropertiesSet() throws Exception { Assert.notNull(userDetailsService, "UserDetailsService must be set"); } /** * Get the UserDetails object from the wrapped UserDetailsService * implementation */ public UserDetails loadUserDetails(Authentication authentication) throws UsernameNotFoundException, DataAccessException { return userDetailsService.loadUserByUsername(authentication.getName()); } /** * Set the wrapped UserDetailsService implementation * * @param aUserDetailsService * The wrapped UserDetailsService to set */ public void setUserDetailsService(UserDetailsService aUserDetailsService) { userDetailsService = aUserDetailsService; } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/GroupManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/Gro0000644000000000000000000000503711623517156030564 0ustar package org.springframework.security.userdetails; import org.springframework.security.GrantedAuthority; /** * Allows management of groups of authorities and their members. *

    * Typically this will be used to supplement the functionality of a {@link UserDetailsManager} * in situations where the organization of application granted authorities into groups is preferred over * a straight mapping of users to roles. *

    * With this scenario, users are allocated to groups and take on the list of authorities which * are assigned to the group, providing more flexible administration options. * * @author Luke Taylor * @version $Id$ */ public interface GroupManager { /** * Returns the names of all groups that this group manager controls. */ String[] findAllGroups(); /** * Locates the users who are members of a group * * @param groupName the group whose members are required * @return the usernames of the group members */ String[] findUsersInGroup(String groupName); /** * Creates a new group with the specified list of authorities. * * @param groupName the name for the new group * @param authorities the authorities which are to be allocated to this group. */ void createGroup(String groupName, GrantedAuthority[] authorities); /** * Removes a group, including all members and authorities. * * @param groupName the group to remove. */ void deleteGroup(String groupName); /** * Changes the name of a group without altering the assigned authorities or members. */ void renameGroup(String oldName, String newName); /** * Makes a user a member of a particular group. * * @param username the user to be given membership. * @param group the name of the group to which the user will be added. */ void addUserToGroup(String username, String group); /** * Deletes a user's membership of a group. * * @param username the user * @param groupName the group to remove them from */ void removeUserFromGroup(String username, String groupName); /** * Obtains the list of authorities which are assigned to a group. */ GrantedAuthority[] findGroupAuthorities(String groupName); /** * Assigns a new authority to a group. */ void addGroupAuthority(String groupName, GrantedAuthority authority); /** * Deletes an authority from those assigned to a group */ void removeGroupAuthority(String groupName, GrantedAuthority authority); } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/jdbc/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/jdb0000755000000000000000000000000011623517156030565 5ustar ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/jdbc/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/jdb0000644000000000000000000000011611623517156030565 0ustar Exposes a JDBC-based authentication repository. ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/jdbc/JdbcDaoImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/jdb0000644000000000000000000004067511623517156030603 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.jdbc; import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthorityImpl; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.userdetails.User; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.context.ApplicationContextException; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.jdbc.object.MappingSqlQuery; import org.springframework.util.Assert; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.List; import java.util.ArrayList; import java.util.Set; import java.util.HashSet; import javax.sql.DataSource; /** * UserDetailsServiceRetrieves implementation which retrieves the user details * (username, password, enabled flag, and authorities) from a database using JDBC queries. * *

    Default Schema

    * A default database schema is assumed, with two tables "users" and "authorities". * *

    The Users table

    * * This table contains the login name, password and enabled status of the user. * * * * * * *
    Column
    username
    password
    enabled
    * *

    The Authorities Table

    * * * * * *
    Column
    username
    authority
    * * If you are using an existing schema you will have to set the queries usersByUsernameQuery and * authoritiesByUsernameQuery to match your database setup * (see {@link #DEF_USERS_BY_USERNAME_QUERY} and {@link #DEF_AUTHORITIES_BY_USERNAME_QUERY}). * *

    * In order to minimise backward compatibility issues, this implementation doesn't recognise the expiration of user * accounts or the expiration of user credentials. However, it does recognise and honour the user enabled/disabled * column. This should map to a boolean type in the result set (the SQL type will depend on the * database you are using). All the other columns map to Strings. * *

    Group Support

    * Support for group-based authorities can be enabled by setting the enableGroups property to true * (you may also then wish to set enableAuthorities to false to disable loading of authorities * directly). With this approach, authorities are allocated to groups and a user's authorities are determined based * on the groups they are a member of. The net result is the same (a UserDetails containing a set of * GrantedAuthoritys is loaded), but the different persistence strategy may be more suitable for the * administration of some applications. *

    * When groups are being used, the tables "groups", "group_members" and "group_authorities" are used. See * {@link #DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY} for the default query which is used to load the group authorities. * Again you can customize this by setting the groupAuthoritiesByUsernameQuery property, but the format of * the rows returned should match the default. * * @author Ben Alex * @author colin sampaleanu * @author Luke Taylor * @version $Id$ */ public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService { //~ Static fields/initializers ===================================================================================== public static final String DEF_USERS_BY_USERNAME_QUERY = "SELECT username,password,enabled " + "FROM users " + "WHERE username = ?"; public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY = "SELECT username,authority " + "FROM authorities " + "WHERE username = ?"; public static final String DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY = "SELECT g.id, g.group_name, ga.authority " + "FROM groups g, group_members gm, group_authorities ga " + "WHERE gm.username = ? " + "AND g.id = ga.group_id " + "AND g.id = gm.group_id"; //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private MappingSqlQuery authoritiesByUsernameMapping; private MappingSqlQuery groupAuthoritiesByUsernameMapping; private MappingSqlQuery usersByUsernameMapping; private String authoritiesByUsernameQuery; private String groupAuthoritiesByUsernameQuery; private String usersByUsernameQuery; private String rolePrefix = ""; private boolean usernameBasedPrimaryKey = true; private boolean enableAuthorities = true; private boolean enableGroups; //~ Constructors =================================================================================================== public JdbcDaoImpl() { usersByUsernameQuery = DEF_USERS_BY_USERNAME_QUERY; authoritiesByUsernameQuery = DEF_AUTHORITIES_BY_USERNAME_QUERY; groupAuthoritiesByUsernameQuery = DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY; } //~ Methods ======================================================================================================== /** * Allows subclasses to add their own granted authorities to the list to be returned in the * User. * * @param username the username, for use by finder methods * @param authorities the current granted authorities, as populated from the authoritiesByUsername * mapping */ protected void addCustomAuthorities(String username, List authorities) {} public String getUsersByUsernameQuery() { return usersByUsernameQuery; } protected void initDao() throws ApplicationContextException { Assert.isTrue(enableAuthorities || enableGroups, "Use of either authorities or groups must be enabled"); initMappingSqlQueries(); } /** * Extension point to allow other MappingSqlQuery objects to be substituted in a subclass */ private void initMappingSqlQueries() { this.usersByUsernameMapping = new UsersByUsernameMapping(getDataSource()); this.authoritiesByUsernameMapping = new AuthoritiesByUsernameMapping(getDataSource()); this.groupAuthoritiesByUsernameMapping = new GroupAuthoritiesByUsernameMapping(getDataSource()); } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { List users = loadUsersByUsername(username); if (users.size() == 0) { throw new UsernameNotFoundException( messages.getMessage("JdbcDaoImpl.notFound", new Object[]{username}, "Username {0} not found"), username); } UserDetails user = (UserDetails) users.get(0); // contains no GrantedAuthority[] Set dbAuthsSet = new HashSet(); if (enableAuthorities) { dbAuthsSet.addAll(loadUserAuthorities(user.getUsername())); } if (enableGroups) { dbAuthsSet.addAll(loadGroupAuthorities(user.getUsername())); } List dbAuths = new ArrayList(dbAuthsSet); addCustomAuthorities(user.getUsername(), dbAuths); if (dbAuths.size() == 0) { throw new UsernameNotFoundException( messages.getMessage("JdbcDaoImpl.noAuthority", new Object[] {username}, "User {0} has no GrantedAuthority"), username); } GrantedAuthority[] arrayAuths = (GrantedAuthority[]) dbAuths.toArray(new GrantedAuthority[dbAuths.size()]); return createUserDetails(username, user, arrayAuths); } /** * Executes the usersByUsernameQuery and returns a list of UserDetails objects (there should normally * only be one matching user). */ protected List loadUsersByUsername(String username) { return usersByUsernameMapping.execute(username); } /** * Loads authorities by executing the authoritiesByUsernameQuery. * * @return a list of GrantedAuthority objects for the user */ protected List loadUserAuthorities(String username) { return authoritiesByUsernameMapping.execute(username); } protected List loadGroupAuthorities(String username) { return groupAuthoritiesByUsernameMapping.execute(username); } /** * Can be overridden to customize the creation of the final UserDetailsObject returnd from loadUserByUsername. * * @param username the name originally passed to loadUserByUsername * @param userFromUserQuery the object returned from the execution of the * @param combinedAuthorities the combined array of authorities from all the authority loading queries. * @return the final UserDetails which should be used in the system. */ protected UserDetails createUserDetails(String username, UserDetails userFromUserQuery, GrantedAuthority[] combinedAuthorities) { String returnUsername = userFromUserQuery.getUsername(); if (!usernameBasedPrimaryKey) { returnUsername = username; } return new User(returnUsername, userFromUserQuery.getPassword(), userFromUserQuery.isEnabled(), true, true, true, combinedAuthorities); } /** * Allows the default query string used to retrieve authorities based on username to be overriden, if * default table or column names need to be changed. The default query is {@link * #DEF_AUTHORITIES_BY_USERNAME_QUERY}; when modifying this query, ensure that all returned columns are mapped * back to the same column names as in the default query. * * @param queryString The query string to set */ public void setAuthoritiesByUsernameQuery(String queryString) { authoritiesByUsernameQuery = queryString; } protected String getAuthoritiesByUsernameQuery() { return authoritiesByUsernameQuery; } /** * Allows the default query string used to retrieve group authorities based on username to be overriden, if * default table or column names need to be changed. The default query is {@link * #DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY}; when modifying this query, ensure that all returned columns are mapped * back to the same column names as in the default query. * * @param queryString The query string to set */ public void setGroupAuthoritiesByUsernameQuery(String queryString) { groupAuthoritiesByUsernameQuery = queryString; } /** * Allows a default role prefix to be specified. If this is set to a non-empty value, then it is * automatically prepended to any roles read in from the db. This may for example be used to add the * ROLE_ prefix expected to exist in role names (by default) by some other Spring Security * classes, in the case that the prefix is not already present in the db. * * @param rolePrefix the new prefix */ public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } protected String getRolePrefix() { return rolePrefix; } /** * If true (the default), indicates the {@link #getUsersByUsernameQuery()} returns a username * in response to a query. If false, indicates that a primary key is used instead. If set to * true, the class will use the database-derived username in the returned UserDetails. * If false, the class will use the {@link #loadUserByUsername(String)} derived username in the * returned UserDetails. * * @param usernameBasedPrimaryKey true if the mapping queries return the username String, * or false if the mapping returns a database primary key. */ public void setUsernameBasedPrimaryKey(boolean usernameBasedPrimaryKey) { this.usernameBasedPrimaryKey = usernameBasedPrimaryKey; } protected boolean isUsernameBasedPrimaryKey() { return usernameBasedPrimaryKey; } /** * Allows the default query string used to retrieve users based on username to be overriden, if default * table or column names need to be changed. The default query is {@link #DEF_USERS_BY_USERNAME_QUERY}; when * modifying this query, ensure that all returned columns are mapped back to the same column names as in the * default query. If the 'enabled' column does not exist in the source db, a permanent true value for this column * may be returned by using a query similar to

         * "SELECT username,password,'true' as enabled FROM users WHERE username = ?"
    * * @param usersByUsernameQueryString The query string to set */ public void setUsersByUsernameQuery(String usersByUsernameQueryString) { this.usersByUsernameQuery = usersByUsernameQueryString; } protected boolean getEnableAuthorities() { return enableAuthorities; } /** * Enables loading of authorities (roles) from the authorities table. Defaults to true */ public void setEnableAuthorities(boolean enableAuthorities) { this.enableAuthorities = enableAuthorities; } protected boolean getEnableGroups() { return enableGroups; } /** * Enables support for group authorities. Defaults to false * @param enableGroups */ public void setEnableGroups(boolean enableGroups) { this.enableGroups = enableGroups; } //~ Inner Classes ================================================================================================== /** * Query object to look up a user's authorities. */ private class AuthoritiesByUsernameMapping extends MappingSqlQuery { protected AuthoritiesByUsernameMapping(DataSource ds) { super(ds, authoritiesByUsernameQuery); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { String roleName = rolePrefix + rs.getString(2); GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName); return authority; } } private class GroupAuthoritiesByUsernameMapping extends MappingSqlQuery { protected GroupAuthoritiesByUsernameMapping(DataSource ds) { super(ds, groupAuthoritiesByUsernameQuery); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { String roleName = rolePrefix + rs.getString(3); GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName); return authority; } } /** * Query object to look up a user. */ private class UsersByUsernameMapping extends MappingSqlQuery { protected UsersByUsernameMapping(DataSource ds) { super(ds, usersByUsernameQuery); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { String username = rs.getString(1); String password = rs.getString(2); boolean enabled = rs.getBoolean(3); UserDetails user = new User(username, password, enabled, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")}); return user; } } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/jdbc/JdbcUserDetailsManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/jdb0000644000000000000000000004336511623517156030602 0ustar package org.springframework.security.userdetails.jdbc; import org.springframework.security.AccessDeniedException; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationManager; import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthorityImpl; import org.springframework.security.util.AuthorityUtils; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.providers.dao.UserCache; import org.springframework.security.providers.dao.cache.NullUserCache; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsManager; import org.springframework.security.userdetails.GroupManager; import org.springframework.context.ApplicationContextException; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.jdbc.core.PreparedStatementSetter; import org.springframework.jdbc.core.RowMapper; import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; /** * Jdbc user management service. * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsManager, GroupManager { //~ Static fields/initializers ===================================================================================== // UserDetailsManager SQL public static final String DEF_CREATE_USER_SQL = "insert into users (username, password, enabled) values (?,?,?)"; public static final String DEF_DELETE_USER_SQL = "delete from users where username = ?"; public static final String DEF_UPDATE_USER_SQL = "update users set password = ?, enabled = ? where username = ?"; public static final String DEF_INSERT_AUTHORITY_SQL = "insert into authorities (username, authority) values (?,?)"; public static final String DEF_DELETE_USER_AUTHORITIES_SQL = "delete from authorities where username = ?"; public static final String DEF_USER_EXISTS_SQL = "select username from users where username = ?"; public static final String DEF_CHANGE_PASSWORD_SQL = "update users set password = ? where username = ?"; // GroupManager SQL public static final String DEF_FIND_GROUPS_SQL = "select group_name from groups"; public static final String DEF_FIND_USERS_IN_GROUP_SQL = "select username from group_members gm, groups g " + "where gm.group_id = g.id" + " and g.group_name = ?"; public static final String DEF_INSERT_GROUP_SQL = "insert into groups (group_name) values (?)"; public static final String DEF_FIND_GROUP_ID_SQL = "select id from groups where group_name = ?"; public static final String DEF_INSERT_GROUP_AUTHORITY_SQL = "insert into group_authorities (group_id, authority) values (?,?)"; public static final String DEF_DELETE_GROUP_SQL = "delete from groups where id = ?"; public static final String DEF_DELETE_GROUP_AUTHORITIES_SQL = "delete from group_authorities where group_id = ?"; public static final String DEF_DELETE_GROUP_MEMBERS_SQL = "delete from group_members where group_id = ?"; public static final String DEF_RENAME_GROUP_SQL = "update groups set group_name = ? where group_name = ?"; public static final String DEF_INSERT_GROUP_MEMBER_SQL = "insert into group_members (group_id, username) values (?,?)"; public static final String DEF_DELETE_GROUP_MEMBER_SQL = "delete from group_members where group_id = ? and username = ?"; public static final String DEF_GROUP_AUTHORITIES_QUERY_SQL = "select g.id, g.group_name, ga.authority " + "from groups g, group_authorities ga " + "where g.group_name = ? " + "and g.id = ga.group_id "; public static final String DEF_DELETE_GROUP_AUTHORITY_SQL = "delete from group_authorities where group_id = ? and authority = ?"; //~ Instance fields ================================================================================================ protected final Log logger = LogFactory.getLog(getClass()); private String createUserSql = DEF_CREATE_USER_SQL; private String deleteUserSql = DEF_DELETE_USER_SQL; private String updateUserSql = DEF_UPDATE_USER_SQL; private String createAuthoritySql = DEF_INSERT_AUTHORITY_SQL; private String deleteUserAuthoritiesSql = DEF_DELETE_USER_AUTHORITIES_SQL; private String userExistsSql = DEF_USER_EXISTS_SQL; private String changePasswordSql = DEF_CHANGE_PASSWORD_SQL; private String findAllGroupsSql = DEF_FIND_GROUPS_SQL; private String findUsersInGroupSql = DEF_FIND_USERS_IN_GROUP_SQL; private String insertGroupSql = DEF_INSERT_GROUP_SQL; private String findGroupIdSql = DEF_FIND_GROUP_ID_SQL; private String insertGroupAuthoritySql = DEF_INSERT_GROUP_AUTHORITY_SQL; private String deleteGroupSql = DEF_DELETE_GROUP_SQL; private String deleteGroupAuthoritiesSql = DEF_DELETE_GROUP_AUTHORITIES_SQL; private String deleteGroupMembersSql = DEF_DELETE_GROUP_MEMBERS_SQL; private String renameGroupSql = DEF_RENAME_GROUP_SQL; private String insertGroupMemberSql = DEF_INSERT_GROUP_MEMBER_SQL; private String deleteGroupMemberSql = DEF_DELETE_GROUP_MEMBER_SQL; private String groupAuthoritiesSql = DEF_GROUP_AUTHORITIES_QUERY_SQL; private String deleteGroupAuthoritySql = DEF_DELETE_GROUP_AUTHORITY_SQL; private AuthenticationManager authenticationManager; private UserCache userCache = new NullUserCache(); //~ Methods ======================================================================================================== protected void initDao() throws ApplicationContextException { if (authenticationManager == null) { logger.info("No authentication manager set. Reauthentication of users when changing passwords will " + "not be performed."); } super.initDao(); } //~ UserDetailsManager implementation ============================================================================== public void createUser(final UserDetails user) { validateUserDetails(user); getJdbcTemplate().update(createUserSql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { ps.setString(1, user.getUsername()); ps.setString(2, user.getPassword()); ps.setBoolean(3, user.isEnabled()); } }); insertUserAuthorities(user); } public void updateUser(final UserDetails user) { validateUserDetails(user); getJdbcTemplate().update(updateUserSql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { ps.setString(1, user.getPassword()); ps.setBoolean(2, user.isEnabled()); ps.setString(3, user.getUsername()); } }); deleteUserAuthorities(user.getUsername()); insertUserAuthorities(user); userCache.removeUserFromCache(user.getUsername()); } private void insertUserAuthorities(UserDetails user) { for (int i=0; i < user.getAuthorities().length; i++) { getJdbcTemplate().update(createAuthoritySql, new Object[] {user.getUsername(), user.getAuthorities()[i].getAuthority()}); } } public void deleteUser(String username) { deleteUserAuthorities(username); getJdbcTemplate().update(deleteUserSql, new Object[] {username}); userCache.removeUserFromCache(username); } private void deleteUserAuthorities(String username) { getJdbcTemplate().update(deleteUserAuthoritiesSql, new Object[] {username}); } public void changePassword(String oldPassword, String newPassword) throws AuthenticationException { Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); if (currentUser == null) { // This would indicate bad coding somewhere throw new AccessDeniedException("Can't change password as no Authentication object found in context " + "for current user."); } String username = currentUser.getName(); // If an authentication manager has been set, reauthenticate the user with the supplied password. if (authenticationManager != null) { logger.debug("Reauthenticating user '"+ username + "' for password change request."); authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, oldPassword)); } else { logger.debug("No authentication manager set. Password won't be re-checked."); } logger.debug("Changing password for user '"+ username + "'"); getJdbcTemplate().update(changePasswordSql, new String[] {newPassword, username}); SecurityContextHolder.getContext().setAuthentication(createNewAuthentication(currentUser, newPassword)); userCache.removeUserFromCache(username); } protected Authentication createNewAuthentication(Authentication currentAuth, String newPassword) { UserDetails user = loadUserByUsername(currentAuth.getName()); UsernamePasswordAuthenticationToken newAuthentication = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities()); newAuthentication.setDetails(currentAuth.getDetails()); return newAuthentication; } public boolean userExists(String username) { List users = getJdbcTemplate().queryForList(userExistsSql, new Object[] {username}); if (users.size() > 1) { throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'", 1); } return users.size() == 1; } //~ GroupManager implementation ==================================================================================== public String[] findAllGroups() { return (String[]) getJdbcTemplate().queryForList(findAllGroupsSql, String.class).toArray(new String[0]); } public String[] findUsersInGroup(String groupName) { Assert.hasText(groupName); return (String[]) getJdbcTemplate().queryForList(findUsersInGroupSql, new String[] {groupName}, String.class).toArray(new String[0]); } public void createGroup(final String groupName, final GrantedAuthority[] authorities) { Assert.hasText(groupName); Assert.notNull(authorities); logger.debug("Creating new group '" + groupName + "' with authorities " + AuthorityUtils.authorityArrayToSet(authorities)); getJdbcTemplate().update(insertGroupSql, new String[] {groupName}); final int groupId = findGroupId(groupName); for (int i=0; i < authorities.length; i++) { final String authority = authorities[i].getAuthority(); getJdbcTemplate().update(insertGroupAuthoritySql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { ps.setInt(1, groupId); ps.setString(2, authority); } }); } } public void deleteGroup(String groupName) { logger.debug("Deleting group '" + groupName + "'"); Assert.hasText(groupName); final int id = findGroupId(groupName); PreparedStatementSetter groupIdPSS = new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { ps.setInt(1, id); } }; getJdbcTemplate().update(deleteGroupMembersSql, groupIdPSS); getJdbcTemplate().update(deleteGroupAuthoritiesSql, groupIdPSS); getJdbcTemplate().update(deleteGroupSql, groupIdPSS); } public void renameGroup(String oldName, String newName) { logger.debug("Changing group name from '" + oldName + "' to '" + newName + "'"); Assert.hasText(oldName); Assert.hasText(newName); getJdbcTemplate().update(renameGroupSql, new String[] {newName, oldName}); } public void addUserToGroup(final String username, final String groupName) { logger.debug("Adding user '" + username + "' to group '" + groupName + "'"); Assert.hasText(username); Assert.hasText(groupName); final int id = findGroupId(groupName); getJdbcTemplate().update(insertGroupMemberSql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { ps.setInt(1, id); ps.setString(2, username); } }); userCache.removeUserFromCache(username); } public void removeUserFromGroup(final String username, final String groupName) { logger.debug("Removing user '" + username + "' to group '" + groupName + "'"); Assert.hasText(username); Assert.hasText(groupName); final int id = findGroupId(groupName); getJdbcTemplate().update(deleteGroupMemberSql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { ps.setInt(1, id); ps.setString(2, username); } }); userCache.removeUserFromCache(username); } public GrantedAuthority[] findGroupAuthorities(String groupName) { logger.debug("Loading authorities for group '" + groupName + "'"); Assert.hasText(groupName); List authorities = getJdbcTemplate().query(groupAuthoritiesSql, new String[] {groupName}, new RowMapper() { public Object mapRow(ResultSet rs, int rowNum) throws SQLException { String roleName = getRolePrefix() + rs.getString(3); GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName); return authority; } }); return (GrantedAuthority[]) authorities.toArray(new GrantedAuthority[0]); } public void removeGroupAuthority(String groupName, final GrantedAuthority authority) { logger.debug("Removing authority '" + authority + "' from group '" + groupName + "'"); Assert.hasText(groupName); Assert.notNull(authority); final int id = findGroupId(groupName); getJdbcTemplate().update(deleteGroupAuthoritySql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { ps.setInt(1, id); ps.setString(2, authority.getAuthority()); } }); } public void addGroupAuthority(final String groupName, final GrantedAuthority authority) { logger.debug("Adding authority '" + authority + "' to group '" + groupName + "'"); Assert.hasText(groupName); Assert.notNull(authority); final int id = findGroupId(groupName); getJdbcTemplate().update(insertGroupAuthoritySql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { ps.setInt(1, id); ps.setString(2, authority.getAuthority()); } }); } private int findGroupId(String group) { return getJdbcTemplate().queryForInt(findGroupIdSql, new Object[] {group}); } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } public void setCreateUserSql(String createUserSql) { Assert.hasText(createUserSql); this.createUserSql = createUserSql; } public void setDeleteUserSql(String deleteUserSql) { Assert.hasText(deleteUserSql); this.deleteUserSql = deleteUserSql; } public void setUpdateUserSql(String updateUserSql) { Assert.hasText(updateUserSql); this.updateUserSql = updateUserSql; } public void setCreateAuthoritySql(String createAuthoritySql) { Assert.hasText(createAuthoritySql); this.createAuthoritySql = createAuthoritySql; } public void setDeleteUserAuthoritiesSql(String deleteUserAuthoritiesSql) { Assert.hasText(deleteUserAuthoritiesSql); this.deleteUserAuthoritiesSql = deleteUserAuthoritiesSql; } public void setUserExistsSql(String userExistsSql) { Assert.hasText(userExistsSql); this.userExistsSql = userExistsSql; } public void setChangePasswordSql(String changePasswordSql) { Assert.hasText(changePasswordSql); this.changePasswordSql = changePasswordSql; } public void setFindAllGroupsSql(String findAllGroupsSql) { this.findAllGroupsSql = findAllGroupsSql; } /** * Optionally sets the UserCache if one is in use in the application. * This allows the user to be removed from the cache after updates have taken place to avoid stale data. * * @param userCache the cache used by the AuthenticationManager. */ public void setUserCache(UserCache userCache) { Assert.notNull(userCache, "userCache cannot be null"); this.userCache = userCache; } private void validateUserDetails(UserDetails user) { Assert.hasText(user.getUsername(), "Username may not be empty or null"); validateAuthorities(user.getAuthorities()); } private void validateAuthorities(GrantedAuthority[] authorities) { Assert.notNull(authorities, "Authorities list must not be null"); for (int i=0; i < authorities.length; i++) { Assert.notNull(authorities[i], "Authorities list contains a null entry"); Assert.hasText(authorities[i].getAuthority(), "getAuthority() method must return a non-empty string"); } } } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/AuthenticationUserDetailsService.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/Aut0000644000000000000000000000132211623517156030557 0ustar package org.springframework.security.userdetails; import org.springframework.security.Authentication; /** * Interface that allows for retrieving a UserDetails object based on an Authentication object. * * @author Ruud Senden * @version $Id$ * @since 2.0 */ public interface AuthenticationUserDetailsService { /** * * @param token The pre-authenticated authentication token * @return UserDetails for the given authentication token, never null. * @throws UsernameNotFoundException * if no user details can be found for the given authentication * token */ UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException; } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/UserDetailsManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/Use0000644000000000000000000000235011623517156030564 0ustar package org.springframework.security.userdetails; /** * An extension of the {@link UserDetailsService} which provides the ability * to create new users and update existing ones. * * @author Luke Taylor * @since 2.0 * @version $Id$ */ public interface UserDetailsManager extends UserDetailsService { /** * Create a new user with the supplied details. */ void createUser(UserDetails user); /** * Update the specified user. */ void updateUser(UserDetails user); /** * Remove the user with the given login name from the system. */ void deleteUser(String username); /** * Modify the current user's password. This should change the user's password in * the persistent user repository (datbase, LDAP etc) and should also modify the * current security context to contain the new password. * * @param oldPassword current password (for re-authentication if required) * @param newPassword the password to change to */ void changePassword(String oldPassword, String newPassword); /** * Check if a user with the supplied login name exists in the system. */ boolean userExists(String username); } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/checker/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/che0000755000000000000000000000000011623517156030565 5ustar ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/checker/AccountStatusUserDetailsChecker.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/che0000644000000000000000000000307111623517156030570 0ustar package org.springframework.security.userdetails.checker; import org.springframework.security.userdetails.UserDetailsChecker; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.LockedException; import org.springframework.security.DisabledException; import org.springframework.security.AccountExpiredException; import org.springframework.security.CredentialsExpiredException; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.context.support.MessageSourceAccessor; /** * @author Luke Taylor * @version $Id$ */ public class AccountStatusUserDetailsChecker implements UserDetailsChecker { protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); public void check(UserDetails user) { if (!user.isAccountNonLocked()) { throw new LockedException(messages.getMessage("UserDetailsService.locked", "User account is locked"), user); } if (!user.isEnabled()) { throw new DisabledException(messages.getMessage("UserDetailsService.disabled", "User is disabled"), user); } if (!user.isAccountNonExpired()) { throw new AccountExpiredException(messages.getMessage("UserDetailsService.expired", "User account has expired"), user); } if (!user.isCredentialsNonExpired()) { throw new CredentialsExpiredException(messages.getMessage("UserDetailsService.credentialsExpired", "User credentials have expired"), user); } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/User.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/Use0000644000000000000000000002473211623517156030574 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails; import java.util.SortedSet; import java.util.TreeSet; import org.springframework.security.GrantedAuthority; import org.springframework.util.Assert; /** * Models core user information retieved by an {@link UserDetailsService}.

    Implemented with value object * semantics (immutable after construction, like a String). Developers may use this class directly, * subclass it, or write their own {@link UserDetails} implementation from scratch.

    * * @author Ben Alex * @version $Id$ */ public class User implements UserDetails { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private String password; private String username; private GrantedAuthority[] authorities; private boolean accountNonExpired; private boolean accountNonLocked; private boolean credentialsNonExpired; private boolean enabled; //~ Constructors =================================================================================================== /** * Construct the User with the details required by * {@link org.springframework.security.providers.dao.DaoAuthenticationProvider}. * * @param username the username presented to the * DaoAuthenticationProvider * @param password the password that should be presented to the * DaoAuthenticationProvider * @param enabled set to true if the user is enabled * @param authorities the authorities that should be granted to the caller * if they presented the correct username and password and the user * is enabled * * @throws IllegalArgumentException if a null value was passed * either as a parameter or as an element in the * GrantedAuthority[] array * * @deprecated use new constructor with extended properties (this * constructor will be removed from release 1.0.0) */ public User(String username, String password, boolean enabled, GrantedAuthority[] authorities) throws IllegalArgumentException { this(username, password, enabled, true, true, authorities); } /** * Construct the User with the details required by * {@link org.springframework.security.providers.dao.DaoAuthenticationProvider}. * * @param username the username presented to the * DaoAuthenticationProvider * @param password the password that should be presented to the * DaoAuthenticationProvider * @param enabled set to true if the user is enabled * @param accountNonExpired set to true if the account has not * expired * @param credentialsNonExpired set to true if the credentials * have not expired * @param authorities the authorities that should be granted to the caller * if they presented the correct username and password and the user * is enabled * * @throws IllegalArgumentException if a null value was passed * either as a parameter or as an element in the * GrantedAuthority[] array * * @deprecated use new constructor with extended properties (this * constructor will be removed from release 1.0.0) */ public User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, GrantedAuthority[] authorities) throws IllegalArgumentException { this(username, password, enabled, accountNonExpired, credentialsNonExpired, true, authorities); } /** * Construct the User with the details required by * {@link org.springframework.security.providers.dao.DaoAuthenticationProvider}. * * @param username the username presented to the * DaoAuthenticationProvider * @param password the password that should be presented to the * DaoAuthenticationProvider * @param enabled set to true if the user is enabled * @param accountNonExpired set to true if the account has not * expired * @param credentialsNonExpired set to true if the credentials * have not expired * @param accountNonLocked set to true if the account is not * locked * @param authorities the authorities that should be granted to the caller * if they presented the correct username and password and the user * is enabled * * @throws IllegalArgumentException if a null value was passed * either as a parameter or as an element in the * GrantedAuthority[] array */ public User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, GrantedAuthority[] authorities) throws IllegalArgumentException { if (((username == null) || "".equals(username)) || (password == null)) { throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } this.username = username; this.password = password; this.enabled = enabled; this.accountNonExpired = accountNonExpired; this.credentialsNonExpired = credentialsNonExpired; this.accountNonLocked = accountNonLocked; setAuthorities(authorities); } //~ Methods ======================================================================================================== public boolean equals(Object rhs) { if (!(rhs instanceof User) || (rhs == null)) { return false; } User user = (User) rhs; // We rely on constructor to guarantee any User has non-null and >0 // authorities if (user.getAuthorities().length != this.getAuthorities().length) { return false; } for (int i = 0; i < this.getAuthorities().length; i++) { if (!this.getAuthorities()[i].equals(user.getAuthorities()[i])) { return false; } } // We rely on constructor to guarantee non-null username and password return (this.getPassword().equals(user.getPassword()) && this.getUsername().equals(user.getUsername()) && (this.isAccountNonExpired() == user.isAccountNonExpired()) && (this.isAccountNonLocked() == user.isAccountNonLocked()) && (this.isCredentialsNonExpired() == user.isCredentialsNonExpired()) && (this.isEnabled() == user.isEnabled())); } public GrantedAuthority[] getAuthorities() { return authorities; } public String getPassword() { return password; } public String getUsername() { return username; } public int hashCode() { int code = 9792; if (this.getAuthorities() != null) { for (int i = 0; i < this.getAuthorities().length; i++) { code = code * (this.getAuthorities()[i].hashCode() % 7); } } if (this.getPassword() != null) { code = code * (this.getPassword().hashCode() % 7); } if (this.getUsername() != null) { code = code * (this.getUsername().hashCode() % 7); } if (this.isAccountNonExpired()) { code = code * -2; } if (this.isAccountNonLocked()) { code = code * -3; } if (this.isCredentialsNonExpired()) { code = code * -5; } if (this.isEnabled()) { code = code * -7; } return code; } public boolean isAccountNonExpired() { return accountNonExpired; } public boolean isAccountNonLocked() { return this.accountNonLocked; } public boolean isCredentialsNonExpired() { return credentialsNonExpired; } public boolean isEnabled() { return enabled; } protected void setAuthorities(GrantedAuthority[] authorities) { Assert.notNull(authorities, "Cannot pass a null GrantedAuthority array"); // Ensure array iteration order is predictable (as per UserDetails.getAuthorities() contract and SEC-xxx) SortedSet sorter = new TreeSet(); for (int i = 0; i < authorities.length; i++) { Assert.notNull(authorities[i], "Granted authority element " + i + " is null - GrantedAuthority[] cannot contain any null elements"); sorter.add(authorities[i]); } this.authorities = (GrantedAuthority[]) sorter.toArray(new GrantedAuthority[sorter.size()]); } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString()).append(": "); sb.append("Username: ").append(this.username).append("; "); sb.append("Password: [PROTECTED]; "); sb.append("Enabled: ").append(this.enabled).append("; "); sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; "); sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; "); sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; "); if (this.getAuthorities() != null) { sb.append("Granted Authorities: "); for (int i = 0; i < this.getAuthorities().length; i++) { if (i > 0) { sb.append(", "); } sb.append(this.getAuthorities()[i].toString()); } } else { sb.append("Not granted any authorities"); } return sb.toString(); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/memory/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/mem0000755000000000000000000000000011623517156030604 5ustar ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/memory/UserAttributeEditor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/mem0000644000000000000000000000447011623517156030613 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.memory; import java.beans.PropertyEditorSupport; import java.util.ArrayList; import java.util.List; import org.springframework.util.StringUtils; /** * Property editor that creates a {@link UserAttribute} from a comma separated list of values. * * @author Ben Alex * @version $Id$ */ public class UserAttributeEditor extends PropertyEditorSupport { //~ Methods ======================================================================================================== public void setAsText(String s) throws IllegalArgumentException { if (StringUtils.hasText(s)) { String[] tokens = StringUtils.commaDelimitedListToStringArray(s); UserAttribute userAttrib = new UserAttribute(); List authoritiesAsString = new ArrayList(); for (int i = 0; i < tokens.length; i++) { String currentToken = tokens[i].trim(); if (i == 0) { userAttrib.setPassword(currentToken); } else { if (currentToken.toLowerCase().equals("enabled")) { userAttrib.setEnabled(true); } else if (currentToken.toLowerCase().equals("disabled")) { userAttrib.setEnabled(false); } else { authoritiesAsString.add(currentToken); } } } userAttrib.setAuthoritiesAsString(authoritiesAsString); if (userAttrib.isValid()) { setValue(userAttrib); } else { setValue(null); } } else { setValue(null); } } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/memory/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/mem0000644000000000000000000000011711623517156030605 0ustar Exposes an in-memory authentication repository. ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/memory/InMemoryDaoImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/mem0000644000000000000000000000476111623517156030616 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.memory; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataAccessException; import org.springframework.util.Assert; import java.util.Properties; /** * Retrieves user details from an in-memory list created by the bean context. * * @author Ben Alex * @version $Id$ */ public class InMemoryDaoImpl implements UserDetailsService, InitializingBean { //~ Instance fields ================================================================================================ private UserMap userMap; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.userMap, "A list of users, passwords, enabled/disabled status and their granted authorities must be set"); } public UserMap getUserMap() { return userMap; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { return userMap.getUser(username); } public void setUserMap(UserMap userMap) { this.userMap = userMap; } /** * Modifies the internal UserMap to reflect the Properties instance passed. This * helps externalise user information to another file etc. * * @param props the account information in a Properties object format */ public void setUserProperties(Properties props) { UserMap userMap = new UserMap(); this.userMap = UserMapEditor.addUsersFromProperties(userMap, props); } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/memory/UserMapEditor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/mem0000644000000000000000000000727511623517156030621 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.memory; import org.springframework.security.userdetails.User; import org.springframework.security.userdetails.UserDetails; import org.springframework.beans.propertyeditors.PropertiesEditor; import java.beans.PropertyEditorSupport; import java.util.Iterator; import java.util.Properties; /** * Property editor to assist with the setup of a {@link UserMap}.

    The format of entries should be:

    *

    username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]

    *

    The password must always be the first entry after the equals. The enabled or * disabled keyword can appear anywhere (apart from the first entry reserved for the password). If * neither enabled or disabled appear, the default is enabled. At least one * granted authority must be listed.

    *

    The username represents the key and duplicates are handled the same was as duplicates would be * in Java Properties files.

    *

    If the above requirements are not met, the invalid entry will be silently ignored.

    *

    This editor always assumes each entry has a non-expired account and non-expired credentials. However, it * does honour the user enabled/disabled flag as described above.

    * * @author Ben Alex * @version $Id$ */ public class UserMapEditor extends PropertyEditorSupport { //~ Methods ======================================================================================================== public static UserMap addUsersFromProperties(UserMap userMap, Properties props) { // Now we have properties, process each one individually UserAttributeEditor configAttribEd = new UserAttributeEditor(); for (Iterator iter = props.keySet().iterator(); iter.hasNext();) { String username = (String) iter.next(); String value = props.getProperty(username); // Convert value to a password, enabled setting, and list of granted authorities configAttribEd.setAsText(value); UserAttribute attr = (UserAttribute) configAttribEd.getValue(); // Make a user object, assuming the properties were properly provided if (attr != null) { UserDetails user = new User(username, attr.getPassword(), attr.isEnabled(), true, true, true, attr.getAuthorities()); userMap.addUser(user); } } return userMap; } public void setAsText(String s) throws IllegalArgumentException { UserMap userMap = new UserMap(); if ((s == null) || "".equals(s)) { // Leave value in property editor null } else { // Use properties editor to tokenize the string PropertiesEditor propertiesEditor = new PropertiesEditor(); propertiesEditor.setAsText(s); Properties props = (Properties) propertiesEditor.getValue(); addUsersFromProperties(userMap, props); } setValue(userMap); } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/memory/UserMap.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/mem0000644000000000000000000000614011623517156030607 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.memory; import java.util.HashMap; import java.util.Map; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UsernameNotFoundException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; /** * Used by {@link InMemoryDaoImpl} to store a list of users and their corresponding granted authorities. * * @author Ben Alex * @version $Id$ */ public class UserMap { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(UserMap.class); //~ Instance fields ================================================================================================ private Map userMap = new HashMap(); //~ Methods ======================================================================================================== /** * Adds a user to the in-memory map. * * @param user the user to be stored * * @throws IllegalArgumentException if a null User was passed */ public void addUser(UserDetails user) throws IllegalArgumentException { Assert.notNull(user, "Must be a valid User"); logger.info("Adding user [" + user + "]"); this.userMap.put(user.getUsername().toLowerCase(), user); } /** * Locates the specified user by performing a case insensitive search by username. * * @param username to find * * @return the located user * * @throws UsernameNotFoundException if the user could not be found */ public UserDetails getUser(String username) throws UsernameNotFoundException { UserDetails result = (UserDetails) this.userMap.get(username.toLowerCase()); if (result == null) { throw new UsernameNotFoundException("Could not find user: " + username, username); } return result; } /** * Indicates the size of the user map. * * @return the number of users in the map */ public int getUserCount() { return this.userMap.size(); } /** * Set the users in this {@link UserMap}. Overrides previously added users. * * @param users {@link Map} <{@link String}, {@link UserDetails}> with pairs (username, userdetails) * @since 1.1 */ public void setUsers(Map users) { this.userMap = users; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/memory/UserAttribute.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/mem0000644000000000000000000000630211623517156030607 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.memory; import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthorityImpl; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Vector; /** * Used by {@link InMemoryDaoImpl} to temporarily store the attributes associated with a user. * * @author Ben Alex * @version $Id$ */ public class UserAttribute { //~ Instance fields ================================================================================================ private List authorities = new Vector(); private String password; private boolean enabled = true; //~ Constructors =================================================================================================== public UserAttribute() { super(); } //~ Methods ======================================================================================================== public void addAuthority(GrantedAuthority newAuthority) { this.authorities.add(newAuthority); } public GrantedAuthority[] getAuthorities() { GrantedAuthority[] toReturn = {new GrantedAuthorityImpl("demo")}; return (GrantedAuthority[]) this.authorities.toArray(toReturn); } /** * Set all authorities for this user. * * @param authorities {@link List} <{@link GrantedAuthority}> * @since 1.1 */ public void setAuthorities(List authorities) { this.authorities = authorities; } /** * Set all authorities for this user from String values. * It will create the necessary {@link GrantedAuthority} objects. * * @param authoritiesAsString {@link List} <{@link String}> * @since 1.1 */ public void setAuthoritiesAsString(List authoritiesAsString) { setAuthorities(new ArrayList(authoritiesAsString.size())); Iterator it = authoritiesAsString.iterator(); while (it.hasNext()) { GrantedAuthority grantedAuthority = new GrantedAuthorityImpl((String) it.next()); addAuthority(grantedAuthority); } } public String getPassword() { return password; } public boolean isEnabled() { return enabled; } public boolean isValid() { if ((this.password != null) && (authorities.size() > 0)) { return true; } else { return false; } } public void setEnabled(boolean enabled) { this.enabled = enabled; } public void setPassword(String password) { this.password = password; } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/hierarchicalroles/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/hie0000755000000000000000000000000011623517156030573 5ustar ././@LongLink0000000000000000000000000000022600000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/hierarchicalroles/CycleInRoleHierarchyException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/hie0000644000000000000000000000204711623517156030600 0ustar /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.hierarchicalroles; /** * Exception that is thrown because of a cycle in the role hierarchy definition * * @author Michael Mayr */ public class CycleInRoleHierarchyException extends RuntimeException { private static final long serialVersionUID = -4970510612118296707L; public CycleInRoleHierarchyException() { super("Exception thrown because of a cycle in the role hierarchy definition!"); } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/hierarchicalroles/UserDetailsWrapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/hie0000644000000000000000000000447211623517156030604 0ustar /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.hierarchicalroles; import org.springframework.security.GrantedAuthority; import org.springframework.security.userdetails.UserDetails; /** * This class wraps Spring Security's UserDetails in a way that its getAuthorities() method is * delegated to RoleHierarchy.getReachableGrantedAuthorities. All other methods are * delegated to the UserDetails implementation. * * @author Michael Mayr * @deprecated use a {@link RoleHierarchyVoter} instead. */ public class UserDetailsWrapper implements UserDetails { private static final long serialVersionUID = 1532428778390085311L; private UserDetails userDetails = null; private RoleHierarchy roleHierarchy = null; public UserDetailsWrapper(UserDetails userDetails, RoleHierarchy roleHierarchy) { this.userDetails = userDetails; this.roleHierarchy = roleHierarchy; } public boolean isAccountNonExpired() { return userDetails.isAccountNonExpired(); } public boolean isAccountNonLocked() { return userDetails.isAccountNonLocked(); } public GrantedAuthority[] getAuthorities() { return roleHierarchy.getReachableGrantedAuthorities(userDetails.getAuthorities()); } public boolean isCredentialsNonExpired() { return userDetails.isCredentialsNonExpired(); } public boolean isEnabled() { return userDetails.isEnabled(); } public String getPassword() { return userDetails.getPassword(); } public String getUsername() { return userDetails.getUsername(); } public UserDetails getUnwrappedUserDetails() { return userDetails; } }././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/hierarchicalroles/RoleHierarchyImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/hie0000644000000000000000000002047311623517156030603 0ustar /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.hierarchicalroles; import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthorityImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.*; /** *

    * This class defines a role hierarchy for use with the UserDetailsServiceWrapper. *

    *

    * Here is an example configuration of a role hierarchy (hint: read the ">" sign as "includes"):

            <property name="hierarchy">
                <value>
                    ROLE_A > ROLE_B
                    ROLE_B > ROLE_AUTHENTICATED
                    ROLE_AUTHENTICATED > ROLE_UNAUTHENTICATED
                </value>
            </property>
    

    *

    * Explanation of the above:
    * In effect every user with ROLE_A also has ROLE_B, ROLE_AUTHENTICATED and ROLE_UNAUTHENTICATED;
    * every user with ROLE_B also has ROLE_AUTHENTICATED and ROLE_UNAUTHENTICATED;
    * every user with ROLE_AUTHENTICATED also has ROLE_UNAUTHENTICATED. *

    *

    * Hierarchical Roles will dramatically shorten your access rules (and also make the access rules much more elegant). *

    *

    * Consider this access rule for Spring Security's RoleVoter (background: every user that is authenticated should be * able to log out):
    * /logout.html=ROLE_A,ROLE_B,ROLE_AUTHENTICATED
    * With hierarchical roles this can now be shortened to:
    * /logout.html=ROLE_AUTHENTICATED
    * In addition to shorter rules this will also make your access rules more readable and your intentions clearer. *

    * * @author Michael Mayr * */ public class RoleHierarchyImpl implements RoleHierarchy { private static final Log logger = LogFactory.getLog(RoleHierarchyImpl.class); private String roleHierarchyStringRepresentation = null; /** * rolesReachableInOneStepMap is a Map that under the key of a specific role name contains a set of all roles * reachable from this role in 1 step */ private Map rolesReachableInOneStepMap = null; /** * rolesReachableInOneOrMoreStepsMap is a Map that under the key of a specific role name contains a set of all * roles reachable from this role in 1 or more steps */ private Map rolesReachableInOneOrMoreStepsMap = null; /** * Set the role hierarchy and precalculate for every role the set of all reachable roles, i. e. all roles lower in * the hierarchy of every given role. Precalculation is done for performance reasons (reachable roles can then be * calculated in O(1) time). * During precalculation cycles in role hierarchy are detected and will cause a * CycleInRoleHierarchyException to be thrown. * * @param roleHierarchyStringRepresentation - String definition of the role hierarchy. */ public void setHierarchy(String roleHierarchyStringRepresentation) { this.roleHierarchyStringRepresentation = roleHierarchyStringRepresentation; logger.debug("setHierarchy() - The following role hierarchy was set: " + roleHierarchyStringRepresentation); buildRolesReachableInOneStepMap(); buildRolesReachableInOneOrMoreStepsMap(); } public GrantedAuthority[] getReachableGrantedAuthorities(GrantedAuthority[] authorities) { if (authorities == null || authorities.length == 0) { return null; } Set reachableRoles = new HashSet(); for (int i = 0; i < authorities.length; i++) { reachableRoles.add(authorities[i]); Set additionalReachableRoles = (Set) rolesReachableInOneOrMoreStepsMap.get(authorities[i]); if (additionalReachableRoles != null) { reachableRoles.addAll(additionalReachableRoles); } } if (logger.isDebugEnabled()) { logger.debug("getReachableGrantedAuthorities() - From the roles " + Arrays.asList(authorities) + " one can reach " + reachableRoles + " in zero or more steps."); } return (GrantedAuthority[]) reachableRoles.toArray(new GrantedAuthority[reachableRoles.size()]); } /** * Parse input and build the map for the roles reachable in one step: the higher role will become a key that * references a set of the reachable lower roles. */ private void buildRolesReachableInOneStepMap() { String parsingRegex = "(\\s*([^\\s>]+)\\s*\\>\\s*([^\\s>]+))"; Pattern pattern = Pattern.compile(parsingRegex); Matcher roleHierarchyMatcher = pattern.matcher(roleHierarchyStringRepresentation); rolesReachableInOneStepMap = new HashMap(); while (roleHierarchyMatcher.find()) { GrantedAuthority higherRole = new GrantedAuthorityImpl(roleHierarchyMatcher.group(2)); GrantedAuthority lowerRole = new GrantedAuthorityImpl(roleHierarchyMatcher.group(3)); Set rolesReachableInOneStepSet = null; if (!rolesReachableInOneStepMap.containsKey(higherRole)) { rolesReachableInOneStepSet = new HashSet(); rolesReachableInOneStepMap.put(higherRole, rolesReachableInOneStepSet); } else { rolesReachableInOneStepSet = (Set) rolesReachableInOneStepMap.get(higherRole); } rolesReachableInOneStepSet.add(lowerRole); logger.debug("buildRolesReachableInOneStepMap() - From role " + higherRole + " one can reach role " + lowerRole + " in one step."); } } /** * For every higher role from rolesReachableInOneStepMap store all roles that are reachable from it in the map of * roles reachable in one or more steps. (Or throw a CycleInRoleHierarchyException if a cycle in the role * hierarchy definition is detected) */ private void buildRolesReachableInOneOrMoreStepsMap() { rolesReachableInOneOrMoreStepsMap = new HashMap(); // iterate over all higher roles from rolesReachableInOneStepMap Iterator roleIterator = rolesReachableInOneStepMap.keySet().iterator(); while (roleIterator.hasNext()) { GrantedAuthority role = (GrantedAuthority) roleIterator.next(); Set rolesToVisitSet = new HashSet(); if (rolesReachableInOneStepMap.containsKey(role)) { rolesToVisitSet.addAll((Set) rolesReachableInOneStepMap.get(role)); } Set visitedRolesSet = new HashSet(); while (!rolesToVisitSet.isEmpty()) { // take a role from the rolesToVisit set GrantedAuthority aRole = (GrantedAuthority) rolesToVisitSet.iterator().next(); rolesToVisitSet.remove(aRole); visitedRolesSet.add(aRole); if (rolesReachableInOneStepMap.containsKey(aRole)) { Set newReachableRoles = (Set) rolesReachableInOneStepMap.get(aRole); // definition of a cycle: you can reach the role you are starting from if (rolesToVisitSet.contains(role) || visitedRolesSet.contains(role)) { throw new CycleInRoleHierarchyException(); } else { // no cycle rolesToVisitSet.addAll(newReachableRoles); } } } rolesReachableInOneOrMoreStepsMap.put(role, visitedRolesSet); logger.debug("buildRolesReachableInOneOrMoreStepsMap() - From role " + role + " one can reach " + visitedRolesSet + " in one or more steps."); } } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/hierarchicalroles/UserDetailsServiceWrapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/hie0000644000000000000000000000442211623517156030577 0ustar /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.hierarchicalroles; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.dao.DataAccessException; /** * This class wraps Spring Security's UserDetailsService in a way that its loadUserByUsername() * method returns wrapped UserDetails that return all hierachically reachable authorities * instead of only the directly assigned authorities. * * @author Michael Mayr * @deprecated use a {@link RoleHierarchyVoter} instead of populating the user Authentication object * with the additional authorities. */ public class UserDetailsServiceWrapper implements UserDetailsService { private UserDetailsService userDetailsService = null; private RoleHierarchy roleHierarchy = null; public void setRoleHierarchy(RoleHierarchy roleHierarchy) { this.roleHierarchy = roleHierarchy; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { UserDetails userDetails = userDetailsService.loadUserByUsername(username); // wrapped UserDetailsService might throw UsernameNotFoundException or DataAccessException which will then bubble up return new UserDetailsWrapper(userDetails, roleHierarchy); } public UserDetailsService getWrappedUserDetailsService() { return userDetailsService; } }././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/hierarchicalroles/RoleHierarchy.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/hie0000644000000000000000000000301511623517156030574 0ustar /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.hierarchicalroles; import org.springframework.security.GrantedAuthority; /** * The simple interface of a role hierarchy. * * @author Michael Mayr * */ public interface RoleHierarchy { /** * This method returns an array of all reachable authorities.
    * Reachable authorities are the directly assigned authorities plus all * authorities that are (transitively) reachable from them in the role * hierarchy.
    * Example:
    * Role hierarchy: ROLE_A > ROLE_B and ROLE_B > ROLE_C.
    * Directly assigned authority: ROLE_A.
    * Reachable authorities: ROLE_A, ROLE_B, ROLE_C. * * @param authorities - Array of the directly assigned authorities. * @return Array of all reachable authorities given the assigned authorities. */ public GrantedAuthority[] getReachableGrantedAuthorities(GrantedAuthority[] authorities); } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/UsernameNotFoundException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/Use0000644000000000000000000000372411623517156030572 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails; import org.springframework.security.BadCredentialsException; /** * Thrown if an {@link UserDetailsService} implementation cannot locate a {@link User} by its username. * * @author Ben Alex * @version $Id$ */ public class UsernameNotFoundException extends BadCredentialsException { //~ Constructors =================================================================================================== /** * Constructs a UsernameNotFoundException with the specified * message. * * @param msg the detail message. */ public UsernameNotFoundException(String msg) { super(msg); } /** * Constructs a UsernameNotFoundException, making use of the extraInformation * property of the superclass. * * @param msg the detail message * @param extraInformation additional information such as the username. */ public UsernameNotFoundException(String msg, Object extraInformation) { super(msg, extraInformation); } /** * Constructs a UsernameNotFoundException with the specified * message and root cause. * * @param msg the detail message. * @param t root cause */ public UsernameNotFoundException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/ldap/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/lda0000755000000000000000000000000011623517156030566 5ustar ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/ldap/LdapUserDetailsManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/lda0000644000000000000000000004104011623517156030567 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.ldap; import org.springframework.security.Authentication; import org.springframework.security.BadCredentialsException; import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthorityImpl; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.ldap.LdapUsernameToDnMapper; import org.springframework.security.ldap.LdapUtils; import org.springframework.security.ldap.DefaultLdapUsernameToDnMapper; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsManager; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.dao.DataAccessException; import org.springframework.ldap.core.AttributesMapper; import org.springframework.ldap.core.AttributesMapperCallbackHandler; import org.springframework.ldap.core.ContextExecutor; import org.springframework.ldap.core.ContextSource; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DistinguishedName; import org.springframework.ldap.core.LdapTemplate; import org.springframework.ldap.core.SearchExecutor; import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.naming.Context; import javax.naming.NameNotFoundException; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttribute; import javax.naming.directory.DirContext; import javax.naming.directory.ModificationItem; import javax.naming.directory.SearchControls; import javax.naming.ldap.LdapContext; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; /** * An Ldap implementation of UserDetailsManager. *

    * It is designed around a standard setup where users and groups/roles are stored under separate contexts, * defined by the "userDnBase" and "groupSearchBase" properties respectively. *

    *

    * In this case, LDAP is being used purely to retrieve information and this class can be used in place of any other * UserDetailsService for authentication. Authentication isn't performed directly against the directory, unlike with the * LDAP authentication provider setup. *

    * * * @author Luke Taylor * @since 2.0 * @version $Id$ */ public class LdapUserDetailsManager implements UserDetailsManager { private final Log logger = LogFactory.getLog(LdapUserDetailsManager.class); /** * The strategy for mapping usernames to LDAP distinguished names. * This will be used when building DNs for creating new users etc. */ LdapUsernameToDnMapper usernameMapper = new DefaultLdapUsernameToDnMapper("cn=users", "uid"); /** The DN under which groups are stored */ private DistinguishedName groupSearchBase = new DistinguishedName("cn=groups"); /** Password attribute name */ private String passwordAttributeName = "userPassword"; /** The attribute which corresponds to the role name of a group. */ private String groupRoleAttributeName ="cn"; /** The attribute which contains members of a group */ private String groupMemberAttributeName = "uniquemember"; private String rolePrefix = "ROLE_"; /** The pattern to be used for the user search. {0} is the user's DN */ private String groupSearchFilter = "(uniquemember={0})"; /** * The strategy used to create a UserDetails object from the LDAP context, username and list of authorities. * This should be set to match the required UserDetails implementation. */ private UserDetailsContextMapper userDetailsMapper = new InetOrgPersonContextMapper(); private LdapTemplate template; /** Default context mapper used to create a set of roles from a list of attributes */ private AttributesMapper roleMapper = new AttributesMapper() { public Object mapFromAttributes(Attributes attributes) throws NamingException { Attribute roleAttr = attributes.get(groupRoleAttributeName); NamingEnumeration ne = roleAttr.getAll(); // assert ne.hasMore(); Object group = ne.next(); String role = group.toString(); return new GrantedAuthorityImpl(rolePrefix + role.toUpperCase()); } }; private String[] attributesToRetrieve; public LdapUserDetailsManager(ContextSource contextSource) { template = new LdapTemplate(contextSource); } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { DistinguishedName dn = usernameMapper.buildDn(username); GrantedAuthority[] authorities = getUserAuthorities(dn, username); logger.debug("Loading user '"+ username + "' with DN '" + dn + "'"); DirContextAdapter userCtx = loadUserAsContext(dn, username); return userDetailsMapper.mapUserFromContext(userCtx, username, authorities); } private DirContextAdapter loadUserAsContext(final DistinguishedName dn, final String username) { return (DirContextAdapter) template.executeReadOnly(new ContextExecutor() { public Object executeWithContext(DirContext ctx) throws NamingException { try { Attributes attrs = ctx.getAttributes(dn, attributesToRetrieve); return new DirContextAdapter(attrs, LdapUtils.getFullDn(dn, ctx)); } catch(NameNotFoundException notFound) { throw new UsernameNotFoundException("User " + username + " not found", notFound); } } }); } /** * Changes the password for the current user. The username is obtained from the security context. *

    * If the old password is supplied, the update will be made by rebinding as the user, thus modifying the password * using the user's permissions. If oldPassword is null, the update will be attempted using a * standard read/write context supplied by the context source. *

    * * @param oldPassword the old password * @param newPassword the new value of the password. */ public void changePassword(final String oldPassword, final String newPassword) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); Assert.notNull(authentication, "No authentication object found in security context. Can't change current user's password!"); String username = authentication.getName(); logger.debug("Changing password for user '"+ username); final DistinguishedName dn = usernameMapper.buildDn(username); final ModificationItem[] passwordChange = new ModificationItem[] { new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute(passwordAttributeName, newPassword)) }; if(oldPassword == null) { template.modifyAttributes(dn, passwordChange); return; } template.executeReadWrite(new ContextExecutor() { public Object executeWithContext(DirContext dirCtx) throws NamingException { LdapContext ctx = (LdapContext) dirCtx; ctx.removeFromEnvironment("com.sun.jndi.ldap.connect.pool"); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, LdapUtils.getFullDn(dn, ctx).toString()); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, oldPassword); // TODO: reconnect doesn't appear to actually change the credentials try { ctx.reconnect(null); } catch (javax.naming.AuthenticationException e) { throw new BadCredentialsException("Authentication for password change failed."); } ctx.modifyAttributes(dn, passwordChange); return null; } }); } /** * * @param dn the distinguished name of the entry - may be either relative to the base context * or a complete DN including the name of the context (either is supported). * @param username the user whose roles are required. * @return the granted authorities returned by the group search */ GrantedAuthority[] getUserAuthorities(final DistinguishedName dn, final String username) { SearchExecutor se = new SearchExecutor() { public NamingEnumeration executeSearch(DirContext ctx) throws NamingException { DistinguishedName fullDn = LdapUtils.getFullDn(dn, ctx); SearchControls ctrls = new SearchControls(); ctrls.setReturningAttributes(new String[] {groupRoleAttributeName}); return ctx.search(groupSearchBase, groupSearchFilter, new String[] {fullDn.toUrl(), username}, ctrls); } }; AttributesMapperCallbackHandler roleCollector = new AttributesMapperCallbackHandler(roleMapper); template.search(se, roleCollector); List authorities = roleCollector.getList(); return (GrantedAuthority[]) authorities.toArray(new GrantedAuthority[authorities.size()]); } // protected String getRoleFilter(DistinguishedName dn, String username) { // return new EqualsFilter("uniquemember", dn.toString()).encode(); // } public void createUser(UserDetails user) { DirContextAdapter ctx = new DirContextAdapter(); copyToContext(user, ctx); DistinguishedName dn = usernameMapper.buildDn(user.getUsername()); // Check for any existing authorities which might be set for this DN GrantedAuthority[] authorities = getUserAuthorities(dn, user.getUsername()); if(authorities.length > 0) { removeAuthorities(dn, authorities); } logger.debug("Creating new user '"+ user.getUsername() + "' with DN '" + dn + "'"); template.bind(dn, ctx, null); addAuthorities(dn, user.getAuthorities()); } public void updateUser(UserDetails user) { // Assert.notNull(attributesToRetrieve, "Configuration must specify a list of attributes in order to use update."); DistinguishedName dn = usernameMapper.buildDn(user.getUsername()); logger.debug("Updating user '"+ user.getUsername() + "' with DN '" + dn + "'"); GrantedAuthority[] authorities = getUserAuthorities(dn, user.getUsername()); DirContextAdapter ctx = loadUserAsContext(dn, user.getUsername()); ctx.setUpdateMode(true); copyToContext(user, ctx); // Remove the objectclass attribute from the list of mods (if present). List mods = new LinkedList(Arrays.asList(ctx.getModificationItems())); ListIterator modIt = mods.listIterator(); while(modIt.hasNext()) { ModificationItem mod = (ModificationItem) modIt.next(); Attribute a = mod.getAttribute(); if("objectclass".equalsIgnoreCase(a.getID())) { modIt.remove(); } } template.modifyAttributes(dn, (ModificationItem[]) mods.toArray(new ModificationItem[mods.size()])); // template.rebind(dn, ctx, null); // Remove the old authorities and replace them with the new one removeAuthorities(dn, authorities); addAuthorities(dn, user.getAuthorities()); } public void deleteUser(String username) { DistinguishedName dn = usernameMapper.buildDn(username); removeAuthorities(dn, getUserAuthorities(dn, username)); template.unbind(dn); } public boolean userExists(String username) { DistinguishedName dn = usernameMapper.buildDn(username); try { Object obj = template.lookup(dn); if (obj instanceof Context) { LdapUtils.closeContext((Context) obj); } return true; } catch(org.springframework.ldap.NameNotFoundException e) { return false; } } /** * Creates a DN from a group name. * * @param group the name of the group * @return the DN of the corresponding group, including the groupSearchBase */ protected DistinguishedName buildGroupDn(String group) { DistinguishedName dn = new DistinguishedName(groupSearchBase); dn.add(groupRoleAttributeName, group.toLowerCase()); return dn; } protected void copyToContext(UserDetails user, DirContextAdapter ctx) { userDetailsMapper.mapUserToContext(user, ctx); } protected void addAuthorities(DistinguishedName userDn, GrantedAuthority[] authorities) { modifyAuthorities(userDn, authorities, DirContext.ADD_ATTRIBUTE); } protected void removeAuthorities(DistinguishedName userDn, GrantedAuthority[] authorities) { modifyAuthorities(userDn, authorities, DirContext.REMOVE_ATTRIBUTE); } private void modifyAuthorities(final DistinguishedName userDn, final GrantedAuthority[] authorities, final int modType) { template.executeReadWrite(new ContextExecutor() { public Object executeWithContext(DirContext ctx) throws NamingException { for(int i=0; i < authorities.length; i++) { GrantedAuthority authority = authorities[i]; String group = convertAuthorityToGroup(authority); DistinguishedName fullDn = LdapUtils.getFullDn(userDn, ctx); ModificationItem addGroup = new ModificationItem(modType, new BasicAttribute(groupMemberAttributeName, fullDn.toUrl())); ctx.modifyAttributes(buildGroupDn(group), new ModificationItem[] {addGroup}); } return null; } }); } private String convertAuthorityToGroup(GrantedAuthority authority) { String group = authority.getAuthority(); if(group.startsWith(rolePrefix)) { group = group.substring(rolePrefix.length()); } return group; } public void setUsernameMapper(LdapUsernameToDnMapper usernameMapper) { this.usernameMapper = usernameMapper; } public void setPasswordAttributeName(String passwordAttributeName) { this.passwordAttributeName = passwordAttributeName; } public void setGroupSearchBase(String groupSearchBase) { this.groupSearchBase = new DistinguishedName(groupSearchBase); } public void setGroupRoleAttributeName(String groupRoleAttributeName) { this.groupRoleAttributeName = groupRoleAttributeName; } public void setAttributesToRetrieve(String[] attributesToRetrieve) { Assert.notNull(attributesToRetrieve); this.attributesToRetrieve = attributesToRetrieve; } public void setUserDetailsMapper(UserDetailsContextMapper userDetailsMapper) { this.userDetailsMapper = userDetailsMapper; } /** * Sets the name of the multi-valued attribute which holds the DNs of users who are members of a group. *

    * Usually this will be uniquemember (the default value) or member. *

    * * @param groupMemberAttributeName the name of the attribute used to store group members. */ public void setGroupMemberAttributeName(String groupMemberAttributeName) { Assert.hasText(groupMemberAttributeName); this.groupMemberAttributeName = groupMemberAttributeName; this.groupSearchFilter = "(" + groupMemberAttributeName + "={0})"; } public void setRoleMapper(AttributesMapper roleMapper) { this.roleMapper = roleMapper; } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/ldap/LdapUserDetailsService.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/lda0000644000000000000000000000403611623517156030573 0ustar package org.springframework.security.userdetails.ldap; import org.springframework.security.GrantedAuthority; import org.springframework.security.ldap.LdapUserSearch; import org.springframework.security.ldap.LdapAuthoritiesPopulator; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.ldap.core.DirContextOperations; import org.springframework.util.Assert; /** * LDAP implementation of UserDetailsService based around an {@link LdapUserSearch} * and an {@link LdapAuthoritiesPopulator}. The final UserDetails object * returned from loadUserByUsername is created by the configured UserDetailsContextMapper. * * @author Luke Taylor * @version $Id$ */ public class LdapUserDetailsService implements UserDetailsService { private LdapUserSearch userSearch; private LdapAuthoritiesPopulator authoritiesPopulator; private UserDetailsContextMapper userDetailsMapper = new LdapUserDetailsMapper(); public LdapUserDetailsService(LdapUserSearch userSearch, LdapAuthoritiesPopulator authoritiesPopulator) { Assert.notNull(userSearch, "userSearch must not be null"); Assert.notNull(authoritiesPopulator, "authoritiesPopulator must not be null"); this.userSearch = userSearch; this.authoritiesPopulator = authoritiesPopulator; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { DirContextOperations userData = userSearch.searchForUser(username); GrantedAuthority[] authorities = authoritiesPopulator.getGrantedAuthorities(userData, username); return userDetailsMapper.mapUserFromContext(userData, username, authorities); } public void setUserDetailsMapper(UserDetailsContextMapper userDetailsMapper) { Assert.notNull(userDetailsMapper, "userDetailsMapper must not be null"); this.userDetailsMapper = userDetailsMapper; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/ldap/Person.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/lda0000644000000000000000000000764311623517156030602 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.ldap; import org.springframework.util.Assert; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DirContextOperations; import org.springframework.security.ldap.LdapUtils; import java.util.List; import java.util.ArrayList; import java.util.Arrays; /** * UserDetails implementation whose properties are based on the LDAP schema for Person. * * @author Luke * @since 2.0 * @version $Id$ */ public class Person extends LdapUserDetailsImpl { private String sn; private String description; private String telephoneNumber; private List cn = new ArrayList(); protected Person() { } public String getSn() { return sn; } public String[] getCn() { return (String[]) cn.toArray(new String[cn.size()]); } public String getDescription() { return description; } public String getTelephoneNumber() { return telephoneNumber; } protected void populateContext(DirContextAdapter adapter) { adapter.setAttributeValue("sn", sn); adapter.setAttributeValues("cn", getCn()); adapter.setAttributeValue("description", getDescription()); adapter.setAttributeValue("telephoneNumber", getTelephoneNumber()); if(getPassword() != null) { adapter.setAttributeValue("userPassword", getPassword()); } adapter.setAttributeValues("objectclass", new String[] {"top", "person"}); } public static class Essence extends LdapUserDetailsImpl.Essence { public Essence() { } public Essence(DirContextOperations ctx) { super(ctx); setCn(ctx.getStringAttributes("cn")); setSn(ctx.getStringAttribute("sn")); setDescription(ctx.getStringAttribute("description")); setTelephoneNumber(ctx.getStringAttribute("telephoneNumber")); Object passo = ctx.getObjectAttribute("userPassword"); if(passo != null) { String password = LdapUtils.convertPasswordToString(passo); setPassword(password); } } public Essence(Person copyMe) { super(copyMe); setSn(copyMe.sn); setDescription(copyMe.getDescription()); setTelephoneNumber(copyMe.getTelephoneNumber()); ((Person) instance).cn = new ArrayList(copyMe.cn); } protected LdapUserDetailsImpl createTarget() { return new Person(); } public void setSn(String sn) { ((Person) instance).sn = sn; } public void setCn(String[] cn) { ((Person) instance).cn = Arrays.asList(cn); } public void addCn(String value) { ((Person) instance).cn.add(value); } public void setTelephoneNumber(String tel) { ((Person) instance).telephoneNumber = tel; } public void setDescription(String desc) { ((Person) instance).description = desc; } public LdapUserDetails createUserDetails() { Person p = (Person) super.createUserDetails(); Assert.hasLength(p.sn); Assert.notNull(p.cn); Assert.notEmpty(p.cn); // TODO: Check contents for null entries return p; } } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/ldap/LdapUserDetailsImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/lda0000644000000000000000000001765111623517156030602 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.ldap; import org.springframework.security.GrantedAuthority; import org.springframework.security.util.AuthorityUtils; import org.springframework.ldap.core.DirContextOperations; import org.springframework.util.Assert; import javax.naming.Name; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; /** * A UserDetails implementation which is used internally by the Ldap services. It also contains the user's * distinguished name and a set of attributes that have been retrieved from the Ldap server. *

    * An instance may be created as the result of a search, or when user information is retrieved during authentication. *

    *

    * An instance of this class will be used by the LdapAuthenticationProvider to construct the final user details * object that it returns. *

    * * @author Luke Taylor * @version $Id$ */ public class LdapUserDetailsImpl implements LdapUserDetails { //~ Instance fields ================================================================================================ private Attributes attributes = new BasicAttributes(); private String dn; private String password; private String username; private GrantedAuthority[] authorities = AuthorityUtils.NO_AUTHORITIES; private boolean accountNonExpired = true; private boolean accountNonLocked = true; private boolean credentialsNonExpired = true; private boolean enabled = true; //~ Constructors =================================================================================================== protected LdapUserDetailsImpl() {} //~ Methods ======================================================================================================== public Attributes getAttributes() { return attributes; } public GrantedAuthority[] getAuthorities() { return authorities; } public String getDn() { return dn; } public String getPassword() { return password; } public String getUsername() { return username; } public boolean isAccountNonExpired() { return accountNonExpired; } public boolean isAccountNonLocked() { return accountNonLocked; } public boolean isCredentialsNonExpired() { return credentialsNonExpired; } public boolean isEnabled() { return enabled; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString()).append(": "); sb.append("Username: ").append(this.username).append("; "); sb.append("Password: [PROTECTED]; "); sb.append("Enabled: ").append(this.enabled).append("; "); sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; "); sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; "); sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; "); if (this.getAuthorities() != null) { sb.append("Granted Authorities: "); for (int i = 0; i < this.getAuthorities().length; i++) { if (i > 0) { sb.append(", "); } sb.append(this.getAuthorities()[i].toString()); } } else { sb.append("Not granted any authorities"); } return sb.toString(); } //~ Inner Classes ================================================================================================== /** * Variation of essence pattern. Used to create mutable intermediate object */ public static class Essence { protected LdapUserDetailsImpl instance = createTarget(); private List mutableAuthorities = new ArrayList(); public Essence() { } public Essence(DirContextOperations ctx) { setDn(ctx.getDn()); } public Essence(LdapUserDetails copyMe) { setDn(copyMe.getDn()); setAttributes(copyMe.getAttributes()); setUsername(copyMe.getUsername()); setPassword(copyMe.getPassword()); setEnabled(copyMe.isEnabled()); setAccountNonExpired(copyMe.isAccountNonExpired()); setCredentialsNonExpired(copyMe.isCredentialsNonExpired()); setAccountNonLocked(copyMe.isAccountNonLocked()); setAuthorities(copyMe.getAuthorities()); } protected LdapUserDetailsImpl createTarget() { return new LdapUserDetailsImpl(); } /** Adds the authority to the list, unless it is already there, in which case it is ignored */ public void addAuthority(GrantedAuthority a) { if(!hasAuthority(a)) { mutableAuthorities.add(a); } } private boolean hasAuthority(GrantedAuthority a) { Iterator authorities = mutableAuthorities.iterator(); while(authorities.hasNext()) { GrantedAuthority authority = (GrantedAuthority) authorities.next(); if(authority.equals(a)) { return true; } } return false; } public LdapUserDetails createUserDetails() { Assert.notNull(instance, "Essence can only be used to create a single instance"); Assert.notNull(instance.username, "username must not be null"); Assert.notNull(instance.getDn(), "Distinguished name must not be null"); instance.authorities = getGrantedAuthorities(); LdapUserDetails newInstance = instance; instance = null; return newInstance; } public GrantedAuthority[] getGrantedAuthorities() { return (GrantedAuthority[]) mutableAuthorities.toArray(new GrantedAuthority[0]); } public void setAccountNonExpired(boolean accountNonExpired) { instance.accountNonExpired = accountNonExpired; } public void setAccountNonLocked(boolean accountNonLocked) { instance.accountNonLocked = accountNonLocked; } public void setAttributes(Attributes attributes) { instance.attributes = attributes; } public void setAuthorities(GrantedAuthority[] authorities) { mutableAuthorities = new ArrayList(Arrays.asList(authorities)); } public void setCredentialsNonExpired(boolean credentialsNonExpired) { instance.credentialsNonExpired = credentialsNonExpired; } public void setDn(String dn) { instance.dn = dn; } public void setDn(Name dn) { instance.dn = dn.toString(); } public void setEnabled(boolean enabled) { instance.enabled = enabled; } public void setPassword(String password) { instance.password = password; } public void setUsername(String username) { instance.username = username; } } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/ldap/InetOrgPerson.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/lda0000644000000000000000000002160311623517156030572 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.ldap; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DirContextOperations; /** * UserDetails implementation whose properties are based on a subset of the * LDAP schema for inetOrgPerson. * *

    * The username will be mapped from the uid attribute by default. * * @author Luke * @version $Id$ */ public class InetOrgPerson extends Person { private String carLicense; // Person.cn private String destinationIndicator; private String departmentNumber; // Person.description private String displayName; private String employeeNumber; private String homePhone; private String homePostalAddress; private String initials; private String mail; private String mobile; private String o; private String ou; private String postalAddress; private String postalCode; private String roomNumber; private String street; // Person.sn // Person.telephoneNumber private String title; private String uid; public String getUid() { return uid; } public String getMail() { return mail; } public String getEmployeeNumber() { return employeeNumber; } public String getInitials() { return initials; } public String getDestinationIndicator() { return destinationIndicator; } public String getO() { return o; } public String getOu() { return ou; } public String getTitle() { return title; } public String getCarLicense() { return carLicense; } public String getDepartmentNumber() { return departmentNumber; } public String getDisplayName() { return displayName; } public String getHomePhone() { return homePhone; } public String getRoomNumber() { return roomNumber; } public String getHomePostalAddress() { return homePostalAddress; } public String getMobile() { return mobile; } public String getPostalAddress() { return postalAddress; } public String getPostalCode() { return postalCode; } public String getStreet() { return street; } protected void populateContext(DirContextAdapter adapter) { super.populateContext(adapter); adapter.setAttributeValue("carLicense", carLicense); adapter.setAttributeValue("departmentNumber", departmentNumber); adapter.setAttributeValue("destinationIndicator", destinationIndicator); adapter.setAttributeValue("displayName", displayName); adapter.setAttributeValue("employeeNumber", employeeNumber); adapter.setAttributeValue("homePhone", homePhone); adapter.setAttributeValue("homePostalAddress", homePostalAddress); adapter.setAttributeValue("initials", initials); adapter.setAttributeValue("mail", mail); adapter.setAttributeValue("mobile", mobile); adapter.setAttributeValue("postalAddress", postalAddress); adapter.setAttributeValue("postalCode", postalCode); adapter.setAttributeValue("ou", ou); adapter.setAttributeValue("o", o); adapter.setAttributeValue("roomNumber", roomNumber); adapter.setAttributeValue("street", street); adapter.setAttributeValue("uid", uid); adapter.setAttributeValues("objectclass", new String[] {"top", "person", "organizationalPerson", "inetOrgPerson"}); } public static class Essence extends Person.Essence { public Essence() { } public Essence(InetOrgPerson copyMe) { super(copyMe); setCarLicense(copyMe.getCarLicense()); setDepartmentNumber(copyMe.getDepartmentNumber()); setDestinationIndicator(copyMe.getDestinationIndicator()); setDisplayName(copyMe.getDisplayName()); setEmployeeNumber(copyMe.getEmployeeNumber()); setHomePhone(copyMe.getHomePhone()); setHomePostalAddress(copyMe.getHomePostalAddress()); setInitials(copyMe.getInitials()); setMail(copyMe.getMail()); setMobile(copyMe.getMobile()); setO(copyMe.getO()); setOu(copyMe.getOu()); setPostalAddress(copyMe.getPostalAddress()); setPostalCode(copyMe.getPostalCode()); setRoomNumber(copyMe.getRoomNumber()); setStreet(copyMe.getStreet()); setTitle(copyMe.getTitle()); setUid(copyMe.getUid()); } public Essence(DirContextOperations ctx) { super(ctx); setCarLicense(ctx.getStringAttribute("carLicense")); setDepartmentNumber(ctx.getStringAttribute("departmentNumber")); setDestinationIndicator(ctx.getStringAttribute("destinationIndicator")); setDisplayName(ctx.getStringAttribute("displayName")); setEmployeeNumber(ctx.getStringAttribute("employeeNumber")); setHomePhone(ctx.getStringAttribute("homePhone")); setHomePostalAddress(ctx.getStringAttribute("homePostalAddress")); setInitials(ctx.getStringAttribute("initials")); setMail(ctx.getStringAttribute("mail")); setMobile(ctx.getStringAttribute("mobile")); setO(ctx.getStringAttribute("o")); setOu(ctx.getStringAttribute("ou")); setPostalAddress(ctx.getStringAttribute("postalAddress")); setPostalCode(ctx.getStringAttribute("postalCode")); setRoomNumber(ctx.getStringAttribute("roomNumber")); setStreet(ctx.getStringAttribute("street")); setTitle(ctx.getStringAttribute("title")); setUid(ctx.getStringAttribute("uid")); } protected LdapUserDetailsImpl createTarget() { return new InetOrgPerson(); } public void setMail(String email) { ((InetOrgPerson) instance).mail = email; } public void setUid(String uid) { ((InetOrgPerson) instance).uid = uid; if(instance.getUsername() == null) { setUsername(uid); } } public void setInitials(String initials) { ((InetOrgPerson) instance).initials = initials; } public void setO(String organization) { ((InetOrgPerson) instance).o = organization; } public void setOu(String ou) { ((InetOrgPerson) instance).ou = ou; } public void setRoomNumber(String no) { ((InetOrgPerson) instance).roomNumber = no; } public void setTitle(String title) { ((InetOrgPerson) instance).title = title; } public void setCarLicense(String carLicense) { ((InetOrgPerson) instance).carLicense = carLicense; } public void setDepartmentNumber(String departmentNumber) { ((InetOrgPerson) instance).departmentNumber = departmentNumber; } public void setDisplayName(String displayName) { ((InetOrgPerson) instance).displayName = displayName; } public void setEmployeeNumber(String no) { ((InetOrgPerson) instance).employeeNumber = no; } public void setDestinationIndicator(String destination) { ((InetOrgPerson) instance).destinationIndicator = destination; } public void setHomePhone(String homePhone) { ((InetOrgPerson) instance).homePhone = homePhone; } public void setStreet(String street) { ((InetOrgPerson) instance).street = street; } public void setPostalCode(String postalCode) { ((InetOrgPerson) instance).postalCode = postalCode; } public void setPostalAddress(String postalAddress) { ((InetOrgPerson) instance).postalAddress = postalAddress; } public void setMobile(String mobile) { ((InetOrgPerson) instance).mobile = mobile; } public void setHomePostalAddress(String homePostalAddress) { ((InetOrgPerson) instance).homePostalAddress = homePostalAddress; } } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/ldap/InetOrgPersonContextMapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/lda0000644000000000000000000000316311623517156030573 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.ldap; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.GrantedAuthority; import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.util.Assert; /** * @author Luke Taylor * @version $Id$ */ public class InetOrgPersonContextMapper implements UserDetailsContextMapper { public UserDetails mapUserFromContext(DirContextOperations ctx, String username, GrantedAuthority[] authorities) { InetOrgPerson.Essence p = new InetOrgPerson.Essence(ctx); p.setUsername(username); p.setAuthorities(authorities); return p.createUserDetails(); } public void mapUserToContext(UserDetails user, DirContextAdapter ctx) { Assert.isInstanceOf(InetOrgPerson.class, user, "UserDetails must be an InetOrgPerson instance"); InetOrgPerson p = (InetOrgPerson) user; p.populateContext(ctx); } } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/ldap/UserDetailsContextMapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/lda0000644000000000000000000000356411623517156030600 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.ldap; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.GrantedAuthority; import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.DirContextAdapter; /** * Operations to map a UserDetails object to and from a Spring LDAP DirContextOperations implementation. * Used by LdapUserDetailsManager when loading and saving/creating user information. * * @author Luke Taylor * @since 2.0 * @version $Id$ */ public interface UserDetailsContextMapper { /** * Creates a fully populated UserDetails object for use by the security framework. * * @param ctx the context object which contains the user information. * @param username the user's supplied login name. * @param authority the list of authorities which the user should be given. * @return the user object. */ UserDetails mapUserFromContext(DirContextOperations ctx, String username, GrantedAuthority[] authority); /** * Reverse of the above operation. Populates a context object from the supplied user object. * Called when saving a user, for example. */ void mapUserToContext(UserDetails user, DirContextAdapter ctx); } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/ldap/LdapUserDetailsMapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/lda0000644000000000000000000001466111623517156030600 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.ldap; import org.springframework.security.GrantedAuthorityImpl; import org.springframework.security.GrantedAuthority; import org.springframework.security.userdetails.UserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DirContextOperations; /** * The context mapper used by the LDAP authentication provider to create an LDAP user object. * * @author Luke Taylor * @version $Id$ */ public class LdapUserDetailsMapper implements UserDetailsContextMapper { //~ Instance fields ================================================================================================ private final Log logger = LogFactory.getLog(LdapUserDetailsMapper.class); private String passwordAttributeName = "userPassword"; private String rolePrefix = "ROLE_"; private String[] roleAttributes = null; private boolean convertToUpperCase = true; //~ Methods ======================================================================================================== public UserDetails mapUserFromContext(DirContextOperations ctx, String username, GrantedAuthority[] authorities) { String dn = ctx.getNameInNamespace(); logger.debug("Mapping user details from context with DN: " + dn); LdapUserDetailsImpl.Essence essence = new LdapUserDetailsImpl.Essence(); essence.setDn(dn); Object passwordValue = ctx.getObjectAttribute(passwordAttributeName); if (passwordValue != null) { essence.setPassword(mapPassword(passwordValue)); } essence.setUsername(username); // Map the roles for (int i = 0; (roleAttributes != null) && (i < roleAttributes.length); i++) { String[] rolesForAttribute = ctx.getStringAttributes(roleAttributes[i]); if (rolesForAttribute == null) { logger.debug("Couldn't read role attribute '" + roleAttributes[i] + "' for user " + dn); continue; } for (int j = 0; j < rolesForAttribute.length; j++) { GrantedAuthority authority = createAuthority(rolesForAttribute[j]); if (authority != null) { essence.addAuthority(authority); } } } // Add the supplied authorities for (int i=0; i < authorities.length; i++) { essence.addAuthority(authorities[i]); } return essence.createUserDetails(); } public void mapUserToContext(UserDetails user, DirContextAdapter ctx) { throw new UnsupportedOperationException("LdapUserDetailsMapper only supports reading from a context. Please" + "use a subclass if mapUserToContext() is required."); } /** * Extension point to allow customized creation of the user's password from * the attribute stored in the directory. * * @param passwordValue the value of the password attribute * @return a String representation of the password. */ protected String mapPassword(Object passwordValue) { if (!(passwordValue instanceof String)) { // Assume it's binary passwordValue = new String((byte[]) passwordValue); } return (String) passwordValue; } /** * Creates a GrantedAuthority from a role attribute. Override to customize * authority object creation. *

    * The default implementation converts string attributes to roles, making use of the rolePrefix * and convertToUpperCase properties. Non-String attributes are ignored. *

    * * @param role the attribute returned from * @return the authority to be added to the list of authorities for the user, or null * if this attribute should be ignored. */ protected GrantedAuthority createAuthority(Object role) { if (role instanceof String) { if (convertToUpperCase) { role = ((String) role).toUpperCase(); } return new GrantedAuthorityImpl(rolePrefix + role); } return null; } /** * Determines whether role field values will be converted to upper case when loaded. * The default is true. * * @param convertToUpperCase true if the roles should be converted to upper case. */ public void setConvertToUpperCase(boolean convertToUpperCase) { this.convertToUpperCase = convertToUpperCase; } /** * The name of the attribute which contains the user's password. * Defaults to "userPassword". * * @param passwordAttributeName the name of the attribute */ public void setPasswordAttributeName(String passwordAttributeName) { this.passwordAttributeName = passwordAttributeName; } /** * The names of any attributes in the user's entry which represent application * roles. These will be converted to GrantedAuthoritys and added to the * list in the returned LdapUserDetails object. The attribute values must be Strings by default. * * @param roleAttributes the names of the role attributes. */ public void setRoleAttributes(String[] roleAttributes) { Assert.notNull(roleAttributes, "roleAttributes array cannot be null"); this.roleAttributes = roleAttributes; } /** * The prefix that should be applied to the role names * @param rolePrefix the prefix (defaults to "ROLE_"). */ public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/ldap/LdapUserDetails.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/lda0000644000000000000000000000315311623517156030572 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.userdetails.ldap; import org.springframework.security.userdetails.UserDetails; import javax.naming.directory.Attributes; /** * Captures the information for a user's LDAP entry. * * @author Luke Taylor * @version $Id$ */ public interface LdapUserDetails extends UserDetails { //~ Methods ======================================================================================================== /** * The attributes for the user's entry in the directory (or a subset of them, depending on what was * retrieved from the directory). * * @deprecated Map additional attributes to user properties in a custom object rather than accessing them here. * @return the user's attributes, or an empty array if none were obtained, never null. */ Attributes getAttributes(); /** * The DN of the entry for this user's account. * * @return the user's DN */ String getDn(); } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/ldap/PersonContextMapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/userdetails/lda0000644000000000000000000000172311623517156030573 0ustar package org.springframework.security.userdetails.ldap; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.GrantedAuthority; import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.util.Assert; /** * @author Luke Taylor * @version $Id$ */ public class PersonContextMapper implements UserDetailsContextMapper { public UserDetails mapUserFromContext(DirContextOperations ctx, String username, GrantedAuthority[] authorities) { Person.Essence p = new Person.Essence(ctx); p.setUsername(username); p.setAuthorities(authorities); return p.createUserDetails(); } public void mapUserToContext(UserDetails user, DirContextAdapter ctx) { Assert.isInstanceOf(Person.class, user, "UserDetails must be a Person instance"); Person p = (Person) user; p.populateContext(ctx); } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ConfigAttributeDefinition.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ConfigAttribute0000644000000000000000000001427611623517156030607 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.springframework.util.Assert; /** * Holds a group of {@link ConfigAttribute}s that are associated with a given secure object target - effectively a * Collection. *

    * Once created, the object is immutable. *

    * All the ConfigAttributeDefinitions associated with a given {@link * org.springframework.security.intercept.AbstractSecurityInterceptor} are stored in an {@link * org.springframework.security.intercept.ObjectDefinitionSource}. * * @author Ben Alex * @version $Id$ */ public class ConfigAttributeDefinition implements Serializable { public static final ConfigAttributeDefinition NO_ATTRIBUTES = new ConfigAttributeDefinition(); //~ Instance fields ================================================================================================ private List configAttributes; //~ Constructors =================================================================================================== private ConfigAttributeDefinition() { configAttributes = Collections.EMPTY_LIST; } /** * Creates a ConfigAttributeDefinition containing a single attribute * @param attribute the String name of the attribute (converted internally to a SecurityConfig instance). */ public ConfigAttributeDefinition(String attribute) { configAttributes = new ArrayList(1); configAttributes.add(new SecurityConfig(attribute)); configAttributes = Collections.unmodifiableList(configAttributes); } /** * Creates a ConfigAttributeDefinition containing a single attribute. */ public ConfigAttributeDefinition(ConfigAttribute attribute) { configAttributes = new ArrayList(1); configAttributes.add(attribute); configAttributes = Collections.unmodifiableList(configAttributes); } /** * Builds a collection of ConfigAttributes from an array of String tokens, each of which will be wrapped in a * SecurityConfig instance. * * @param attributeTokens the tokens which will be turned into attributes. */ public ConfigAttributeDefinition(String[] attributeTokens) { configAttributes = new ArrayList(attributeTokens.length); for (int i = 0; i < attributeTokens.length; i++) { configAttributes.add(new SecurityConfig(attributeTokens[i].trim())); } configAttributes = Collections.unmodifiableList(configAttributes); } /** * Creates an immutable ConfigAttributeDefinition from the supplied list of ConfigAttribute objects. */ public ConfigAttributeDefinition(List configAttributes) { Iterator attributes = configAttributes.iterator(); while (attributes.hasNext()) { Assert.isInstanceOf(ConfigAttribute.class, attributes.next(), "List entries must be of type ConfigAttribute"); } this.configAttributes = Collections.unmodifiableList(new ArrayList(configAttributes)); } /** * Creates a ConfigAttributeDefinition by including only those attributes which implement ConfigAttribute. * * @param unfilteredInput a collection of various elements, zero or more which implement ConfigAttribute (can also be null) * @return a ConfigAttributeDefinition if at least one ConfigAttribute was present, or null if none implemented it */ public static ConfigAttributeDefinition createFiltered(Collection unfilteredInput) { if (unfilteredInput == null) { return null; } List configAttributes = new ArrayList(); Iterator i = unfilteredInput.iterator(); while (i.hasNext()) { Object element = i.next(); if (element instanceof ConfigAttribute) { configAttributes.add(element); } } if (configAttributes.size() == 0) { return null; } return new ConfigAttributeDefinition(configAttributes); } //~ Methods ======================================================================================================== /** * Indicates whether the specified ConfigAttribute is contained within this * ConfigAttributeDefinition. * * @param configAttribute the attribute to locate * * @return true if the specified ConfigAttribute is contained, false * otherwise */ public boolean contains(ConfigAttribute configAttribute) { return configAttributes.contains(configAttribute); } public boolean equals(Object obj) { if (!(obj instanceof ConfigAttributeDefinition)) { return false; } ConfigAttributeDefinition test = (ConfigAttributeDefinition) obj; return configAttributes.equals(test.configAttributes); } /** * Returns the internal collection of ConfigAttributes defined by this * ConfigAttributeDefinition. *

    * Allows AccessDecisionManagers and other classes to loop through every configuration attribute * associated with a target secure object. * * @return the configuration attributes stored in this instance. */ public Collection getConfigAttributes() { return this.configAttributes; } public String toString() { return this.configAttributes.toString(); } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/SpringSecurityMessageSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/SpringSecurityM0000644000000000000000000000351411623517156030616 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.context.support.ResourceBundleMessageSource; /** * The default MessageSource used by Spring Security. *

    All Spring Security classes requiring messge localization will by default use this class. * However, all such classes will also implement MessageSourceAware so that the application context can * inject an alternative message source. Therefore this class is only used when the deployment environment has not * specified an alternative message source.

    * * @author Ben Alex * @version $Id$ */ public class SpringSecurityMessageSource extends ResourceBundleMessageSource { //~ Constructors =================================================================================================== public SpringSecurityMessageSource() { setBasename("org.springframework.security.messages"); } //~ Methods ======================================================================================================== public static MessageSourceAccessor getAccessor() { return new MessageSourceAccessor(new SpringSecurityMessageSource()); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/0000755000000000000000000000000011623520776027560 5ustar ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000755000000000000000000000000011623517156030613 5ustar ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/MethodDefinitionAttributes.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000535411623517156030624 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.method; import java.lang.reflect.Method; import java.util.Collection; import org.springframework.beans.factory.InitializingBean; import org.springframework.metadata.Attributes; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.util.Assert; /** * Provides {@link ConfigAttributeDefinition}s for a method signature (via the lookupAttributes method) * by delegating to a configured {@link Attributes} object. The latter may use Commons attributes * or some other approach to determine the ConfigAttributes which apply. * *

    * Note that attributes defined against parent classes (either for their methods or interfaces) are not * detected. The attributes must be defined against an explicit method or interface on the intercepted class. *

    * * Attributes detected that do not implement {@link ConfigAttribute} will be ignored. * * @author Cameron Braid * @author Ben Alex * @version $Id$ */ public class MethodDefinitionAttributes extends AbstractFallbackMethodDefinitionSource implements InitializingBean { //~ Instance fields ================================================================================================ private Attributes attributes; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(attributes, "attributes required"); } public Collection getConfigAttributeDefinitions() { return null; } protected ConfigAttributeDefinition findAttributes(Class clazz) { return ConfigAttributeDefinition.createFiltered(attributes.getAttributes(clazz)); } protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) { return ConfigAttributeDefinition.createFiltered(attributes.getAttributes(method)); } public void setAttributes(Attributes attributes) { Assert.notNull(attributes, "Attributes required"); this.attributes = attributes; } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/MethodDefinitionSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000225411623517156030620 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.method; import java.lang.reflect.Method; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.ObjectDefinitionSource; /** * Interface for ObjectDefinitionSource implementations * that are designed to perform lookups keyed on Methods. * * @author Ben Alex * @version $Id$ */ public interface MethodDefinitionSource extends ObjectDefinitionSource { public ConfigAttributeDefinition getAttributes(Method method, Class targetClass); } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/aspectj/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000755000000000000000000000000011623517156030613 5ustar ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/aspectj/AspectJSecurityInterceptor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000663411623517156030626 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.method.aspectj; import org.springframework.security.intercept.AbstractSecurityInterceptor; import org.springframework.security.intercept.InterceptorStatusToken; import org.springframework.security.intercept.ObjectDefinitionSource; import org.springframework.security.intercept.method.MethodDefinitionSource; import org.aspectj.lang.JoinPoint; /** * Provides security interception of AspectJ method invocations.

    The ObjectDefinitionSource required * by this security interceptor is of type {@link MethodDefinitionSource}. This is shared with the AOP Alliance based * security interceptor (MethodSecurityInterceptor), since both work with Java Methods.

    *

    The secure object type is org.aspectj.lang.JoinPoint, which is passed from the relevant * around() advice. The around() advice also passes an anonymous implementation of {@link * AspectJCallback} which contains the call for AspectJ to continue processing: return proceed();.

    *

    Refer to {@link AbstractSecurityInterceptor} for details on the workflow.

    * * @author Ben Alex * @version $Id$ */ public class AspectJSecurityInterceptor extends AbstractSecurityInterceptor { //~ Instance fields ================================================================================================ private MethodDefinitionSource objectDefinitionSource; //~ Methods ======================================================================================================== public MethodDefinitionSource getObjectDefinitionSource() { return this.objectDefinitionSource; } public Class getSecureObjectClass() { return JoinPoint.class; } /** * This method should be used to enforce security on a JoinPoint. * * @param jp The AspectJ joint point being invoked which requires a security decision * @param advisorProceed the advice-defined anonymous class that implements AspectJCallback containing * a simple return proceed(); statement * * @return The returned value from the method invocation */ public Object invoke(JoinPoint jp, AspectJCallback advisorProceed) { Object result = null; InterceptorStatusToken token = super.beforeInvocation(jp); try { result = advisorProceed.proceedWithObject(); } finally { result = super.afterInvocation(token, result); } return result; } public ObjectDefinitionSource obtainObjectDefinitionSource() { return this.objectDefinitionSource; } public void setObjectDefinitionSource(MethodDefinitionSource newSource) { this.objectDefinitionSource = newSource; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/aspectj/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000031311623517156030612 0ustar Enforces security for AspectJ JointPoints, delegating secure object callbacks to the calling aspect.

    Refer to the reference guide for information on usage. ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/aspectj/AspectJAnnotationCallback.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000071011623517156030613 0ustar package org.springframework.security.intercept.method.aspectj; /** * Called by the {@link AspectJAnnotationSecurityInterceptor} when it wishes for the * AspectJ processing to continue. * * @author Mike Wiesner * @version $Id$ */ public interface AspectJAnnotationCallback { //~ Methods ======================================================================================================== Object proceedWithObject() throws Throwable; } ././@LongLink0000000000000000000000000000023000000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/aspectj/AspectJAnnotationSecurityInterceptor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000420311623517156030614 0ustar package org.springframework.security.intercept.method.aspectj; import org.springframework.security.intercept.AbstractSecurityInterceptor; import org.springframework.security.intercept.InterceptorStatusToken; import org.springframework.security.intercept.ObjectDefinitionSource; import org.springframework.security.intercept.method.MethodDefinitionSource; import org.aspectj.lang.JoinPoint; /** * AspectJ interceptor that supports @Aspect notation. * * @author Mike Wiesner * @version $Id$ */ public class AspectJAnnotationSecurityInterceptor extends AbstractSecurityInterceptor { //~ Instance fields ================================================================================================ private MethodDefinitionSource objectDefinitionSource; //~ Methods ======================================================================================================== public MethodDefinitionSource getObjectDefinitionSource() { return this.objectDefinitionSource; } public Class getSecureObjectClass() { return JoinPoint.class; } /** * This method should be used to enforce security on a JoinPoint. * * @param jp The AspectJ joint point being invoked which requires a security decision * @param advisorProceed the advice-defined anonymous class that implements AspectJCallback containing * a simple return proceed(); statement * * @return The returned value from the method invocation */ public Object invoke(JoinPoint jp, AspectJAnnotationCallback advisorProceed) throws Throwable { Object result = null; InterceptorStatusToken token = super.beforeInvocation(jp); try { result = advisorProceed.proceedWithObject(); } finally { result = super.afterInvocation(token, result); } return result; } public ObjectDefinitionSource obtainObjectDefinitionSource() { return this.objectDefinitionSource; } public void setObjectDefinitionSource(MethodDefinitionSource newSource) { this.objectDefinitionSource = newSource; } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/aspectj/AspectJCallback.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000220111623517156030610 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.method.aspectj; /** * Called by the {@link AspectJSecurityInterceptor} when it wishes for the * AspectJ processing to continue. Typically implemented in the * around() advice as a simple return proceed(); * statement. * * @author Ben Alex * @version $Id$ */ public interface AspectJCallback { //~ Methods ======================================================================================================== Object proceedWithObject(); } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000017111623517156030614 0ustar Provides support objects for securing Java method invocations via different AOP libraries. ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/MethodDefinitionSourceEditor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000517111623517156030621 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.method; import org.springframework.security.ConfigAttributeDefinition; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.propertyeditors.PropertiesEditor; import org.springframework.util.StringUtils; import java.beans.PropertyEditorSupport; import java.util.Iterator; import java.util.Properties; import java.util.Map; import java.util.LinkedHashMap; /** * Property editor to assist with the setup of a {@link MethodDefinitionSource}. *

    The class creates and populates a {@link MapBasedMethodDefinitionSource}.

    * * @author Ben Alex * @version $Id$ */ public class MethodDefinitionSourceEditor extends PropertyEditorSupport { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(MethodDefinitionSourceEditor.class); //~ Methods ======================================================================================================== public void setAsText(String s) throws IllegalArgumentException { if ((s == null) || "".equals(s)) { setValue(new MapBasedMethodDefinitionSource()); return; } // Use properties editor to tokenize the string PropertiesEditor propertiesEditor = new PropertiesEditor(); propertiesEditor.setAsText(s); Properties props = (Properties) propertiesEditor.getValue(); // Now we have properties, process each one individually Map mappings = new LinkedHashMap(); for (Iterator iter = props.keySet().iterator(); iter.hasNext();) { String name = (String) iter.next(); String value = props.getProperty(name); String[] tokens = StringUtils.commaDelimitedListToStringArray(value); mappings.put(name, new ConfigAttributeDefinition(tokens)); } setValue(new MapBasedMethodDefinitionSource(mappings)); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/aopalliance/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000755000000000000000000000000011623517156030613 5ustar ././@LongLink0000000000000000000000000000022500000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/aopalliance/MethodDefinitionSourceAdvisor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000001514311623517156030621 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.method.aopalliance; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; import org.aopalliance.aop.Advice; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.Pointcut; import org.springframework.aop.support.AbstractPointcutAdvisor; import org.springframework.aop.support.StaticMethodMatcherPointcut; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.security.intercept.method.MethodDefinitionSource; import org.springframework.util.Assert; /** * Advisor driven by a {@link MethodDefinitionSource}, used to exclude a {@link MethodSecurityInterceptor} from * public (ie non-secure) methods. *

    * Because the AOP framework caches advice calculations, this is normally faster than just letting the * MethodSecurityInterceptor run and find out itself that it has no work to do. *

    * This class also allows the use of Spring's * {@link org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator}, which makes * configuration easier than setup a ProxyFactoryBean for each object requiring security. Note that * autoproxying is not supported for BeanFactory implementations, as post-processing is automatic only for application * contexts. *

    * Based on Spring's TransactionAttributeSourceAdvisor. * * @author Ben Alex * @version $Id$ */ public class MethodDefinitionSourceAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware { //~ Instance fields ================================================================================================ private MethodDefinitionSource attributeSource; private MethodSecurityInterceptor interceptor; private Pointcut pointcut = new MethodDefinitionSourcePointcut(); private BeanFactory beanFactory; private String adviceBeanName; private final Object adviceMonitor = new Object(); //~ Constructors =================================================================================================== /** * @deprecated use the decoupled approach instead */ public MethodDefinitionSourceAdvisor(MethodSecurityInterceptor advice) { Assert.notNull(advice.getObjectDefinitionSource(), "Cannot construct a MethodDefinitionSourceAdvisor using a " + "MethodSecurityInterceptor that has no ObjectDefinitionSource configured"); this.interceptor = advice; this.attributeSource = advice.getObjectDefinitionSource(); } /** * Alternative constructor for situations where we want the advisor decoupled from the advice. Instead the advice * bean name should be set. This prevents eager instantiation of the interceptor * (and hence the AuthenticationManager). See SEC-773, for example. *

    * This is essentially the approach taken by subclasses of {@link AbstractBeanFactoryPointcutAdvisor}, which this * class should extend in future. The original hierarchy and constructor have been retained for backwards * compatibility. * * @param adviceBeanName name of the MethodSecurityInterceptor bean * @param attributeSource the attribute source (should be the same as the one used on the interceptor) */ public MethodDefinitionSourceAdvisor(String adviceBeanName, MethodDefinitionSource attributeSource) { Assert.notNull(adviceBeanName, "The adviceBeanName cannot be null"); Assert.notNull(attributeSource, "The attributeSource cannot be null"); this.adviceBeanName = adviceBeanName; this.attributeSource = attributeSource; } //~ Methods ======================================================================================================== public Pointcut getPointcut() { return pointcut; } public Advice getAdvice() { synchronized (this.adviceMonitor) { if (interceptor == null) { Assert.notNull(adviceBeanName, "'adviceBeanName' must be set for use with bean factory lookup."); Assert.state(beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'"); interceptor = (MethodSecurityInterceptor) beanFactory.getBean(this.adviceBeanName, MethodSecurityInterceptor.class); } return interceptor; } } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } //~ Inner Classes ================================================================================================== class MethodDefinitionSourcePointcut extends StaticMethodMatcherPointcut { public boolean matches(Method m, Class targetClass) { return attributeSource.getAttributes(m, targetClass) != null; } } /** * Represents a MethodInvocation. *

    * Required as MethodDefinitionSource only supports lookup of configuration attributes for * MethodInvocations. */ class InternalMethodInvocation implements MethodInvocation { private Method method; private Class targetClass; public InternalMethodInvocation(Method method, Class targetClass) { this.method = method; this.targetClass = targetClass; } protected InternalMethodInvocation() { throw new UnsupportedOperationException(); } public Object[] getArguments() { throw new UnsupportedOperationException(); } public Method getMethod() { return this.method; } public AccessibleObject getStaticPart() { throw new UnsupportedOperationException(); } public Object getThis() { return this.targetClass; } public Object proceed() throws Throwable { throw new UnsupportedOperationException(); } } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/aopalliance/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000017111623517156030614 0ustar Enforces security for AOP Alliance MethodInvocations, such as via Spring AOP. ././@LongLink0000000000000000000000000000022100000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/aopalliance/MethodSecurityInterceptor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000602311623517156030616 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.method.aopalliance; import org.springframework.security.intercept.AbstractSecurityInterceptor; import org.springframework.security.intercept.InterceptorStatusToken; import org.springframework.security.intercept.ObjectDefinitionSource; import org.springframework.security.intercept.method.MethodDefinitionSource; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * Provides security interception of AOP Alliance based method invocations.

    The * ObjectDefinitionSource required by this security interceptor is of type {@link * MethodDefinitionSource}. This is shared with the AspectJ based security interceptor * (AspectJSecurityInterceptor), since both work with Java Methods.

    *

    Refer to {@link AbstractSecurityInterceptor} for details on the workflow.

    * * @author Ben Alex * @version $Id$ */ public class MethodSecurityInterceptor extends AbstractSecurityInterceptor implements MethodInterceptor { //~ Instance fields ================================================================================================ private MethodDefinitionSource objectDefinitionSource; //~ Methods ======================================================================================================== public MethodDefinitionSource getObjectDefinitionSource() { return this.objectDefinitionSource; } public Class getSecureObjectClass() { return MethodInvocation.class; } /** * This method should be used to enforce security on a MethodInvocation. * * @param mi The method being invoked which requires a security decision * * @return The returned value from the method invocation * * @throws Throwable if any error occurs */ public Object invoke(MethodInvocation mi) throws Throwable { Object result = null; InterceptorStatusToken token = super.beforeInvocation(mi); try { result = mi.proceed(); } finally { result = super.afterInvocation(token, result); } return result; } public ObjectDefinitionSource obtainObjectDefinitionSource() { return this.objectDefinitionSource; } public void setObjectDefinitionSource(MethodDefinitionSource newSource) { this.objectDefinitionSource = newSource; } } ././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/DelegatingMethodDefinitionSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000461311623517156030621 0ustar package org.springframework.security.intercept.method; import java.lang.reflect.Method; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.util.Assert; /** * Automatically tries a series of method definition sources, relying on the first source of metadata * that provides a non-null response. * * @author Ben Alex * @version $Id$ */ public final class DelegatingMethodDefinitionSource implements MethodDefinitionSource, InitializingBean { private List methodDefinitionSources; public void afterPropertiesSet() throws Exception { Assert.notEmpty(methodDefinitionSources, "A list of MethodDefinitionSources is required"); } public ConfigAttributeDefinition getAttributes(Method method, Class targetClass) { Iterator i = methodDefinitionSources.iterator(); while (i.hasNext()) { MethodDefinitionSource s = (MethodDefinitionSource) i.next(); ConfigAttributeDefinition result = s.getAttributes(method, targetClass); if (result != null) { return result; } } return null; } public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { Iterator i = methodDefinitionSources.iterator(); while (i.hasNext()) { MethodDefinitionSource s = (MethodDefinitionSource) i.next(); ConfigAttributeDefinition result = s.getAttributes(object); if (result != null) { return result; } } return null; } public Collection getConfigAttributeDefinitions() { Set set = new HashSet(); Iterator i = methodDefinitionSources.iterator(); while (i.hasNext()) { MethodDefinitionSource s = (MethodDefinitionSource) i.next(); Collection attrs = s.getConfigAttributeDefinitions(); if (attrs != null) { set.addAll(attrs); } } return set; } public boolean supports(Class clazz) { Iterator i = methodDefinitionSources.iterator(); while (i.hasNext()) { MethodDefinitionSource s = (MethodDefinitionSource) i.next(); if (s.supports(clazz)) { return true; } } return false; } public void setMethodDefinitionSources(List methodDefinitionSources) { Assert.notEmpty(methodDefinitionSources, "A list of MethodDefinitionSources is required"); this.methodDefinitionSources = methodDefinitionSources; } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/AbstractMethodDefinitionSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000000754611623517156030631 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.method; import org.springframework.security.ConfigAttributeDefinition; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.CodeSignature; import org.springframework.util.Assert; import java.lang.reflect.Method; /** * Abstract implementation of MethodDefinitionSource. * * @author Ben Alex * @version $Id$ */ public abstract class AbstractMethodDefinitionSource implements MethodDefinitionSource { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AbstractMethodDefinitionSource.class); //~ Methods ======================================================================================================== public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { Assert.notNull(object, "Object cannot be null"); if (object instanceof MethodInvocation) { return this.lookupAttributes(((MethodInvocation) object).getMethod()); } if (object instanceof JoinPoint) { JoinPoint jp = (JoinPoint) object; Class targetClazz = jp.getTarget().getClass(); String targetMethodName = jp.getStaticPart().getSignature().getName(); Class[] types = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes(); if (logger.isDebugEnabled()) { logger.debug("Target Class: " + targetClazz); logger.debug("Target Method Name: " + targetMethodName); for (int i = 0; i < types.length; i++) { if (logger.isDebugEnabled()) { logger.debug("Target Method Arg #" + i + ": " + types[i]); } } } try { return this.lookupAttributes(targetClazz.getMethod(targetMethodName, types)); } catch (NoSuchMethodException nsme) { throw new IllegalArgumentException("Could not obtain target method from JoinPoint: " + jp); } } throw new IllegalArgumentException("Object must be a MethodInvocation or JoinPoint"); } /** * Performs the actual lookup of the relevant ConfigAttributeDefinition for the specified * Method which is subject of the method invocation.

    Provided so subclasses need only to * provide one basic method to properly interface with the MethodDefinitionSource.

    *

    Returns null if there are no matching attributes for the method.

    * * @param method the method being invoked for which configuration attributes should be looked up * * @return the ConfigAttributeDefinition that applies to the specified Method */ protected abstract ConfigAttributeDefinition lookupAttributes(Method method); public boolean supports(Class clazz) { return (MethodInvocation.class.isAssignableFrom(clazz) || JoinPoint.class.isAssignableFrom(clazz)); } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/AbstractFallbackMethodDefinitionSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000002065411623517156030624 0ustar package org.springframework.security.intercept.method; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.CodeSignature; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; /** * Abstract implementation of {@link MethodDefinitionSource} that supports both Spring AOP and AspectJ and * caches configuration attribute resolution from: 1. specific target method; 2. target class; 3. declaring method; * 4. declaring class/interface. * *

    * This class mimics the behaviour of Spring's AbstractFallbackTransactionAttributeSource class. *

    * *

    * Note that this class cannot extract security metadata where that metadata is expressed by way of * a target method/class (ie #1 and #2 above) AND the target method/class is encapsulated in another * proxy object. Spring Security does not walk a proxy chain to locate the concrete/final target object. * Consider making Spring Security your final advisor (so it advises the final target, as opposed to * another proxy), move the metadata to declared methods or interfaces the proxy implements, or provide * your own replacement MethodDefinitionSource. *

    * * @author Ben Alex * @version $Id$ * @since 2.0 */ public abstract class AbstractFallbackMethodDefinitionSource implements MethodDefinitionSource { private static final Log logger = LogFactory.getLog(AbstractFallbackMethodDefinitionSource.class); private final static Object NULL_CONFIG_ATTRIBUTE = new Object(); private final Map attributeCache = new HashMap(); public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { Assert.notNull(object, "Object cannot be null"); if (object instanceof MethodInvocation) { MethodInvocation mi = (MethodInvocation) object; Object target = mi.getThis(); return getAttributes(mi.getMethod(), target == null ? null : target.getClass()); } if (object instanceof JoinPoint) { JoinPoint jp = (JoinPoint) object; Class targetClass = jp.getTarget().getClass(); String targetMethodName = jp.getStaticPart().getSignature().getName(); Class[] types = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes(); Class declaringType = ((CodeSignature) jp.getStaticPart().getSignature()).getDeclaringType(); Method method = ClassUtils.getMethodIfAvailable(declaringType, targetMethodName, types); Assert.notNull(method, "Could not obtain target method from JoinPoint: '"+ jp + "'"); return getAttributes(method, targetClass); } throw new IllegalArgumentException("Object must be a MethodInvocation or JoinPoint"); } public final boolean supports(Class clazz) { return (MethodInvocation.class.isAssignableFrom(clazz) || JoinPoint.class.isAssignableFrom(clazz)); } public ConfigAttributeDefinition getAttributes(Method method, Class targetClass) { // First, see if we have a cached value. Object cacheKey = new DefaultCacheKey(method, targetClass); synchronized (this.attributeCache) { Object cached = this.attributeCache.get(cacheKey); if (cached != null) { // Value will either be canonical value indicating there is no config attribute, // or an actual config attribute. if (cached == NULL_CONFIG_ATTRIBUTE) { return null; } else { return (ConfigAttributeDefinition) cached; } } else { // We need to work it out. ConfigAttributeDefinition cfgAtt = computeAttributes(method, targetClass); // Put it in the cache. if (cfgAtt == null) { this.attributeCache.put(cacheKey, NULL_CONFIG_ATTRIBUTE); } else { if (logger.isDebugEnabled()) { logger.debug("Adding security method [" + cacheKey + "] with attribute [" + cfgAtt + "]"); } this.attributeCache.put(cacheKey, cfgAtt); } return cfgAtt; } } } /** * * @param method the method for the current invocation (never null) * @param targetClass the target class for this invocation (may be null) * @return */ private ConfigAttributeDefinition computeAttributes(Method method, Class targetClass) { // The method may be on an interface, but we need attributes from the target class. // If the target class is null, the method will be unchanged. Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass); // First try is the method in the target class. ConfigAttributeDefinition attr = findAttributes(specificMethod, targetClass); if (attr != null) { return attr; } // Second try is the config attribute on the target class. attr = findAttributes(specificMethod.getDeclaringClass()); if (attr != null) { return attr; } if (specificMethod != method || targetClass == null) { // Fallback is to look at the original method. attr = findAttributes(method, method.getDeclaringClass()); if (attr != null) { return attr; } // Last fallback is the class of the original method. return findAttributes(method.getDeclaringClass()); } return null; } /** * Obtains the security metadata applicable to the specified method invocation. * *

    * Note that the {@link Method#getDeclaringClass()} may not equal the targetClass. * Both parameters are provided to assist subclasses which may wish to provide advanced * capabilities related to method metadata being "registered" against a method even if the * target class does not declare the method (i.e. the subclass may only inherit the method). * * @param method the method for the current invocation (never null) * @param targetClass the target class for the invocation (may be null) * @return the security metadata (or null if no metadata applies) */ protected abstract ConfigAttributeDefinition findAttributes(Method method, Class targetClass); /** * Obtains the security metadata registered against the specified class. * *

    * Subclasses should only return metadata expressed at a class level. Subclasses should NOT * aggregate metadata for each method registered against a class, as the abstract superclass * will separate invoke {@link #findAttributes(Method, Class)} for individual methods as * appropriate. * * @param clazz the target class for the invocation (never null) * @return the security metadata (or null if no metadata applies) */ protected abstract ConfigAttributeDefinition findAttributes(Class clazz); private static class DefaultCacheKey { private final Method method; private final Class targetClass; public DefaultCacheKey(Method method, Class targetClass) { this.method = method; this.targetClass = targetClass; } public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof DefaultCacheKey)) { return false; } DefaultCacheKey otherKey = (DefaultCacheKey) other; return (this.method.equals(otherKey.method) && ObjectUtils.nullSafeEquals(this.targetClass, otherKey.targetClass)); } public int hashCode() { return this.method.hashCode() * 21 + (this.targetClass != null ? this.targetClass.hashCode() : 0); } public String toString() { return "CacheKey[" + (targetClass == null ? "-" : targetClass.getName()) + "; " + method + "]"; } } } ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/ProtectPointcutPostProcessor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000001663311623517156030626 0ustar package org.springframework.security.intercept.method; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.weaver.tools.PointcutExpression; import org.aspectj.weaver.tools.PointcutParser; import org.aspectj.weaver.tools.PointcutPrimitive; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.method.aopalliance.MethodDefinitionSourceAdvisor; import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** * Parses AspectJ pointcut expressions, registering methods that match the pointcut with a * traditional {@link MapBasedMethodDefinitionSource}. * *

    * This class provides a convenient way of declaring a list of pointcuts, and then * having every method of every bean defined in the Spring application context compared with * those pointcuts. Where a match is found, the matching method will be registered with the * {@link MapBasedMethodDefinitionSource}. *

    * *

    * It is very important to understand that only the first pointcut that matches a given * method will be taken as authoritative for that method. This is why pointcuts should be provided * as a LinkedHashMap, because their order is very important. *

    * *

    * Note also that only beans defined in the Spring application context will be examined by this * class. *

    * *

    * Because this class registers method security metadata with {@link MapBasedMethodDefinitionSource}, * normal Spring Security capabilities such as {@link MethodDefinitionSourceAdvisor} can be used. * It does not matter the fact the method metadata was originally obtained from an AspectJ pointcut * expression evaluation. *

    * * @author Ben Alex * @verion $Id$ * @since 2.0 * */ public final class ProtectPointcutPostProcessor implements BeanPostProcessor { private static final Log logger = LogFactory.getLog(ProtectPointcutPostProcessor.class); private Map pointcutMap = new LinkedHashMap(); /** Key: string-based pointcut, value: ConfigAttributeDefinition */ private MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource; private PointcutParser parser; private final Set processedBeans = new HashSet(); public ProtectPointcutPostProcessor(MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource) { Assert.notNull(mapBasedMethodDefinitionSource, "MapBasedMethodDefinitionSource to populate is required"); this.mapBasedMethodDefinitionSource = mapBasedMethodDefinitionSource; // Setup AspectJ pointcut expression parser Set supportedPrimitives = new HashSet(); supportedPrimitives.add(PointcutPrimitive.EXECUTION); supportedPrimitives.add(PointcutPrimitive.ARGS); supportedPrimitives.add(PointcutPrimitive.REFERENCE); // supportedPrimitives.add(PointcutPrimitive.THIS); // supportedPrimitives.add(PointcutPrimitive.TARGET); // supportedPrimitives.add(PointcutPrimitive.WITHIN); // supportedPrimitives.add(PointcutPrimitive.AT_ANNOTATION); // supportedPrimitives.add(PointcutPrimitive.AT_WITHIN); // supportedPrimitives.add(PointcutPrimitive.AT_ARGS); // supportedPrimitives.add(PointcutPrimitive.AT_TARGET); parser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(supportedPrimitives); } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (processedBeans.contains(beanName)) { // We already have the metadata for this bean return bean; } // Obtain methods for the present bean Method[] methods; try { methods = bean.getClass().getMethods(); } catch (Exception e) { throw new IllegalStateException(e.getMessage()); } // Check to see if any of those methods are compatible with our pointcut expressions for (int i = 0; i < methods.length; i++) { Iterator iter = pointcutMap.keySet().iterator(); while (iter.hasNext()) { String ex = iter.next().toString(); // Parse the presented AspectJ pointcut expression PointcutExpression expression = parser.parsePointcutExpression(ex); // Try for the bean class directly if (attemptMatch(bean.getClass(), methods[i], expression, beanName)) { // We've found the first expression that matches this method, so move onto the next method now break; // the "while" loop, not the "for" loop } } } processedBeans.add(beanName); return bean; } private boolean attemptMatch(Class targetClass, Method method, PointcutExpression expression, String beanName) { // Determine if the presented AspectJ pointcut expression matches this method boolean matches = expression.matchesMethodExecution(method).alwaysMatches(); // Handle accordingly if (matches) { ConfigAttributeDefinition attr = (ConfigAttributeDefinition) pointcutMap.get(expression.getPointcutExpression()); if (logger.isDebugEnabled()) { logger.debug("AspectJ pointcut expression '" + expression.getPointcutExpression() + "' matches target class '" + targetClass.getName() + "' (bean ID '" + beanName + "') for method '" + method + "'; registering security configuration attribute '" + attr + "'"); } mapBasedMethodDefinitionSource.addSecureMethod(targetClass, method, attr); } return matches; } public void setPointcutMap(Map map) { Assert.notEmpty(map); Iterator i = map.keySet().iterator(); while (i.hasNext()) { String expression = i.next().toString(); Object value = map.get(expression); Assert.isInstanceOf(ConfigAttributeDefinition.class, value, "Map keys must be instances of ConfigAttributeDefinition"); addPointcut(expression, (ConfigAttributeDefinition) value); } } private void addPointcut(String pointcutExpression, ConfigAttributeDefinition definition) { Assert.hasText(pointcutExpression, "An AspectJ pointcut expression is required"); Assert.notNull(definition, "ConfigAttributeDefinition required"); pointcutExpression = replaceBooleanOperators(pointcutExpression); pointcutMap.put(pointcutExpression, definition); if (logger.isDebugEnabled()) { logger.debug("AspectJ pointcut expression '" + pointcutExpression + "' registered for security configuration attribute '" + definition + "'"); } } /** * @see org.springframework.aop.aspectj.AspectJExpressionPointcut#replaceBooleanOperators */ private String replaceBooleanOperators(String pcExpr) { pcExpr = StringUtils.replace(pcExpr," and "," && "); pcExpr = StringUtils.replace(pcExpr, " or ", " || "); pcExpr = StringUtils.replace(pcExpr, " not ", " ! "); return pcExpr; } } ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/MethodInvocationPrivilegeEvaluator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000001020611623517156030614 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.method; import org.springframework.security.AccessDeniedException; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.AbstractSecurityInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Allows users to determine whether they have "before invocation" privileges for a given method invocation.

    Of * course, if an {@link org.springframework.security.AfterInvocationManager} is used to authorize the result of a method * invocation, this class cannot assist determine whether or not the AfterInvocationManager will enable * access. Instead this class aims to allow applications to determine whether or not the current principal would be * allowed to at least attempt to invoke the method, irrespective of the "after" invocation handling.

    * * @author Ben Alex * @version $Id$ */ public class MethodInvocationPrivilegeEvaluator implements InitializingBean { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(MethodInvocationPrivilegeEvaluator.class); //~ Instance fields ================================================================================================ private AbstractSecurityInterceptor securityInterceptor; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(securityInterceptor, "SecurityInterceptor required"); } public boolean isAllowed(MethodInvocation mi, Authentication authentication) { Assert.notNull(mi, "MethodInvocation required"); Assert.notNull(mi.getMethod(), "MethodInvocation must provide a non-null getMethod()"); ConfigAttributeDefinition attrs = securityInterceptor.obtainObjectDefinitionSource().getAttributes(mi); if (attrs == null) { if (securityInterceptor.isRejectPublicInvocations()) { return false; } return true; } if ((authentication == null) || (authentication.getAuthorities() == null) || (authentication.getAuthorities().length == 0)) { return false; } try { securityInterceptor.getAccessDecisionManager().decide(authentication, mi, attrs); } catch (AccessDeniedException unauthorized) { if (logger.isDebugEnabled()) { logger.debug(mi.toString() + " denied for " + authentication.toString(), unauthorized); } return false; } return true; } public void setSecurityInterceptor(AbstractSecurityInterceptor securityInterceptor) { Assert.notNull(securityInterceptor, "AbstractSecurityInterceptor cannot be null"); Assert.isTrue(MethodInvocation.class.equals(securityInterceptor.getSecureObjectClass()), "AbstractSecurityInterceptor does not support MethodInvocations"); Assert.notNull(securityInterceptor.getAccessDecisionManager(), "AbstractSecurityInterceptor must provide a non-null AccessDecisionManager"); this.securityInterceptor = securityInterceptor; } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/method/MapBasedMethodDefinitionSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/metho0000644000000000000000000002700711623517156030623 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.method; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** * Stores a {@link ConfigAttributeDefinition} for a method or class signature. * *

    * This class is the preferred implementation of {@link MethodDefinitionSource} for XML-based * definition of method security metadata. To assist in XML-based definition, wildcard support * is provided. *

    * * @author Ben Alex * @version $Id$ * @since 2.0 */ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefinitionSource implements BeanClassLoaderAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(MapBasedMethodDefinitionSource.class); //~ Instance fields ================================================================================================ private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); /** Map from RegisteredMethod to ConfigAttributeDefinition */ protected Map methodMap = new HashMap(); /** Map from RegisteredMethod to name pattern used for registration */ private Map nameMap = new HashMap(); //~ Methods ======================================================================================================== public MapBasedMethodDefinitionSource() { } /** * Creates the MapBasedMethodDefinitionSource from a * @param methodMap map of method names to ConfigAttributeDefinitions. */ public MapBasedMethodDefinitionSource(Map methodMap) { Iterator iterator = methodMap.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); addSecureMethod((String)entry.getKey(), (ConfigAttributeDefinition)entry.getValue()); } } /** * Implementation does not support class-level attributes. */ protected ConfigAttributeDefinition findAttributes(Class clazz) { return null; } /** * Will walk the method inheritance tree to find the most specific declaration applicable. */ protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) { if (targetClass == null) { return null; } return findAttributesSpecifiedAgainst(method, targetClass); } private ConfigAttributeDefinition findAttributesSpecifiedAgainst(Method method, Class clazz) { RegisteredMethod registeredMethod = new RegisteredMethod(method, clazz); if (methodMap.containsKey(registeredMethod)) { return (ConfigAttributeDefinition) methodMap.get(registeredMethod); } // Search superclass if (clazz.getSuperclass() != null) { return findAttributesSpecifiedAgainst(method, clazz.getSuperclass()); } return null; } /** * Add configuration attributes for a secure method. Method names can end or start with * * for matching multiple methods. * * @param name type and method name, separated by a dot * @param attr required authorities associated with the method */ public void addSecureMethod(String name, ConfigAttributeDefinition attr) { int lastDotIndex = name.lastIndexOf("."); if (lastDotIndex == -1) { throw new IllegalArgumentException("'" + name + "' is not a valid method name: format is FQN.methodName"); } String methodName = name.substring(lastDotIndex + 1); Assert.hasText(methodName, "Method not found for '" + name + "'"); String typeName = name.substring(0, lastDotIndex); Class type = ClassUtils.resolveClassName(typeName, this.beanClassLoader); addSecureMethod(type, methodName, attr); } /** * Add configuration attributes for a secure method. Mapped method names can end or start with * * for matching multiple methods. * * @param javaType target interface or class the security configuration attribute applies to * @param mappedName mapped method name, which the javaType has declared or inherited * @param attr required authorities associated with the method */ public void addSecureMethod(Class javaType, String mappedName, ConfigAttributeDefinition attr) { String name = javaType.getName() + '.' + mappedName; if (logger.isDebugEnabled()) { logger.debug("Request to add secure method [" + name + "] with attributes [" + attr + "]"); } Method[] methods = javaType.getMethods(); List matchingMethods = new ArrayList(); for (int i = 0; i < methods.length; i++) { if (methods[i].getName().equals(mappedName) || isMatch(methods[i].getName(), mappedName)) { matchingMethods.add(methods[i]); } } if (matchingMethods.isEmpty()) { throw new IllegalArgumentException("Couldn't find method '" + mappedName + "' on '" + javaType + "'"); } // register all matching methods for (Iterator it = matchingMethods.iterator(); it.hasNext();) { Method method = (Method) it.next(); RegisteredMethod registeredMethod = new RegisteredMethod(method, javaType); String regMethodName = (String) this.nameMap.get(registeredMethod); if ((regMethodName == null) || (!regMethodName.equals(name) && (regMethodName.length() <= name.length()))) { // no already registered method name, or more specific // method name specification now -> (re-)register method if (regMethodName != null) { logger.debug("Replacing attributes for secure method [" + method + "]: current name [" + name + "] is more specific than [" + regMethodName + "]"); } this.nameMap.put(registeredMethod, name); addSecureMethod(registeredMethod, attr); } else { logger.debug("Keeping attributes for secure method [" + method + "]: current name [" + name + "] is not more specific than [" + regMethodName + "]"); } } } /** * Adds configuration attributes for a specific method, for example where the method has been * matched using a pointcut expression. If a match already exists in the map for the method, then * the existing match will be retained, so that if this method is called for a more general pointcut * it will not override a more specific one which has already been added. This */ public void addSecureMethod(Class javaType, Method method, ConfigAttributeDefinition attr) { RegisteredMethod key = new RegisteredMethod(method, javaType); if (methodMap.containsKey(key)) { logger.debug("Method [" + method + "] is already registered with attributes [" + methodMap.get(key) + "]"); return; } methodMap.put(key, attr); } /** * Add configuration attributes for a secure method. * * @param method the method to be secured * @param attr required authorities associated with the method */ private void addSecureMethod(RegisteredMethod method, ConfigAttributeDefinition attr) { Assert.notNull(method, "RegisteredMethod required"); Assert.notNull(attr, "Configuration attribute required"); if (logger.isInfoEnabled()) { logger.info("Adding secure method [" + method + "] with attributes [" + attr + "]"); } this.methodMap.put(method, attr); } /** * Obtains the configuration attributes explicitly defined against this bean. * * @return the attributes explicitly defined against this bean */ public Collection getConfigAttributeDefinitions() { return Collections.unmodifiableCollection(methodMap.values()); } /** * Return if the given method name matches the mapped name. The default implementation checks for "xxx" and * "xxx" matches. * * @param methodName the method name of the class * @param mappedName the name in the descriptor * * @return if the names match */ private boolean isMatch(String methodName, String mappedName) { return (mappedName.endsWith("*") && methodName.startsWith(mappedName.substring(0, mappedName.length() - 1))) || (mappedName.startsWith("*") && methodName.endsWith(mappedName.substring(1, mappedName.length()))); } public void setBeanClassLoader(ClassLoader beanClassLoader) { Assert.notNull(beanClassLoader, "Bean class loader required"); this.beanClassLoader = beanClassLoader; } /** * @return map size (for unit tests and diagnostics) */ public int getMethodMapSize() { return methodMap.size(); } /** * Stores both the Java Method as well as the Class we obtained the Method from. This is necessary because Method only * provides us access to the declaring class. It doesn't provide a way for us to introspect which Class the Method * was registered against. If a given Class inherits and redeclares a method (i.e. calls super();) the registered Class * and declaring Class are the same. If a given class merely inherits but does not redeclare a method, the registered * Class will be the Class we're invoking against and the Method will provide details of the declared class. */ private class RegisteredMethod { private Method method; private Class registeredJavaType; public RegisteredMethod(Method method, Class registeredJavaType) { Assert.notNull(method, "Method required"); Assert.notNull(registeredJavaType, "Registered Java Type required"); this.method = method; this.registeredJavaType = registeredJavaType; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj != null && obj instanceof RegisteredMethod) { RegisteredMethod rhs = (RegisteredMethod) obj; return method.equals(rhs.method) && registeredJavaType.equals(rhs.registeredJavaType); } return false; } public int hashCode() { return method.hashCode() * registeredJavaType.hashCode(); } public String toString() { return "RegisteredMethod[" + registeredJavaType.getName() + "; " + method + "]"; } } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/packa0000644000000000000000000000274511623517156030570 0ustar Actually enforces the security and ties the whole security system together.

    A secure object is a term frequently used throughout the security system. It does not refer to a business object that is being secured, but instead refers to some infrastructure object that can have security facilities provided for it by Spring Security. For example, one secure object would be MethodInvocation, whilst another would be HTTP {@link org.springframwork.security.intercept.web.FilterInvocation}. Note these are infrastructure objects and their design allows them to represent a large variety of actual resources that might need to be secured, such as business objects or HTTP request URLs.

    Each secure object typically has its own org.springframwork.security.intercept package. Each package usually includes a concrete security interceptor (which subclasses {@link org.springframework.security.intercept.AbstractSecurityInterceptor}, an appropriate {@link org.springframework.security.intercept.ObjectDefinitionSource} for the type of resources the secure object represents, and a property editor to populate the ObjectDefinitionSource.

    It is simple to create new secure object types, given the AbstractSecurityInterceptor provides the majority of the logic and other specialised packages provide the authentication, authorization, run-as replacement management and ContextHolder population. spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/0000755000000000000000000000000011623517156030333 5ustar ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/FIDSToFilterChainMapConverter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/F0000644000000000000000000000546011623517156030450 0ustar package org.springframework.security.intercept.web; import org.springframework.context.ApplicationContext; import org.springframework.util.Assert; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.util.FilterChainProxy; import org.springframework.security.util.UrlMatcher; import javax.servlet.Filter; import java.util.*; import java.util.regex.Pattern; /** * Used internally to provide backward compatibility for configuration of FilterChainProxy using a * FilterInvocationDefinitionSource. This is deprecated in favour of namespace-based configuration. * * This class will convert a FilterInvocationDefinitionSource into a suitable Map, provided it is one of the * recognised implementations (ant path or regular expression). The order of the mappings will be * preserved in the Map. * * @author Luke Taylor * @version $Id$ */ public class FIDSToFilterChainMapConverter { private LinkedHashMap filterChainMap = new LinkedHashMap(); private UrlMatcher matcher; public FIDSToFilterChainMapConverter(DefaultFilterInvocationDefinitionSource fids, ApplicationContext appContext) { // TODO: Check if this is necessary. Retained from refactoring of FilterChainProxy Assert.notNull(fids.getConfigAttributeDefinitions(), "FilterChainProxy requires the " + "FilterInvocationDefinitionSource to return a non-null response to getConfigAttributeDefinitions()"); matcher = fids.getUrlMatcher(); Map requestMap = fids.getRequestMap(); Iterator paths = requestMap.keySet().iterator(); while (paths.hasNext()) { Object entry = paths.next(); String path = entry instanceof Pattern ? ((Pattern)entry).pattern() : (String)entry; ConfigAttributeDefinition configAttributeDefinition = (ConfigAttributeDefinition) requestMap.get(entry); List filters = new ArrayList(); Iterator attributes = configAttributeDefinition.getConfigAttributes().iterator(); while (attributes.hasNext()) { ConfigAttribute attr = (ConfigAttribute) attributes.next(); String filterName = attr.getAttribute(); Assert.notNull(filterName, "Configuration attribute: '" + attr + "' returned null to the getAttribute() " + "method, which is invalid when used with FilterChainProxy"); if (!filterName.equals(FilterChainProxy.TOKEN_NONE)) { filters.add(appContext.getBean(filterName, Filter.class)); } } filterChainMap.put(path, filters); } } public Map getFilterChainMap() { return filterChainMap; } public UrlMatcher getMatcher() { return matcher; } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/FilterInvocation.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/F0000644000000000000000000000720211623517156030444 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.web; import org.springframework.security.util.UrlUtils; import javax.servlet.FilterChain; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Holds objects associated with a HTTP filter.

    Guarantees the request and response are instances of * HttpServletRequest and HttpServletResponse, and that there are no null * objects.

    *

    Required so that security system classes can obtain access to the filter environment, as well as the request * and response.

    * * @author Ben Alex * @author colin sampaleanu * @version $Id$ */ public class FilterInvocation { //~ Instance fields ================================================================================================ private FilterChain chain; private ServletRequest request; private ServletResponse response; //~ Constructors =================================================================================================== public FilterInvocation(ServletRequest request, ServletResponse response, FilterChain chain) { if ((request == null) || (response == null) || (chain == null)) { throw new IllegalArgumentException("Cannot pass null values to constructor"); } if (!(request instanceof HttpServletRequest)) { throw new IllegalArgumentException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new IllegalArgumentException("Can only process HttpServletResponse"); } this.request = request; this.response = response; this.chain = chain; } //~ Methods ======================================================================================================== public FilterChain getChain() { return chain; } /** * Indicates the URL that the user agent used for this request.

    The returned URL does not reflect * the port number determined from a {@link org.springframework.security.util.PortResolver}.

    * * @return the full URL of this request */ public String getFullRequestUrl() { return UrlUtils.getFullRequestUrl(this); } public HttpServletRequest getHttpRequest() { return (HttpServletRequest) request; } public HttpServletResponse getHttpResponse() { return (HttpServletResponse) response; } public ServletRequest getRequest() { return request; } /** * Obtains the web application-specific fragment of the URL. * * @return the URL, excluding any server name, context path or servlet path */ public String getRequestUrl() { return UrlUtils.getRequestUrl(this); } public ServletResponse getResponse() { return response; } public String toString() { return "FilterInvocation: URL: " + getRequestUrl(); } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/p0000644000000000000000000000014311623517156030513 0ustar Enforces security for HTTP requests, typically by the URL requested. ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/FilterInvocationDefinitionSourceEditor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/F0000644000000000000000000001770711623517156030457 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.web; import java.beans.PropertyEditorSupport; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.util.LinkedHashMap; import org.springframework.security.util.StringSplitUtils; import org.springframework.security.util.RegexUrlPathMatcher; import org.springframework.security.util.UrlMatcher; import org.springframework.security.util.AntUrlPathMatcher; import org.springframework.security.ConfigAttributeDefinition; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.StringUtils; /** * Property editor to assist with the setup of a {@link FilterInvocationDefinitionSource}. *

    * Note that from version 2.0, the use of property-editor based configuration is deprecated in favour of namespace * configuration options. *

    * The class creates and populates a * {@link org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource} * using either an Ant or Regular Expression URL matching strategy depending on the type of patterns presented. *

    * By default the class treats presented patterns as regular expressions. If the keyword * PATTERN_TYPE_APACHE_ANT is present (case sensitive), patterns will be treated as Apache Ant paths * rather than regular expressions. * * @author Ben Alex * @deprecated Use namespace configuration instead. May be removed in future versions. * @version $Id$ */ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSupport { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(FilterInvocationDefinitionSourceEditor.class); public static final String DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON = "CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON"; public static final String DIRECTIVE_PATTERN_TYPE_APACHE_ANT = "PATTERN_TYPE_APACHE_ANT"; //~ Methods ======================================================================================================== public void setAsText(String s) throws IllegalArgumentException { if ((s == null) || "".equals(s)) { // Leave target object empty setValue(new DefaultFilterInvocationDefinitionSource(new RegexUrlPathMatcher())); return; } boolean useAnt = s.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1; boolean converUrlToLowerCase = s.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1; if (logger.isDebugEnabled()) { if (useAnt) { logger.debug(("Detected " + DIRECTIVE_PATTERN_TYPE_APACHE_ANT + " directive; using Apache Ant style path expressions")); } if (converUrlToLowerCase) { if (logger.isDebugEnabled()) { logger.debug("Detected " + DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON + " directive; Instructing mapper to convert URLs to lowercase before comparison"); } } } BufferedReader br = new BufferedReader(new StringReader(s)); int counter = 0; String line; LinkedHashMap urlMap = new LinkedHashMap(); while (true) { counter++; try { line = br.readLine(); } catch (IOException ioe) { throw new IllegalArgumentException(ioe.getMessage()); } if (line == null) { break; } line = line.trim(); if (logger.isDebugEnabled()) { logger.debug("Line " + counter + ": " + line); } if (line.startsWith("//")) { continue; } // Attempt to detect malformed lines (as per SEC-204) if (line.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1) { // Directive found; check for second directive or name=value if ((line.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) || (line.lastIndexOf("=") != -1)) { throw new IllegalArgumentException("Line appears to be malformed: " + line); } } // Attempt to detect malformed lines (as per SEC-204) if (line.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) { // Directive found; check for second directive or name=value if ((line.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1) || (line.lastIndexOf("=") != -1)) { throw new IllegalArgumentException("Line appears to be malformed: " + line); } } // Skip lines that are not directives if (line.lastIndexOf('=') == -1) { continue; } if (line.lastIndexOf("==") != -1) { throw new IllegalArgumentException("Only single equals should be used in line " + line); } // Tokenize the line into its name/value tokens // As per SEC-219, use the LAST equals as the delimiter between LHS and RHS String name = StringSplitUtils.substringBeforeLast(line, "="); String value = StringSplitUtils.substringAfterLast(line, "="); if (!StringUtils.hasText(name) || !StringUtils.hasText(value)) { throw new IllegalArgumentException("Failed to parse a valid name/value pair from " + line); } // Attempt to detect malformed lines (as per SEC-204) if (converUrlToLowerCase && useAnt) { // Should all be lowercase; check each character // We only do this for Ant (regexp have control chars) for (int i = 0; i < name.length(); i++) { String character = name.substring(i, i + 1); if (!character.toLowerCase().equals(character)) { throw new IllegalArgumentException("You are using the " + DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON + " with Ant Paths, yet you have specified an uppercase character in line: " + line + " (character '" + character + "')"); } } } String[] tokens = StringUtils.commaDelimitedListToStringArray(value); urlMap.put(new RequestKey(name), new ConfigAttributeDefinition(tokens)); } DefaultFilterInvocationDefinitionSource fids = new DefaultFilterInvocationDefinitionSource(createMatcher(useAnt, converUrlToLowerCase), urlMap); if (useAnt) { fids.setStripQueryStringFromUrls(true); } setValue(fids); } private UrlMatcher createMatcher(boolean useAnt, boolean converUrlToLowerCase) { UrlMatcher matcher; if (useAnt) { matcher = new AntUrlPathMatcher(); ((AntUrlPathMatcher)matcher).setRequiresLowerCaseUrl(converUrlToLowerCase); } else { matcher = new RegexUrlPathMatcher(); ((RegexUrlPathMatcher)matcher).setRequiresLowerCaseUrl(converUrlToLowerCase); } return matcher; } } ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/DefaultFilterInvocationDefinitionSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/D0000644000000000000000000002301211623517156030437 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.web; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.util.UrlMatcher; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Map; import java.util.LinkedHashMap; import java.util.Iterator; import java.util.HashMap; import java.util.Set; import java.util.HashSet; import java.util.Arrays; import java.util.Collection; import java.util.Collections; /** * Default implementation of FilterInvocationDefinitionSource. *

    * Stores an ordered map of compiled URL paths to ConfigAttributeDefinitions and provides URL matching * against the items stored in this map using the configured UrlMatcher. *

    * The order of registering the regular expressions using the * {@link #addSecureUrl(String, ConfigAttributeDefinition)} is very important. * The system will identify the first matching regular * expression for a given HTTP URL. It will not proceed to evaluate later regular expressions if a match has already * been found. Accordingly, the most specific regular expressions should be registered first, with the most general * regular expressions registered last. *

    * If URLs are registered for a particular HTTP method using * {@link #addSecureUrl(String, String, ConfigAttributeDefinition)}, then the method-specific matches will take * precedence over any URLs which are registered without an HTTP method. * * @author Ben Alex * @author Luke Taylor * @version $Id$ */ public class DefaultFilterInvocationDefinitionSource implements FilterInvocationDefinitionSource { private static final Set HTTP_METHODS = new HashSet(Arrays.asList(new String[]{ "DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT", "TRACE" })); protected final Log logger = LogFactory.getLog(getClass()); /** * Non method-specific map of URL patterns to ConfigAttributeDefinitions * TODO: Store in the httpMethod map with null key. */ private Map requestMap = new LinkedHashMap(); /** Stores request maps keyed by specific HTTP methods */ private Map httpMethodMap = new HashMap(); private UrlMatcher urlMatcher; private boolean stripQueryStringFromUrls; /** * Creates a FilterInvocationDefinitionSource with the supplied URL matching strategy. * @param urlMatcher */ DefaultFilterInvocationDefinitionSource(UrlMatcher urlMatcher) { this.urlMatcher = urlMatcher; } /** * Builds the internal request map from the supplied map. The key elements should be of type {@link RequestKey}, * which contains a URL path and an optional HTTP method (may be null). The path stored in the key will depend on * the type of the supplied UrlMatcher. * * @param urlMatcher typically an ant or regular expression matcher. * @param requestMap order-preserving map of . */ public DefaultFilterInvocationDefinitionSource(UrlMatcher urlMatcher, LinkedHashMap requestMap) { this.urlMatcher = urlMatcher; Iterator iterator = requestMap.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); RequestKey reqKey = (RequestKey) entry.getKey(); addSecureUrl(reqKey.getUrl(), reqKey.getMethod(), (ConfigAttributeDefinition) entry.getValue()); } } //~ Methods ======================================================================================================== void addSecureUrl(String pattern, ConfigAttributeDefinition attr) { addSecureUrl(pattern, null, attr); } /** * Adds a URL-ConfigAttributeDefinition pair to the request map, first allowing the UrlMatcher to * process the pattern if required, using its compile method. The returned object will be used as the key * to the request map and will be passed back to the UrlMatcher when iterating through the map to find * a match for a particular URL. */ void addSecureUrl(String pattern, String method, ConfigAttributeDefinition attr) { Map mapToUse = getRequestMapForHttpMethod(method); mapToUse.put(urlMatcher.compile(pattern), attr); if (logger.isDebugEnabled()) { logger.debug("Added URL pattern: " + pattern + "; attributes: " + attr + (method == null ? "" : " for HTTP method '" + method + "'")); } } /** * Return the HTTP method specific request map, creating it if it doesn't already exist. * @param method GET, POST etc * @return map of URL patterns to ConfigAttributeDefinitions for this method. */ private Map getRequestMapForHttpMethod(String method) { if (method == null) { return requestMap; } if (!HTTP_METHODS.contains(method)) { throw new IllegalArgumentException("Unrecognised HTTP method: '" + method + "'"); } Map methodRequestmap = (Map) httpMethodMap.get(method); if (methodRequestmap == null) { methodRequestmap = new LinkedHashMap(); httpMethodMap.put(method, methodRequestmap); } return methodRequestmap; } public Collection getConfigAttributeDefinitions() { return Collections.unmodifiableCollection(getRequestMap().values()); } public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { if ((object == null) || !this.supports(object.getClass())) { throw new IllegalArgumentException("Object must be a FilterInvocation"); } String url = ((FilterInvocation) object).getRequestUrl(); String method = ((FilterInvocation) object).getHttpRequest().getMethod(); return lookupAttributes(url, method); } protected ConfigAttributeDefinition lookupAttributes(String url) { return lookupAttributes(url, null); } /** * Performs the actual lookup of the relevant ConfigAttributeDefinition for the specified * FilterInvocation. *

    * By default, iterates through the stored URL map and calls the * {@link UrlMatcher#pathMatchesUrl(Object path, String url)} method until a match is found. *

    * Subclasses can override if required to perform any modifications to the URL. * * @param url the URI to retrieve configuration attributes for * @param method the HTTP method (GET, POST, DELETE...). * * @return the ConfigAttributeDefinition that applies to the specified FilterInvocation * or null if no match is foud */ public ConfigAttributeDefinition lookupAttributes(String url, String method) { if (stripQueryStringFromUrls) { // Strip anything after a question mark symbol, as per SEC-161. See also SEC-321 int firstQuestionMarkIndex = url.indexOf("?"); if (firstQuestionMarkIndex != -1) { url = url.substring(0, firstQuestionMarkIndex); } } if (urlMatcher.requiresLowerCaseUrl()) { url = url.toLowerCase(); if (logger.isDebugEnabled()) { logger.debug("Converted URL to lowercase, from: '" + url + "'; to: '" + url + "'"); } } ConfigAttributeDefinition attributes = null; Map methodSpecificMap = (Map) httpMethodMap.get(method); if (methodSpecificMap != null) { attributes = lookupUrlInMap(methodSpecificMap, url); } if (attributes == null) { attributes = lookupUrlInMap(requestMap, url); } return attributes; } private ConfigAttributeDefinition lookupUrlInMap(Map requestMap, String url) { Iterator entries = requestMap.entrySet().iterator(); while (entries.hasNext()) { Map.Entry entry = (Map.Entry) entries.next(); Object p = entry.getKey(); boolean matched = urlMatcher.pathMatchesUrl(p, url); if (logger.isDebugEnabled()) { logger.debug("Candidate is: '" + url + "'; pattern is " + p + "; matched=" + matched); } if (matched) { return (ConfigAttributeDefinition) entry.getValue(); } } return null; } public boolean supports(Class clazz) { return FilterInvocation.class.isAssignableFrom(clazz); } public int getMapSize() { return this.requestMap.size(); } Map getRequestMap() { return requestMap; } protected UrlMatcher getUrlMatcher() { return urlMatcher; } public boolean isConvertUrlToLowercaseBeforeComparison() { return urlMatcher.requiresLowerCaseUrl(); } public void setStripQueryStringFromUrls(boolean stripQueryStringFromUrls) { this.stripQueryStringFromUrls = stripQueryStringFromUrls; } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/RequestKey.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/R0000644000000000000000000000241511623517156030461 0ustar package org.springframework.security.intercept.web; /** * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class RequestKey { private String url; private String method; public RequestKey(String url) { this(url, null); } public RequestKey(String url, String method) { this.url = url; this.method = method; } String getUrl() { return url; } String getMethod() { return method; } public int hashCode() { int code = 31; code ^= url.hashCode(); if (method != null) { code ^= method.hashCode(); } return code; } public boolean equals(Object obj) { if (!(obj instanceof RequestKey)) { return false; } RequestKey key = (RequestKey) obj; if (!url.equals(key.url)) { return false; } if (method == null) { return key.method == null; } return method.equals(key.method); } public String toString() { StringBuffer sb = new StringBuffer(url.length() + 7); sb.append("["); if (method != null) { sb.append(method).append(","); } sb.append(url); sb.append("]"); return sb.toString(); } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/FilterSecurityInterceptor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/F0000644000000000000000000001313511623517156030446 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.web; import org.springframework.security.intercept.AbstractSecurityInterceptor; import org.springframework.security.intercept.InterceptorStatusToken; import org.springframework.security.intercept.ObjectDefinitionSource; import org.springframework.security.ui.FilterChainOrder; import org.springframework.core.Ordered; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Performs security handling of HTTP resources via a filter implementation.

    The * ObjectDefinitionSource required by this security interceptor is of type {@link * FilterInvocationDefinitionSource}.

    *

    Refer to {@link AbstractSecurityInterceptor} for details on the workflow.

    * * @author Ben Alex * @version $Id$ */ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter, Ordered { //~ Static fields/initializers ===================================================================================== private static final String FILTER_APPLIED = "__spring_security_filterSecurityInterceptor_filterApplied"; //~ Instance fields ================================================================================================ private FilterInvocationDefinitionSource objectDefinitionSource; private boolean observeOncePerRequest = true; //~ Methods ======================================================================================================== /** * Not used (we rely on IoC container lifecycle services instead) * * @param arg0 ignored * * @throws ServletException never thrown */ public void init(FilterConfig arg0) throws ServletException {} /** * Not used (we rely on IoC container lifecycle services instead) */ public void destroy() {} /** * Method that is actually called by the filter chain. Simply delegates to the {@link * #invoke(FilterInvocation)} method. * * @param request the servlet request * @param response the servlet response * @param chain the filter chain * * @throws IOException if the filter chain fails * @throws ServletException if the filter chain fails */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); } public FilterInvocationDefinitionSource getObjectDefinitionSource() { return this.objectDefinitionSource; } public Class getSecureObjectClass() { return FilterInvocation.class; } public void invoke(FilterInvocation fi) throws IOException, ServletException { if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null) && observeOncePerRequest) { // filter already applied to this request and user wants us to observce // once-per-request handling, so don't re-do security checking fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } else { // first time this request being called, so perform security checking if (fi.getRequest() != null) { fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE); } InterceptorStatusToken token = super.beforeInvocation(fi); try { fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.afterInvocation(token, null); } } } /** * Indicates whether once-per-request handling will be observed. By default this is true, * meaning the FilterSecurityInterceptor will only execute once-per-request. Sometimes users may wish * it to execute more than once per request, such as when JSP forwards are being used and filter security is * desired on each included fragment of the HTTP request. * * @return true (the default) if once-per-request is honoured, otherwise false if * FilterSecurityInterceptor will enforce authorizations for each and every fragment of the * HTTP request. */ public boolean isObserveOncePerRequest() { return observeOncePerRequest; } public ObjectDefinitionSource obtainObjectDefinitionSource() { return this.objectDefinitionSource; } public void setObjectDefinitionSource(FilterInvocationDefinitionSource newSource) { this.objectDefinitionSource = newSource; } public void setObserveOncePerRequest(boolean observeOncePerRequest) { this.observeOncePerRequest = observeOncePerRequest; } public int getOrder() { return FilterChainOrder.FILTER_SECURITY_INTERCEPTOR; } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/FilterInvocationDefinitionSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/F0000644000000000000000000000201011623517156030434 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.web; import org.springframework.security.intercept.ObjectDefinitionSource; /** * Marker interface for ObjectDefinitionSource implementations * that are designed to perform lookups keyed on {@link FilterInvocation}s. * * @author Ben Alex * @version $Id$ */ public interface FilterInvocationDefinitionSource extends ObjectDefinitionSource {} ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/WebInvocationPrivilegeEvaluator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/web/W0000644000000000000000000000676111623517156030476 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept.web; import org.springframework.security.AccessDeniedException; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.AbstractSecurityInterceptor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Allows users to determine whether they have privileges for a given web URI. * * @author Ben Alex * @version $Id$ */ public class WebInvocationPrivilegeEvaluator implements InitializingBean { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(WebInvocationPrivilegeEvaluator.class); //~ Instance fields ================================================================================================ private AbstractSecurityInterceptor securityInterceptor; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(securityInterceptor, "SecurityInterceptor required"); } public boolean isAllowed(FilterInvocation fi, Authentication authentication) { Assert.notNull(fi, "FilterInvocation required"); ConfigAttributeDefinition attrs = securityInterceptor.obtainObjectDefinitionSource().getAttributes(fi); if (attrs == null) { if (securityInterceptor.isRejectPublicInvocations()) { return false; } return true; } if ((authentication == null) || (authentication.getAuthorities() == null) || (authentication.getAuthorities().length == 0)) { return false; } try { securityInterceptor.getAccessDecisionManager().decide(authentication, fi, attrs); } catch (AccessDeniedException unauthorized) { if (logger.isDebugEnabled()) { logger.debug(fi.toString() + " denied for " + authentication.toString(), unauthorized); } return false; } return true; } public void setSecurityInterceptor(AbstractSecurityInterceptor securityInterceptor) { Assert.notNull(securityInterceptor, "AbstractSecurityInterceptor cannot be null"); Assert.isTrue(FilterInvocation.class.equals(securityInterceptor.getSecureObjectClass()), "AbstractSecurityInterceptor does not support FilterInvocations"); Assert.notNull(securityInterceptor.getAccessDecisionManager(), "AbstractSecurityInterceptor must provide a non-null AccessDecisionManager"); this.securityInterceptor = securityInterceptor; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/ObjectDefinitionSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/Objec0000644000000000000000000000502511623517156030525 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept; import org.springframework.security.ConfigAttributeDefinition; import java.util.Collection; /** * Implemented by classes that store and can identify the {@link * ConfigAttributeDefinition} that applies to a given secure object * invocation. * * @author Ben Alex * @version $Id$ */ public interface ObjectDefinitionSource { //~ Methods ======================================================================================================== /** * Accesses the ConfigAttributeDefinition that applies to a given secure object.

    Returns * null if no ConfigAttribiteDefinition applies.

    * * @param object the object being secured * * @return the ConfigAttributeDefinition that applies to the passed object * * @throws IllegalArgumentException if the passed object is not of a type supported by the * ObjectDefinitionSource implementation */ ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException; /** * If available, returns all of the ConfigAttributeDefinitions defined by the implementing class. *

    * This is used by the {@link AbstractSecurityInterceptor} to perform startup time validation of each * ConfigAttribute configured against it. * * @return the ConfigAttributeDefinitions or null if unsupported */ Collection getConfigAttributeDefinitions(); /** * Indicates whether the ObjectDefinitionSource implementation is able to provide * ConfigAttributeDefinitions for the indicated secure object type. * * @param clazz the class that is being queried * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/AbstractSecurityInterceptor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/Abstr0000644000000000000000000005113011623520776030556 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept; import org.springframework.security.AccessDecisionManager; import org.springframework.security.AccessDeniedException; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.AfterInvocationManager; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationCredentialsNotFoundException; import org.springframework.security.AuthenticationManager; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.RunAsManager; import org.springframework.security.context.SecurityContext; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.context.SecurityContextImpl; import org.springframework.security.event.authorization.AuthenticationCredentialsNotFoundEvent; import org.springframework.security.event.authorization.AuthorizationFailureEvent; import org.springframework.security.event.authorization.AuthorizedEvent; import org.springframework.security.event.authorization.PublicInvocationEvent; import org.springframework.security.runas.NullRunAsManager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.Collection; /** * Abstract class that implements security interception for secure objects. *

    * The AbstractSecurityInterceptor will ensure the proper startup configuration of the security * interceptor. It will also implement the proper handling of secure object invocations, namely: *

      *
    1. Obtain the {@link Authentication} object from the {@link SecurityContextHolder}.
    2. *
    3. Determine if the request relates to a secured or public invocation by looking up the secure object request * against the {@link ObjectDefinitionSource}.
    4. *
    5. For an invocation that is secured (there is a * ConfigAttributeDefinition for the secure object invocation): *
        *
      1. If either the {@link org.springframework.security.Authentication#isAuthenticated()} * returns false, or the {@link #alwaysReauthenticate} is * true, authenticate the request against the configured {@link AuthenticationManager}. * When authenticated, replace the Authentication object on the * SecurityContextHolder with the returned value.
      2. *
      3. Authorize the request against the configured {@link AccessDecisionManager}.
      4. *
      5. Perform any run-as replacement via the configured {@link RunAsManager}.
      6. *
      7. Pass control back to the concrete subclass, which will actually proceed with executing the object. * A {@link InterceptorStatusToken} is returned so that after the subclass has finished proceeding with * execution of the object, its finally clause can ensure the AbstractSecurityInterceptor * is re-called and tidies up correctly.
      8. *
      9. The concrete subclass will re-call the AbstractSecurityInterceptor via the * {@link #afterInvocation(InterceptorStatusToken, Object)} method.
      10. *
      11. If the RunAsManager replaced the Authentication object, return the * SecurityContextHolder to the object that existed after the call to * AuthenticationManager.
      12. *
      13. If an AfterInvocationManager is defined, invoke the * invocation manager and allow it to replace the object due to be returned to * the caller.
      14. *
      *
    6. *
    7. For an invocation that is public (there is no ConfigAttributeDefinition for the secure object * invocation): *
        *
      1. As described above, the concrete subclass will be returned an InterceptorStatusToken which is * subsequently re-presented to the AbstractSecurityInterceptor after the secure object has been executed. * The AbstractSecurityInterceptor will take no further action when its * {@link #afterInvocation(InterceptorStatusToken, Object)} is called.
      2. *
      *
    8. *
    9. Control again returns to the concrete subclass, along with the Object that should be returned to * the caller. The subclass will then return that result or exception to the original caller.
    10. *
    * * @author Ben Alex * @version $Id$ */ public abstract class AbstractSecurityInterceptor implements InitializingBean, ApplicationEventPublisherAware, MessageSourceAware { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(AbstractSecurityInterceptor.class); //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private ApplicationEventPublisher eventPublisher; private AccessDecisionManager accessDecisionManager; private AfterInvocationManager afterInvocationManager; private AuthenticationManager authenticationManager; private RunAsManager runAsManager = new NullRunAsManager(); private boolean alwaysReauthenticate = false; private boolean rejectPublicInvocations = false; private boolean validateConfigAttributes = true; //~ Methods ======================================================================================================== /** * Completes the work of the AbstractSecurityInterceptor after the secure object invocation has been * completed. * * @param token as returned by the {@link #beforeInvocation(Object)}} method * @param returnedObject any object returned from the secure object invocation (may be null) * @return the object the secure object invocation should ultimately return to its caller (may be null) */ protected Object afterInvocation(InterceptorStatusToken token, Object returnedObject) { if (token == null) { // public object return returnedObject; } if (token.isContextHolderRefreshRequired()) { if (logger.isDebugEnabled()) { logger.debug("Reverting to original Authentication: " + token.getSecurityContext().getAuthentication()); } SecurityContextHolder.setContext(token.getSecurityContext()); } if (afterInvocationManager != null) { // Attempt after invocation handling try { returnedObject = afterInvocationManager.decide(token.getSecurityContext().getAuthentication(), token.getSecureObject(), token.getAttr(), returnedObject); } catch (AccessDeniedException accessDeniedException) { AuthorizationFailureEvent event = new AuthorizationFailureEvent(token.getSecureObject(), token .getAttr(), token.getSecurityContext().getAuthentication(), accessDeniedException); publishEvent(event); throw accessDeniedException; } } return returnedObject; } public void afterPropertiesSet() throws Exception { Assert.notNull(getSecureObjectClass(), "Subclass must provide a non-null response to getSecureObjectClass()"); Assert.notNull(this.messages, "A message source must be set"); Assert.notNull(this.authenticationManager, "An AuthenticationManager is required"); Assert.notNull(this.accessDecisionManager, "An AccessDecisionManager is required"); Assert.notNull(this.runAsManager, "A RunAsManager is required"); Assert.notNull(this.obtainObjectDefinitionSource(), "An ObjectDefinitionSource is required"); Assert.isTrue(this.obtainObjectDefinitionSource().supports(getSecureObjectClass()), "ObjectDefinitionSource does not support secure object class: " + getSecureObjectClass()); Assert.isTrue(this.runAsManager.supports(getSecureObjectClass()), "RunAsManager does not support secure object class: " + getSecureObjectClass()); Assert.isTrue(this.accessDecisionManager.supports(getSecureObjectClass()), "AccessDecisionManager does not support secure object class: " + getSecureObjectClass()); if (this.afterInvocationManager != null) { Assert.isTrue(this.afterInvocationManager.supports(getSecureObjectClass()), "AfterInvocationManager does not support secure object class: " + getSecureObjectClass()); } if (this.validateConfigAttributes) { Collection attributeDefs = this.obtainObjectDefinitionSource().getConfigAttributeDefinitions(); if (attributeDefs == null) { logger.warn("Could not validate configuration attributes as the ObjectDefinitionSource did not return " + "a ConfigAttributeDefinition collection"); return; } Iterator iter = attributeDefs.iterator(); Set unsupportedAttrs = new HashSet(); while (iter.hasNext()) { ConfigAttributeDefinition def = (ConfigAttributeDefinition) iter.next(); Iterator attributes = def.getConfigAttributes().iterator(); while (attributes.hasNext()) { ConfigAttribute attr = (ConfigAttribute) attributes.next(); if (!this.runAsManager.supports(attr) && !this.accessDecisionManager.supports(attr) && ((this.afterInvocationManager == null) || !this.afterInvocationManager.supports(attr))) { unsupportedAttrs.add(attr); } } } if (unsupportedAttrs.size() != 0) { throw new IllegalArgumentException("Unsupported configuration attributes: " + unsupportedAttrs); } logger.info("Validated configuration attributes"); } } protected InterceptorStatusToken beforeInvocation(Object object) { Assert.notNull(object, "Object was null"); if (!getSecureObjectClass().isAssignableFrom(object.getClass())) { throw new IllegalArgumentException("Security invocation attempted for object " + object.getClass().getName() + " but AbstractSecurityInterceptor only configured to support secure objects of type: " + getSecureObjectClass()); } ConfigAttributeDefinition attr = this.obtainObjectDefinitionSource().getAttributes(object); if (attr == null) { if (rejectPublicInvocations) { throw new IllegalArgumentException( "No public invocations are allowed via this AbstractSecurityInterceptor. " + "This indicates a configuration error because the " + "AbstractSecurityInterceptor.rejectPublicInvocations property is set to 'true'"); } if (logger.isDebugEnabled()) { logger.debug("Public object - authentication not attempted"); } publishEvent(new PublicInvocationEvent(object)); return null; // no further work post-invocation } if (logger.isDebugEnabled()) { logger.debug("Secure object: " + object + "; ConfigAttributes: " + attr); } if (SecurityContextHolder.getContext().getAuthentication() == null) { credentialsNotFound(messages.getMessage("AbstractSecurityInterceptor.authenticationNotFound", "An Authentication object was not found in the SecurityContext"), object, attr); } Authentication authenticated = authenticateIfRequired(); // Attempt authorization try { this.accessDecisionManager.decide(authenticated, object, attr); } catch (AccessDeniedException accessDeniedException) { AuthorizationFailureEvent event = new AuthorizationFailureEvent(object, attr, authenticated, accessDeniedException); publishEvent(event); throw accessDeniedException; } if (logger.isDebugEnabled()) { logger.debug("Authorization successful"); } AuthorizedEvent event = new AuthorizedEvent(object, attr, authenticated); publishEvent(event); // Attempt to run as a different user Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attr); if (runAs == null) { if (logger.isDebugEnabled()) { logger.debug("RunAsManager did not change Authentication object"); } // no further work post-invocation return new InterceptorStatusToken(SecurityContextHolder.getContext(), false, attr, object); } else { if (logger.isDebugEnabled()) { logger.debug("Switching to RunAs Authentication: " + runAs); } SecurityContext originalContext = SecurityContextHolder.getContext(); SecurityContext runAsContext = new SecurityContextImpl(); runAsContext.setAuthentication(runAs); SecurityContextHolder.setContext(runAsContext); // revert to original context post-invocation return new InterceptorStatusToken(originalContext, true, attr, object); } } /** * Checks the current authentication token and passes it to the AuthenticationManager if * {@link org.springframework.security.Authentication#isAuthenticated()} returns false or the property * alwaysReauthenticate has been set to true. * * @return an authenticated Authentication object. */ private Authentication authenticateIfRequired() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication.isAuthenticated() && !alwaysReauthenticate) { if (logger.isDebugEnabled()) { logger.debug("Previously Authenticated: " + authentication); } return authentication; } authentication = authenticationManager.authenticate(authentication); // We don't authenticated.setAuthentication(true), because each provider should do that if (logger.isDebugEnabled()) { logger.debug("Successfully Authenticated: " + authentication); } SecurityContextHolder.getContext().setAuthentication(authentication); return authentication; } /** * Helper method which generates an exception containing the passed reason, * and publishes an event to the application context. *

    * Always throws an exception. * * @param reason to be provided in the exception detail * @param secureObject that was being called * @param configAttribs that were defined for the secureObject */ private void credentialsNotFound(String reason, Object secureObject, ConfigAttributeDefinition configAttribs) { AuthenticationCredentialsNotFoundException exception = new AuthenticationCredentialsNotFoundException(reason); AuthenticationCredentialsNotFoundEvent event = new AuthenticationCredentialsNotFoundEvent(secureObject, configAttribs, exception); publishEvent(event); throw exception; } public AccessDecisionManager getAccessDecisionManager() { return accessDecisionManager; } public AfterInvocationManager getAfterInvocationManager() { return afterInvocationManager; } public AuthenticationManager getAuthenticationManager() { return this.authenticationManager; } public RunAsManager getRunAsManager() { return runAsManager; } /** * Indicates the type of secure objects the subclass will be presenting to * the abstract parent for processing. This is used to ensure collaborators * wired to the AbstractSecurityInterceptor all support the * indicated secure object class. * * @return the type of secure object the subclass provides services for */ public abstract Class getSecureObjectClass(); public boolean isAlwaysReauthenticate() { return alwaysReauthenticate; } public boolean isRejectPublicInvocations() { return rejectPublicInvocations; } public boolean isValidateConfigAttributes() { return validateConfigAttributes; } public abstract ObjectDefinitionSource obtainObjectDefinitionSource(); public void setAccessDecisionManager(AccessDecisionManager accessDecisionManager) { this.accessDecisionManager = accessDecisionManager; } public void setAfterInvocationManager(AfterInvocationManager afterInvocationManager) { this.afterInvocationManager = afterInvocationManager; } /** * Indicates whether the AbstractSecurityInterceptor should * ignore the {@link Authentication#isAuthenticated()} property. Defaults to * false, meaning by default the * Authentication.isAuthenticated() property is trusted and * re-authentication will not occur if the principal has already been * authenticated. * * @param alwaysReauthenticate true to force AbstractSecurityInterceptor to * disregard the value of Authentication.isAuthenticated() and always re-authenticate the request * (defaults to false). */ public void setAlwaysReauthenticate(boolean alwaysReauthenticate) { this.alwaysReauthenticate = alwaysReauthenticate; } public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.eventPublisher = applicationEventPublisher; } public void setAuthenticationManager(AuthenticationManager newManager) { this.authenticationManager = newManager; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } /** * By rejecting public invocations (and setting this property to true), essentially you are ensuring * that every secure object invocation advised by AbstractSecurityInterceptor has a configuration * attribute defined. This is useful to ensure a "fail safe" mode where undeclared secure objects will be rejected * and configuration omissions detected early. An IllegalArgumentException will be thrown by the * AbstractSecurityInterceptor if you set this property to true and an attempt is made to invoke * a secure object that has no configuration attributes. * * @param rejectPublicInvocations set to true to reject invocations of secure objects that have no * configuration attributes (by default it is false which treats undeclared secure objects * as "public" or unauthorized). */ public void setRejectPublicInvocations(boolean rejectPublicInvocations) { this.rejectPublicInvocations = rejectPublicInvocations; } public void setRunAsManager(RunAsManager runAsManager) { this.runAsManager = runAsManager; } public void setValidateConfigAttributes(boolean validateConfigAttributes) { this.validateConfigAttributes = validateConfigAttributes; } private void publishEvent(ApplicationEvent event) { if (this.eventPublisher != null) { this.eventPublisher.publishEvent(event); } } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/InterceptorStatusToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/intercept/Inter0000644000000000000000000000465211623520776030573 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.intercept; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.context.SecurityContext; /** * A return object received by {@link AbstractSecurityInterceptor} subclasses. *

    * This class reflects the status of the security interception, so that the final call to * {@link org.springframework.security.intercept.AbstractSecurityInterceptor#afterInvocation(InterceptorStatusToken, Object)} * can tidy up correctly. * * @author Ben Alex * @version $Id$ */ public class InterceptorStatusToken { //~ Instance fields ================================================================================================ private SecurityContext context; private ConfigAttributeDefinition attr; private Object secureObject; private boolean contextHolderRefreshRequired; //~ Constructors =================================================================================================== public InterceptorStatusToken(SecurityContext context, boolean contextHolderRefreshRequired, ConfigAttributeDefinition attr, Object secureObject) { this.context = context; this.contextHolderRefreshRequired = contextHolderRefreshRequired; this.attr = attr; this.secureObject = secureObject; } //~ Methods ======================================================================================================== public ConfigAttributeDefinition getAttr() { return attr; } public SecurityContext getSecurityContext() { return context; } public Object getSecureObject() { return secureObject; } public boolean isContextHolderRefreshRequired() { return contextHolderRefreshRequired; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AccessDecisionManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AccessDecisionM0000644000000000000000000000545311623517156030507 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Makes a final access control (authorization) decision. * * @author Ben Alex * @version $Id$ */ public interface AccessDecisionManager { //~ Methods ======================================================================================================== /** * Resolves an access control decision for the passed parameters. * * @param authentication the caller invoking the method * @param object the secured object being called * @param config the configuration attributes associated with the secured object being invoked * * @throws AccessDeniedException if access is denied as the authentication does not hold a required authority or * ACL privilege * @throws InsufficientAuthenticationException if access is denied as the authentication does not provide a * sufficient level of trust */ void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException, InsufficientAuthenticationException; /** * Indicates whether this AccessDecisionManager is able to process authorization requests * presented with the passed ConfigAttribute.

    This allows the * AbstractSecurityInterceptor to check every configuration attribute can be consumed by the * configured AccessDecisionManager and/or RunAsManager and/or * AfterInvocationManager.

    * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor * * @return true if this AccessDecisionManager can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); /** * Indicates whether the AccessDecisionManager implementation is able to provide access * control decisions for the indicated secured object type. * * @param clazz the class that is being queried * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/RunAsManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/RunAsManager.ja0000644000000000000000000001072311623517156030423 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Creates a new temporary {@link Authentication} object for the current secure * object invocation only. * *

    * This interface permits implementations to replace the * Authentication object that applies to the current secure * object invocation only. The {@link * org.springframework.security.intercept.AbstractSecurityInterceptor} will replace * the Authentication object held in the * {@link org.springframework.security.context.SecurityContext SecurityContext} * for the duration of the secure object callback only, returning it to * the original Authentication object when the callback ends. *

    * *

    * This is provided so that systems with two layers of objects can be * established. One layer is public facing and has normal secure methods with * the granted authorities expected to be held by external callers. The other * layer is private, and is only expected to be called by objects within the * public facing layer. The objects in this private layer still need security * (otherwise they would be public methods) and they also need security in * such a manner that prevents them being called directly by external callers. * The objects in the private layer would be configured to require granted * authorities never granted to external callers. The * RunAsManager interface provides a mechanism to elevate * security in this manner. *

    * *

    * It is expected implementations will provide a corresponding concrete * Authentication and AuthenticationProvider so that * the replacement Authentication object can be authenticated. * Some form of security will need to be implemented to ensure the * AuthenticationProvider only accepts * Authentication objects created by an authorized concrete * implementation of RunAsManager. *

    * * @author Ben Alex * @version $Id$ */ public interface RunAsManager { //~ Methods ======================================================================================================== /** * Returns a replacement Authentication object for the current secure object invocation, or * null if replacement not required. * * @param authentication the caller invoking the secure object * @param object the secured object being called * @param config the configuration attributes associated with the secure object being invoked * * @return a replacement object to be used for duration of the secure object invocation, or null if * the Authentication should be left as is */ Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config); /** * Indicates whether this RunAsManager is able to process the passed * ConfigAttribute.

    This allows the AbstractSecurityInterceptor to check every * configuration attribute can be consumed by the configured AccessDecisionManager and/or * RunAsManager and/or AfterInvocationManager.

    * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor * * @return true if this RunAsManager can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); /** * Indicates whether the RunAsManager implementation is able to provide run-as replacement for * the indicated secure object type. * * @param clazz the class that is being queried * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthenticationServiceException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthenticationS0000644000000000000000000000312311623517156030605 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Thrown if an authentication request could not be processed due to a system problem.

    This might be thrown if a * backend authentication repository is unavailable.

    * * @author Ben Alex * @version $Id$ */ public class AuthenticationServiceException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs an AuthenticationServiceException with the * specified message. * * @param msg the detail message */ public AuthenticationServiceException(String msg) { super(msg); } /** * Constructs an AuthenticationServiceException with the * specified message and root cause. * * @param msg the detail message * @param t root cause */ public AuthenticationServiceException(String msg, Throwable t) { super(msg, t); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/0000755000000000000000000000000011623517156027576 5ustar ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rememberme/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/remem0000755000000000000000000000000011623517156030624 5ustar ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rememberme/RememberMeAuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/remem0000644000000000000000000000673111623517156030635 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.rememberme; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.BadCredentialsException; import org.springframework.security.providers.AuthenticationProvider; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that validates {@link * org.springframework.security.providers.rememberme.RememberMeAuthenticationToken}s.

    To be successfully validated, the * {@link org.springframework.security.providers.rememberme.RememberMeAuthenticationToken#getKeyHash()} must match this class' * {@link #getKey()}.

    */ public class RememberMeAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(RememberMeAuthenticationProvider.class); //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private String key; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(key); Assert.notNull(this.messages, "A message source must be set"); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } if (this.key.hashCode() != ((RememberMeAuthenticationToken) authentication).getKeyHash()) { throw new BadCredentialsException(messages.getMessage("RememberMeAuthenticationProvider.incorrectKey", "The presented RememberMeAuthenticationToken does not contain the expected key")); } return authentication; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public boolean supports(Class authentication) { return (RememberMeAuthenticationToken.class.isAssignableFrom(authentication)); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rememberme/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/remem0000644000000000000000000000016211623517156030625 0ustar Authentication provider that processes RememberMeAuthenticationTokens. ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rememberme/RememberMeAuthenticationToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/remem0000644000000000000000000000622611623517156030634 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.rememberme; import java.io.Serializable; import org.springframework.security.GrantedAuthority; import org.springframework.security.providers.AbstractAuthenticationToken; /** * Represents a remembered Authentication.

    A remembered Authentication must provide a * fully valid Authentication, including the GrantedAuthority[]s that apply.

    * * @author Ben Alex * @version $Id$ */ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken implements Serializable { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Object principal; private int keyHash; //~ Constructors =================================================================================================== /** * Constructor. * * @param key to identify if this object made by an authorised client * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal * * @throws IllegalArgumentException if a null was passed */ public RememberMeAuthenticationToken(String key, Object principal, GrantedAuthority[] authorities) { super(authorities); if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal)) { throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } this.keyHash = key.hashCode(); this.principal = principal; setAuthenticated(true); } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } if (obj instanceof RememberMeAuthenticationToken) { RememberMeAuthenticationToken test = (RememberMeAuthenticationToken) obj; if (this.getKeyHash() != test.getKeyHash()) { return false; } return true; } return false; } /** * Always returns an empty String * * @return an empty String */ public Object getCredentials() { return ""; } public int getKeyHash() { return this.keyHash; } public Object getPrincipal() { return this.principal; } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ProviderNotFoundException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/Provi0000644000000000000000000000321111623517156030615 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers; import org.springframework.security.AuthenticationException; /** * Thrown by {@link ProviderManager} if no {@link AuthenticationProvider} could be found that supports the * presented {@link org.springframework.security.Authentication} object. * * @author Ben Alex * @version $Id$ */ public class ProviderNotFoundException extends AuthenticationException { //~ Constructors =================================================================================================== /** * Constructs a ProviderNotFoundException with the specified * message. * * @param msg the detail message */ public ProviderNotFoundException(String msg) { super(msg); } /** * Constructs a ProviderNotFoundException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public ProviderNotFoundException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/anonymous/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/anony0000755000000000000000000000000011623517156030643 5ustar ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/anonymous/AnonymousAuthenticationToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/anony0000644000000000000000000000605211623517156030650 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.anonymous; import org.springframework.security.GrantedAuthority; import org.springframework.security.providers.AbstractAuthenticationToken; import java.io.Serializable; /** * Represents an anonymous Authentication. * * @author Ben Alex * @version $Id$ */ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken implements Serializable { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Object principal; private int keyHash; //~ Constructors =================================================================================================== /** * Constructor. * * @param key to identify if this object made by an authorised client * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal * * @throws IllegalArgumentException if a null was passed */ public AnonymousAuthenticationToken(String key, Object principal, GrantedAuthority[] authorities) { super(authorities); if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal) || (authorities == null) || (authorities.length == 0)) { throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } this.keyHash = key.hashCode(); this.principal = principal; setAuthenticated(true); } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } if (obj instanceof AnonymousAuthenticationToken) { AnonymousAuthenticationToken test = (AnonymousAuthenticationToken) obj; if (this.getKeyHash() != test.getKeyHash()) { return false; } return true; } return false; } /** * Always returns an empty String * * @return an empty String */ public Object getCredentials() { return ""; } public int getKeyHash() { return this.keyHash; } public Object getPrincipal() { return this.principal; } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/anonymous/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/anony0000644000000000000000000000031211623517156030641 0ustar Allows you to secure every invocation (especially useful for web request URI security) by always having either an actual principal or an anonymous principal authenticated. ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/anonymous/AnonymousProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/anony0000644000000000000000000001440111623517156030645 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.anonymous; import org.springframework.security.Authentication; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.ui.AuthenticationDetailsSource; import org.springframework.security.ui.WebAuthenticationDetailsSource; import org.springframework.security.ui.FilterChainOrder; import org.springframework.security.ui.SpringSecurityFilter; import org.springframework.security.userdetails.memory.UserAttribute; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Detects if there is no Authentication object in the SecurityContextHolder, and * populates it with one if needed. * * @author Ben Alex * @version $Id$ */ public class AnonymousProcessingFilter extends SpringSecurityFilter implements InitializingBean { //~ Instance fields ================================================================================================ private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); private String key; private UserAttribute userAttribute; private boolean removeAfterRequest = true; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(userAttribute); Assert.hasLength(key); } /** * Enables subclasses to determine whether or not an anonymous authentication token should be setup for * this request. This is useful if anonymous authentication should be allowed only for specific IP subnet ranges * etc. * * @param request to assist the method determine request details * * @return true if the anonymous token should be setup for this request (provided that the request * doesn't already have some other Authentication inside it), or false if no * anonymous token should be setup for this request */ protected boolean applyAnonymousForThisRequest(HttpServletRequest request) { return true; } protected Authentication createAuthentication(HttpServletRequest request) { AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(key, userAttribute.getPassword(), userAttribute.getAuthorities()); auth.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request)); return auth; } protected void doFilterHttp(HttpServletRequest request,HttpServletResponse response, FilterChain chain) throws IOException, ServletException { boolean addedToken = false; if (applyAnonymousForThisRequest(request)) { if (SecurityContextHolder.getContext().getAuthentication() == null) { SecurityContextHolder.getContext().setAuthentication(createAuthentication(request)); addedToken = true; if (logger.isDebugEnabled()) { logger.debug("Populated SecurityContextHolder with anonymous token: '" + SecurityContextHolder.getContext().getAuthentication() + "'"); } } else { if (logger.isDebugEnabled()) { logger.debug("SecurityContextHolder not populated with anonymous token, as it already contained: '" + SecurityContextHolder.getContext().getAuthentication() + "'"); } } } try { chain.doFilter(request, response); } finally { if (addedToken && removeAfterRequest && createAuthentication(request).equals(SecurityContextHolder.getContext().getAuthentication())) { SecurityContextHolder.getContext().setAuthentication(null); } } } public int getOrder() { return FilterChainOrder.ANONYMOUS_FILTER; } public String getKey() { return key; } public UserAttribute getUserAttribute() { return userAttribute; } public boolean isRemoveAfterRequest() { return removeAfterRequest; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } public void setKey(String key) { this.key = key; } /** * Controls whether the filter will remove the Anonymous token after the request is complete. Generally * this is desired to avoid the expense of a session being created by {@link * org.springframework.security.context.HttpSessionContextIntegrationFilter HttpSessionContextIntegrationFilter} simply to * store the Anonymous authentication token.

    Defaults to true, being the most optimal and * appropriate option (ie AnonymousProcessingFilter will clear the token at the end of each request, * thus avoiding the session creation overhead in a typical configuration.

    * * @param removeAfterRequest DOCUMENT ME! */ public void setRemoveAfterRequest(boolean removeAfterRequest) { this.removeAfterRequest = removeAfterRequest; } public void setUserAttribute(UserAttribute userAttributeDefinition) { this.userAttribute = userAttributeDefinition; } } ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/anonymous/AnonymousAuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/anony0000644000000000000000000000616611623517156030656 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.anonymous; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.BadCredentialsException; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.providers.AuthenticationProvider; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that validates {@link AnonymousAuthenticationToken}s. *

    * To be successfully validated, the {@link AnonymousAuthenticationToken#getKeyHash()} must match this class' * {@link #getKey()}. * * @author Ben Alex * @version $Id$ */ public class AnonymousAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private String key; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(key, "A Key is required"); Assert.notNull(this.messages, "A message source must be set"); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } if (this.key.hashCode() != ((AnonymousAuthenticationToken) authentication).getKeyHash()) { throw new BadCredentialsException(messages.getMessage("AnonymousAuthenticationProvider.incorrectKey", "The presented AnonymousAuthenticationToken does not contain the expected key")); } return authentication; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public boolean supports(Class authentication) { return (AnonymousAuthenticationToken.class.isAssignableFrom(authentication)); } } ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/UsernamePasswordAuthenticationToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/Usern0000644000000000000000000000645411623517156030626 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers; import org.springframework.security.GrantedAuthority; /** * An {@link org.springframework.security.Authentication} implementation that is designed for simple presentation of a * username and password. *

    The principal and credentials should be set with an Object that provides * the respective property via its Object.toString() method. The simplest such Object to use * is String.

    * * @author Ben Alex * @version $Id$ */ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Object credentials; private Object principal; //~ Constructors =================================================================================================== /** * This constructor can be safely used by any code that wishes to create a * UsernamePasswordAuthenticationToken, as the {@link * #isAuthenticated()} will return false. * */ public UsernamePasswordAuthenticationToken(Object principal, Object credentials) { super(null); this.principal = principal; this.credentials = credentials; setAuthenticated(false); } /** * This constructor should only be used by AuthenticationManager or AuthenticationProvider * implementations that are satisfied with producing a trusted (ie {@link #isAuthenticated()} = true) * authentication token. * * @param principal * @param credentials * @param authorities */ public UsernamePasswordAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities) { super(authorities); this.principal = principal; this.credentials = credentials; super.setAuthenticated(true); // must use super, as we override } //~ Methods ======================================================================================================== public Object getCredentials() { return this.credentials; } public Object getPrincipal() { return this.principal; } public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { if (isAuthenticated) { throw new IllegalArgumentException( "Cannot set this token to trusted - use constructor containing GrantedAuthority[]s instead"); } super.setAuthenticated(false); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/0000755000000000000000000000000011623517156030341 5ustar ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/DaoAuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/D0000644000000000000000000001335711623517156030460 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.dao; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationServiceException; import org.springframework.security.BadCredentialsException; import org.springframework.security.providers.AuthenticationProvider; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.providers.encoding.PasswordEncoder; import org.springframework.security.providers.encoding.PlaintextPasswordEncoder; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.dao.DataAccessException; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that retrieves user details * from an {@link UserDetailsService}. * * @author Ben Alex * @version $Id$ */ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { //~ Instance fields ================================================================================================ private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder(); private SaltSource saltSource; private UserDetailsService userDetailsService; private boolean includeDetailsObject = true; //~ Methods ======================================================================================================== protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { Object salt = null; if (this.saltSource != null) { salt = this.saltSource.getSalt(userDetails); } if (authentication.getCredentials() == null) { throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), includeDetailsObject ? userDetails : null); } String presentedPassword = authentication.getCredentials().toString(); if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) { throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), includeDetailsObject ? userDetails : null); } } protected void doAfterPropertiesSet() throws Exception { Assert.notNull(this.userDetailsService, "A UserDetailsService must be set"); } protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { UserDetails loadedUser; try { loadedUser = this.getUserDetailsService().loadUserByUsername(username); } catch (DataAccessException repositoryProblem) { throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem); } if (loadedUser == null) { throw new AuthenticationServiceException( "UserDetailsService returned null, which is an interface contract violation"); } return loadedUser; } /** * Sets the PasswordEncoder instance to be used to encode and validate passwords. * If not set, {@link PlaintextPasswordEncoder} will be used by default. * * @param passwordEncoder The passwordEncoder to use */ public void setPasswordEncoder(PasswordEncoder passwordEncoder) { this.passwordEncoder = passwordEncoder; } protected PasswordEncoder getPasswordEncoder() { return passwordEncoder; } /** * The source of salts to use when decoding passwords. null * is a valid value, meaning the DaoAuthenticationProvider * will present null to the relevant PasswordEncoder. * * @param saltSource to use when attempting to decode passwords via the PasswordEncoder */ public void setSaltSource(SaltSource saltSource) { this.saltSource = saltSource; } protected SaltSource getSaltSource() { return saltSource; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } protected UserDetailsService getUserDetailsService() { return userDetailsService; } protected boolean isIncludeDetailsObject() { return includeDetailsObject; } /** * Determines whether the UserDetails will be included in the extraInformation field of a * thrown BadCredentialsException. Defaults to true, but can be set to false if the exception will be * used with a remoting protocol, for example. * * @deprecated use {@link org.springframework.security.providers.ProviderManager#setClearExtraInformation(boolean)} */ public void setIncludeDetailsObject(boolean includeDetailsObject) { this.includeDetailsObject = includeDetailsObject; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/p0000644000000000000000000000014011623517156030516 0ustar An authentication provider that relies upon a data access object. ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/AbstractUserDetailsAuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/A0000644000000000000000000003703311623517156030452 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.dao; import org.springframework.security.AccountExpiredException; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.BadCredentialsException; import org.springframework.security.CredentialsExpiredException; import org.springframework.security.DisabledException; import org.springframework.security.LockedException; import org.springframework.security.providers.AuthenticationProvider; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.providers.dao.cache.NullUserCache; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.security.userdetails.UserDetailsChecker; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * A base {@link AuthenticationProvider} that allows subclasses to override and work with {@link * org.springframework.security.userdetails.UserDetails} objects. The class is designed to respond to {@link * UsernamePasswordAuthenticationToken} authentication requests. * *

    * Upon successful validation, a UsernamePasswordAuthenticationToken will be created and returned to the * caller. The token will include as its principal either a String representation of the username, or the * {@link UserDetails} that was returned from the authentication repository. Using String is appropriate * if a container adapter is being used, as it expects String representations of the username. * Using UserDetails is appropriate if you require access to additional properties of the authenticated * user, such as email addresses, human-friendly names etc. As container adapters are not recommended to be used, * and UserDetails implementations provide additional flexibility, by default a UserDetails * is returned. To override this * default, set the {@link #setForcePrincipalAsString} to true. *

    * Caching is handled via the UserDetails object being placed in the {@link UserCache}. This * ensures that subsequent requests with the same username can be validated without needing to query the {@link * UserDetailsService}. It should be noted that if a user appears to present an incorrect password, the {@link * UserDetailsService} will be queried to confirm the most up-to-date password was used for comparison.

    * * @author Ben Alex * @version $Id$ */ public abstract class AbstractUserDetailsAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private UserCache userCache = new NullUserCache(); private boolean forcePrincipalAsString = false; protected boolean hideUserNotFoundExceptions = true; private UserDetailsChecker preAuthenticationChecks = new DefaultPreAuthenticationChecks(); private UserDetailsChecker postAuthenticationChecks = new DefaultPostAuthenticationChecks(); //~ Methods ======================================================================================================== /** * Allows subclasses to perform any additional checks of a returned (or cached) UserDetails * for a given authentication request. Generally a subclass will at least compare the {@link * Authentication#getCredentials()} with a {@link UserDetails#getPassword()}. If custom logic is needed to compare * additional properties of UserDetails and/or UsernamePasswordAuthenticationToken, * these should also appear in this method. * * @param userDetails as retrieved from the {@link #retrieveUser(String, UsernamePasswordAuthenticationToken)} or * UserCache * @param authentication the current request that needs to be authenticated * * @throws AuthenticationException AuthenticationException if the credentials could not be validated (generally a * BadCredentialsException, an AuthenticationServiceException) */ protected abstract void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException; public final void afterPropertiesSet() throws Exception { Assert.notNull(this.userCache, "A user cache must be set"); Assert.notNull(this.messages, "A message source must be set"); doAfterPropertiesSet(); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports", "Only UsernamePasswordAuthenticationToken is supported")); // Determine username String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName(); boolean cacheWasUsed = true; UserDetails user = this.userCache.getUserFromCache(username); if (user == null) { cacheWasUsed = false; try { user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); } catch (UsernameNotFoundException notFound) { if (hideUserNotFoundExceptions) { throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } else { throw notFound; } } Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract"); } preAuthenticationChecks.check(user); try { additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } catch (AuthenticationException exception) { if (cacheWasUsed) { // There was a problem, so try again after checking // we're using latest data (ie not from the cache) cacheWasUsed = false; user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } else { throw exception; } } postAuthenticationChecks.check(user); if (!cacheWasUsed) { this.userCache.putUserInCache(user); } Object principalToReturn = user; if (forcePrincipalAsString) { principalToReturn = user.getUsername(); } return createSuccessAuthentication(principalToReturn, authentication, user); } /** * Creates a successful {@link Authentication} object.

    Protected so subclasses can override.

    *

    Subclasses will usually store the original credentials the user supplied (not salted or encoded * passwords) in the returned Authentication object.

    * * @param principal that should be the principal in the returned object (defined by the {@link * #isForcePrincipalAsString()} method) * @param authentication that was presented to the provider for validation * @param user that was loaded by the implementation * * @return the successful authentication token */ protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) { // Ensure we return the original credentials the user supplied, // so subsequent attempts are successful even with encoded passwords. // Also ensure we return the original getDetails(), so that future // authentication events after cache expiry contain the details UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal, authentication.getCredentials(), user.getAuthorities()); result.setDetails(authentication.getDetails()); return result; } protected void doAfterPropertiesSet() throws Exception {} public UserCache getUserCache() { return userCache; } public boolean isForcePrincipalAsString() { return forcePrincipalAsString; } public boolean isHideUserNotFoundExceptions() { return hideUserNotFoundExceptions; } /** * Allows subclasses to actually retrieve the UserDetails from an implementation-specific * location, with the option of throwing an AuthenticationException immediately if the presented * credentials are incorrect (this is especially useful if it is necessary to bind to a resource as the user in * order to obtain or generate a UserDetails).

    Subclasses are not required to perform any * caching, as the AbstractUserDetailsAuthenticationProvider will by default cache the * UserDetails. The caching of UserDetails does present additional complexity as this * means subsequent requests that rely on the cache will need to still have their credentials validated, even if * the correctness of credentials was assured by subclasses adopting a binding-based strategy in this method. * Accordingly it is important that subclasses either disable caching (if they want to ensure that this method is * the only method that is capable of authenticating a request, as no UserDetails will ever be * cached) or ensure subclasses implement {@link #additionalAuthenticationChecks(UserDetails, * UsernamePasswordAuthenticationToken)} to compare the credentials of a cached UserDetails with * subsequent authentication requests.

    *

    Most of the time subclasses will not perform credentials inspection in this method, instead * performing it in {@link #additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken)} so * that code related to credentials validation need not be duplicated across two methods.

    * * @param username The username to retrieve * @param authentication The authentication request, which subclasses may need to perform a binding-based * retrieval of the UserDetails * * @return the user information (never null - instead an exception should the thrown) * * @throws AuthenticationException if the credentials could not be validated (generally a * BadCredentialsException, an AuthenticationServiceException or * UsernameNotFoundException) */ protected abstract UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException; public void setForcePrincipalAsString(boolean forcePrincipalAsString) { this.forcePrincipalAsString = forcePrincipalAsString; } /** * By default the AbstractUserDetailsAuthenticationProvider throws a * BadCredentialsException if a username is not found or the password is incorrect. Setting this * property to false will cause UsernameNotFoundExceptions to be thrown instead for the * former. Note this is considered less secure than throwing BadCredentialsException for both * exceptions. * * @param hideUserNotFoundExceptions set to false if you wish UsernameNotFoundExceptions * to be thrown instead of the non-specific BadCredentialsException (defaults to * true) */ public void setHideUserNotFoundExceptions(boolean hideUserNotFoundExceptions) { this.hideUserNotFoundExceptions = hideUserNotFoundExceptions; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setUserCache(UserCache userCache) { this.userCache = userCache; } public boolean supports(Class authentication) { return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); } protected UserDetailsChecker getPreAuthenticationChecks() { return preAuthenticationChecks; } /** * Sets the policy will be used to verify the status of the loaded UserDetails before * validation of the credentials takes place. * * @param preAuthenticationChecks strategy to be invoked prior to authentication. */ public void setPreAuthenticationChecks(UserDetailsChecker preAuthenticationChecks) { this.preAuthenticationChecks = preAuthenticationChecks; } protected UserDetailsChecker getPostAuthenticationChecks() { return postAuthenticationChecks; } public void setPostAuthenticationChecks(UserDetailsChecker postAuthenticationChecks) { this.postAuthenticationChecks = postAuthenticationChecks; } private class DefaultPreAuthenticationChecks implements UserDetailsChecker { public void check(UserDetails user) { if (!user.isAccountNonLocked()) { throw new LockedException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked", "User account is locked"), user); } if (!user.isEnabled()) { throw new DisabledException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled", "User is disabled"), user); } if (!user.isAccountNonExpired()) { throw new AccountExpiredException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired", "User account has expired"), user); } } } private class DefaultPostAuthenticationChecks implements UserDetailsChecker { public void check(UserDetails user) { if (!user.isCredentialsNonExpired()) { throw new CredentialsExpiredException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.credentialsExpired", "User credentials have expired"), user); } } } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/SaltSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/S0000644000000000000000000000235611623517156030474 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.dao; import org.springframework.security.userdetails.UserDetails; /** * Provides alternative sources of the salt to use for encoding passwords. * * @author Ben Alex * @version $Id$ */ public interface SaltSource { //~ Methods ======================================================================================================== /** * Returns the salt to use for the indicated user. * * @param user from the AuthenticationDao * * @return the salt to use for this UserDetails */ Object getSalt(UserDetails user); } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/UserCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/U0000644000000000000000000000514411623517156030474 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.dao; import org.springframework.security.userdetails.User; import org.springframework.security.userdetails.UserDetails; /** * Provides a cache of {@link User} objects. * *

    * Implementations should provide appropriate methods to set their cache * parameters (eg time-to-live) and/or force removal of entities before their * normal expiration. These are not part of the UserCache * interface contract because they vary depending on the type of caching * system used (eg in-memory vs disk vs cluster vs hybrid). *

    * * @author Ben Alex * @version $Id$ */ public interface UserCache { //~ Methods ======================================================================================================== /** * Obtains a {@link UserDetails} from the cache. * * @param username the {@link User#getUsername()} used to place the user in the cache * * @return the populated UserDetails or null if the user could not be found or if the * cache entry has expired */ UserDetails getUserFromCache(String username); /** * Places a {@link UserDetails} in the cache. The username is the key used to subsequently * retrieve the UserDetails. * * @param user the fully populated UserDetails to place in the cache */ void putUserInCache(UserDetails user); /** * Removes the specified user from the cache. The username is the key used to remove the user. * If the user is not found, the method should simply return (not thrown an exception).

    Some cache * implementations may not support eviction from the cache, in which case they should provide appropriate * behaviour to alter the user in either its documentation, via an exception, or through a log message.

    * * @param username to be evicted from the cache */ void removeUserFromCache(String username); } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/salt/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/s0000755000000000000000000000000011623517156030524 5ustar ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/salt/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/s0000644000000000000000000000014411623517156030525 0ustar Implementations that provide salts for more secure password encoding. ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/salt/SystemWideSaltSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/s0000644000000000000000000000414311623517156030530 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.dao.salt; import org.springframework.security.providers.dao.SaltSource; import org.springframework.security.userdetails.UserDetails; import org.springframework.beans.factory.InitializingBean; /** * Uses a static system-wide String as the salt.

    Does not supply a different salt for each {@link * org.springframework.security.userdetails.User}. This means users sharing the same password will still have the same digested * password. Of benefit is the digested passwords will at least be more protected than if stored without any salt.

    * * @author Ben Alex * @version $Id$ */ public class SystemWideSaltSource implements SaltSource, InitializingBean { //~ Instance fields ================================================================================================ private String systemWideSalt; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { if ((this.systemWideSalt == null) || "".equals(this.systemWideSalt)) { throw new IllegalArgumentException("A systemWideSalt must be set"); } } public Object getSalt(UserDetails user) { return this.systemWideSalt; } public String getSystemWideSalt() { return this.systemWideSalt; } public void setSystemWideSalt(String systemWideSalt) { this.systemWideSalt = systemWideSalt; } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/salt/ReflectionSaltSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/s0000644000000000000000000001063611623517156030534 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.dao.salt; import org.springframework.security.AuthenticationServiceException; import org.springframework.security.providers.dao.SaltSource; import org.springframework.security.userdetails.UserDetails; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.BeanUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.Assert; import java.lang.reflect.Method; import java.beans.PropertyDescriptor; /** * Obtains a salt from a specified property of the {@link org.springframework.security.userdetails.User} object. *

    * This allows you to subclass User and provide an additional bean getter for a salt. You should use a * synthetic value that does not change, such as a database primary key. Do not use username if it is * likely to change. * * @author Ben Alex * @version $Id$ */ public class ReflectionSaltSource implements SaltSource, InitializingBean { //~ Instance fields ================================================================================================ private String userPropertyToUse; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasText(userPropertyToUse, "A userPropertyToUse must be set"); } /** * Performs reflection on the passed User to obtain the salt. *

    * The property identified by userPropertyToUse must be available from the passed User * object. If it is not available, an {@link AuthenticationServiceException} will be thrown. * * @param user which contains the method identified by userPropertyToUse * * @return the result of invoking user.userPropertyToUse(), or if the method doesn't exist, * user.getUserPropertyToUse(). * * @throws AuthenticationServiceException if reflection fails */ public Object getSalt(UserDetails user) { Method saltMethod = findSaltMethod(user); try { return saltMethod.invoke(user, new Object[] {}); } catch (Exception exception) { throw new AuthenticationServiceException(exception.getMessage(), exception); } } private Method findSaltMethod(UserDetails user) { Method saltMethod = ReflectionUtils.findMethod(user.getClass(), userPropertyToUse, new Class[0]); if (saltMethod == null) { PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(user.getClass(), userPropertyToUse); if (pd != null) { saltMethod = pd.getReadMethod(); } if (saltMethod == null) { throw new AuthenticationServiceException("Unable to find salt method on user Object. Does the class '" + user.getClass().getName() + "' have a method or getter named '" + userPropertyToUse + "' ?"); } } return saltMethod; } protected String getUserPropertyToUse() { return userPropertyToUse; } /** * The method name to call to obtain the salt. Can be either a method name or a bean property name. If your * UserDetails contains a UserDetails.getSalt() method, you should set this property to * "getSalt" or "salt". * * @param userPropertyToUse the name of the getter to call to obtain the salt from the * UserDetails */ public void setUserPropertyToUse(String userPropertyToUse) { this.userPropertyToUse = userPropertyToUse; } public String toString() { return "ReflectionSaltSource[ userPropertyToUse='" + userPropertyToUse + "'; ]"; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/cache/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/c0000755000000000000000000000000011623517156030504 5ustar ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/cache/NullUserCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/c0000644000000000000000000000235111623517156030507 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.dao.cache; import org.springframework.security.providers.dao.UserCache; import org.springframework.security.userdetails.UserDetails; /** * Does not perform any caching. * * @author Ben Alex * @version $Id$ */ public class NullUserCache implements UserCache { //~ Methods ======================================================================================================== public UserDetails getUserFromCache(String username) { return null; } public void putUserInCache(UserDetails user) {} public void removeUserFromCache(String username) {} } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/cache/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/c0000644000000000000000000000015711623517156030511 0ustar Caches User objects for the DaoAuthenticationProvider. ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/cache/EhCacheBasedUserCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/dao/c0000644000000000000000000000636411623517156030517 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.dao.cache; import net.sf.ehcache.CacheException; import net.sf.ehcache.Element; import net.sf.ehcache.Ehcache; import org.springframework.security.providers.dao.UserCache; import org.springframework.security.userdetails.UserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.util.Assert; /** * Caches User objects using a Spring IoC defined EHCACHE. * * @author Ben Alex * @version $Id$ */ public class EhCacheBasedUserCache implements UserCache, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(EhCacheBasedUserCache.class); //~ Instance fields ================================================================================================ private Ehcache cache; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "cache mandatory"); } public Ehcache getCache() { return cache; } public UserDetails getUserFromCache(String username) { Element element = null; try { element = cache.get(username); } catch (CacheException cacheException) { throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage()); } if (logger.isDebugEnabled()) { logger.debug("Cache hit: " + (element != null) + "; username: " + username); } if (element == null) { return null; } else { return (UserDetails) element.getValue(); } } public void putUserInCache(UserDetails user) { Element element = new Element(user.getUsername(), user); if (logger.isDebugEnabled()) { logger.debug("Cache put: " + element.getKey()); } cache.put(element); } public void removeUserFromCache(UserDetails user) { if (logger.isDebugEnabled()) { logger.debug("Cache remove: " + user.getUsername()); } this.removeUserFromCache(user.getUsername()); } public void removeUserFromCache(String username) { cache.remove(username); } public void setCache(Ehcache cache) { this.cache = cache; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/preauth/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/preau0000755000000000000000000000000011623517156030633 5ustar ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/preauth/PreAuthenticatedAuthenticationToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/preau0000644000000000000000000000427711623517156030647 0ustar package org.springframework.security.providers.preauth; import org.springframework.security.providers.AbstractAuthenticationToken; import org.springframework.security.GrantedAuthority; /** * {@link org.springframework.security.Authentication} implementation for pre-authenticated * authentication. * * @author Ruud Senden * @since 2.0 */ public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationToken { private Object principal; private Object credentials; /** * Constructor used for an authentication request. The {@link * org.springframework.security.Authentication#isAuthenticated()} will return * false. * * @TODO Should we have only a single credentials parameter here? For * example for X509 the certificate is used as credentials, while * currently a J2EE username is specified as a principal but could as * well be set as credentials. * * @param aPrincipal * The pre-authenticated principal * @param aCredentials * The pre-authenticated credentials */ public PreAuthenticatedAuthenticationToken(Object aPrincipal, Object aCredentials) { super(null); this.principal = aPrincipal; this.credentials = aCredentials; } /** * Constructor used for an authentication response. The {@link * org.springframework.security.Authentication#isAuthenticated()} will return * true. * * @param aPrincipal * The authenticated principal * @param anAuthorities * The granted authorities */ public PreAuthenticatedAuthenticationToken(Object aPrincipal, Object aCredentials, GrantedAuthority[] anAuthorities) { super(anAuthorities); this.principal = aPrincipal; this.credentials = aCredentials; setAuthenticated(true); } /** * Get the credentials */ public Object getCredentials() { return this.credentials; } /** * Get the principal */ public Object getPrincipal() { return this.principal; } } ././@LongLink0000000000000000000000000000024100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesUserDetailsService.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/preau0000644000000000000000000000474311623517156030645 0ustar package org.springframework.security.providers.preauth; import org.springframework.security.userdetails.AuthenticationUserDetailsService; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.User; import org.springframework.security.GrantedAuthoritiesContainer; import org.springframework.security.GrantedAuthority; import org.springframework.security.AuthenticationException; import org.springframework.security.Authentication; import org.springframework.util.Assert; /** *

    * This AuthenticationUserDetailsService implementation creates a UserDetails * object based solely on the information contained in the given * PreAuthenticatedAuthenticationToken. The user name is set to the name as * returned by PreAuthenticatedAuthenticationToken.getName(), the password is * set to a fixed dummy value (it will not be used by the * PreAuthenticatedAuthenticationProvider anyway), and the Granted Authorities * are retrieved from the details object as returned by * PreAuthenticatedAuthenticationToken.getDetails(). * *

    * The details object as returned by PreAuthenticatedAuthenticationToken.getDetails() must implement the * {@link GrantedAuthoritiesContainer} interface for this implementation to work. * * @author Ruud Senden * @since 2.0 */ public class PreAuthenticatedGrantedAuthoritiesUserDetailsService implements AuthenticationUserDetailsService { /** * Get a UserDetails object based on the user name contained in the given * token, and the GrantedAuthorities as returned by the * GrantedAuthoritiesContainer implementation as returned by * the token.getDetails() method. */ public final UserDetails loadUserDetails(Authentication token) throws AuthenticationException { Assert.notNull(token.getDetails()); Assert.isInstanceOf(GrantedAuthoritiesContainer.class, token.getDetails()); GrantedAuthority[] authorities = ((GrantedAuthoritiesContainer) token.getDetails()).getGrantedAuthorities(); UserDetails ud = createuserDetails(token, authorities); return ud; } /** * Creates the final UserDetails object. Can be overridden to customize the contents. * * @param token the authentication request token * @param authorities the pre-authenticated authorities. */ protected UserDetails createuserDetails(Authentication token, GrantedAuthority[] authorities) { return new User(token.getName(), "N/A", true, true, true, true, authorities); } } ././@LongLink0000000000000000000000000000022300000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/preauth/PreAuthenticatedAuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/preau0000644000000000000000000001264211623517156030642 0ustar package org.springframework.security.providers.preauth; import org.springframework.security.providers.AuthenticationProvider; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.BadCredentialsException; import org.springframework.security.userdetails.AuthenticationUserDetailsService; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsChecker; import org.springframework.security.userdetails.checker.AccountStatusUserDetailsChecker; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.Ordered; import org.springframework.util.Assert; /** *

    * Processes a pre-authenticated authentication request. The request will * typically originate from a {@link org.springframework.security.ui.preauth.AbstractPreAuthenticatedProcessingFilter} * subclass. * *

    * This authentication provider will not perform any checks on authentication * requests, as they should already be pre- authenticated. However, the * AuthenticationUserDetailsService implementation may still throw a UsernameNotFoundException, for example. * * @author Ruud Senden * @version $Id$ * @since 2.0 */ public class PreAuthenticatedAuthenticationProvider implements AuthenticationProvider, InitializingBean, Ordered { private static final Log logger = LogFactory.getLog(PreAuthenticatedAuthenticationProvider.class); private AuthenticationUserDetailsService preAuthenticatedUserDetailsService = null; private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); private boolean throwExceptionWhenTokenRejected = false; private int order = -1; // default: same as non-ordered /** * Check whether all required properties have been set. */ public void afterPropertiesSet() { Assert.notNull(preAuthenticatedUserDetailsService, "An AuthenticationUserDetailsService must be set"); } /** * Authenticate the given PreAuthenticatedAuthenticationToken. *

    * If the principal contained in the authentication object is null, the request will be ignored to allow other * providers to authenticate it. */ public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } if (logger.isDebugEnabled()) { logger.debug("PreAuthenticated authentication request: " + authentication); } if (authentication.getPrincipal() == null) { logger.debug("No pre-authenticated principal found in request."); if (throwExceptionWhenTokenRejected) { throw new BadCredentialsException("No pre-authenticated principal found in request."); } return null; } if (authentication.getCredentials() == null) { logger.debug("No pre-authenticated credentials found in request."); if (throwExceptionWhenTokenRejected) { throw new BadCredentialsException("No pre-authenticated credentials found in request."); } return null; } UserDetails ud = preAuthenticatedUserDetailsService.loadUserDetails(authentication); userDetailsChecker.check(ud); PreAuthenticatedAuthenticationToken result = new PreAuthenticatedAuthenticationToken(ud, authentication.getCredentials(), ud.getAuthorities()); result.setDetails(authentication.getDetails()); return result; } /** * Indicate that this provider only supports PreAuthenticatedAuthenticationToken (sub)classes. */ public boolean supports(Class authentication) { return PreAuthenticatedAuthenticationToken.class.isAssignableFrom(authentication); } /** * Set the AuthenticatedUserDetailsServices to be used. * * @param aPreAuthenticatedUserDetailsService */ public void setPreAuthenticatedUserDetailsService(AuthenticationUserDetailsService aPreAuthenticatedUserDetailsService) { this.preAuthenticatedUserDetailsService = aPreAuthenticatedUserDetailsService; } public int getOrder() { return order; } public void setOrder(int i) { order = i; } /** * If true, causes the provider to throw a BadCredentialsException if the presented authentication * request is invalid (contains a null principal or credentials). Otherwise it will just return * null. Defaults to false. */ public void setThrowExceptionWhenTokenRejected(boolean throwExceptionWhenTokenRejected) { this.throwExceptionWhenTokenRejected = throwExceptionWhenTokenRejected; } /** * Sets the strategy which will be used to validate the loaded UserDetails object * for the user. Defaults to an {@link AccountStatusUserDetailsChecker}. * @param userDetailsChecker */ public void setUserDetailsChecker(UserDetailsChecker userDetailsChecker) { Assert.notNull(userDetailsChecker, "userDetailsChacker cannot be null"); this.userDetailsChecker = userDetailsChecker; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encoding/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encod0000755000000000000000000000000011623517156030607 5ustar ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encoding/Md4PasswordEncoder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encod0000644000000000000000000000565411623517156030623 0ustar /* Copyright 2004, 2005, 2006, 2007 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.encoding; import java.io.UnsupportedEncodingException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; /** * MD4 implementation of PasswordEncoder. *

    * If a null password is presented, it will be treated as an empty String ("") password. *

    * As MD4 is a one-way hash, the salt can contain any characters. *

    * NOTE: This password encoder is only included for backwards compatability with legacy applications, it's not * secure, don't use it for anything new! * * @author Alan Stewart */ public class Md4PasswordEncoder extends BaseDigestPasswordEncoder { //~ Methods ======================================================================================================== /** * Encodes the rawPass using an MD4 message digest. If a salt is specified it will be merged with the password * before encoding. * * @param rawPass The plain text password * @param salt The salt to sprinkle * @return Hex string of password digest (or base64 encoded string if encodeHashAsBase64 is enabled. */ public String encodePassword(String rawPass, Object salt) { String saltedPass = mergePasswordAndSalt(rawPass, salt, false); byte[] passBytes; try { passBytes = saltedPass.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { throw new IllegalStateException("UTF-8 not supported!"); } Md4 md4 = new Md4(); md4.update(passBytes, 0, passBytes.length); byte[] resBuf = md4.digest(); if (getEncodeHashAsBase64()) { return new String(Base64.encodeBase64(resBuf)); } else { return new String(Hex.encodeHex(resBuf)); } } /** * Takes a previously encoded password and compares it with a raw password after mixing in the salt and * encoding that value. * * @param encPass previously encoded password * @param rawPass plain text password * @param salt salt to mix into password * @return true or false */ public boolean isPasswordValid(String encPass, String rawPass, Object salt) { String pass1 = "" + encPass; String pass2 = encodePassword(rawPass, salt); return pass1.equals(pass2); } public String getAlgorithm() { return "MD4"; } }././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encoding/MessageDigestPasswordEncoder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encod0000644000000000000000000001072011623517156030611 0ustar package org.springframework.security.providers.encoding; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * Base for digest password encoders. *

    This class can be used stand-alone, or one of the subclasses can be used for compatiblity and convenience. * When using this class directly you must specify a * * Message Digest Algorithm to use as a constructor arg

    * *

    The encoded password hash is normally returned as Hex (32 char) version of the hash bytes. * Setting the encodeHashAsBase64 property to true will cause the encoded pass to be returned * as Base64 text, which will consume 24 characters. * See {@link BaseDigestPasswordEncoder#setEncodeHashAsBase64(boolean)} *

    *

    * This PasswordEncoder can be used directly as in the following example:
    *

     * <bean id="passwordEncoder" class="org.springframework.security.providers.encoding.MessageDigestPasswordEncoder">
     *     <constructor-arg value="MD5"/>
     * </bean>
     * 
    *

    * * @author Ray Krueger * @since 1.0.1 */ public class MessageDigestPasswordEncoder extends BaseDigestPasswordEncoder { private final String algorithm; /** * The digest algorithm to use * Supports the named * Message Digest Algorithms in the Java environment. * * @param algorithm */ public MessageDigestPasswordEncoder(String algorithm) { this(algorithm, false); } /** * Convenience constructor for specifying the algorithm and whether or not to enable base64 encoding * * @param algorithm * @param encodeHashAsBase64 * @throws IllegalArgumentException if an unknown */ public MessageDigestPasswordEncoder(String algorithm, boolean encodeHashAsBase64) throws IllegalArgumentException { this.algorithm = algorithm; setEncodeHashAsBase64(encodeHashAsBase64); //Validity Check getMessageDigest(); } /** * Encodes the rawPass using a MessageDigest. * If a salt is specified it will be merged with the password before encoding. * * @param rawPass The plain text password * @param salt The salt to sprinkle * @return Hex string of password digest (or base64 encoded string if encodeHashAsBase64 is enabled. */ public String encodePassword(String rawPass, Object salt) { String saltedPass = mergePasswordAndSalt(rawPass, salt, false); MessageDigest messageDigest = getMessageDigest(); byte[] digest; try { digest = messageDigest.digest(saltedPass.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { throw new IllegalStateException("UTF-8 not supported!"); } if (getEncodeHashAsBase64()) { return new String(Base64.encodeBase64(digest)); } else { return new String(Hex.encodeHex(digest)); } } /** * Get a MessageDigest instance for the given algorithm. * Throws an IllegalArgumentException if algorithm is unknown * * @return MessageDigest instance * @throws IllegalArgumentException if NoSuchAlgorithmException is thrown */ protected final MessageDigest getMessageDigest() throws IllegalArgumentException { try { return MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException("No such algorithm [" + algorithm + "]"); } } /** * Takes a previously encoded password and compares it with a rawpassword after mixing in the salt and * encoding that value * * @param encPass previously encoded password * @param rawPass plain text password * @param salt salt to mix into password * @return true or false */ public boolean isPasswordValid(String encPass, String rawPass, Object salt) { String pass1 = "" + encPass; String pass2 = encodePassword(rawPass, salt); return pass1.equals(pass2); } public String getAlgorithm() { return algorithm; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encoding/ShaPasswordEncoder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encod0000644000000000000000000000370511623517156030616 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.encoding; /** *

    SHA implementation of PasswordEncoder.

    *

    If a null password is presented, it will be treated as an empty String ("") * password.

    *

    As SHA is a one-way hash, the salt can contain any characters. The default strength for the SHA encoding is SHA-1. * If you wish to use higher strengths use the argumented constructor. * {@link #ShaPasswordEncoder(int strength)} *

    *

    * The applicationContext example... *

     * <bean id="passwordEncoder" class="org.springframework.security.providers.encoding.ShaPasswordEncoder">
     *     <constructor-arg value="256"/>
     * </bean>
     * 
    * * @author Ray Krueger * @author colin sampaleanu * @author Ben Alex * @version $Id$ */ public class ShaPasswordEncoder extends MessageDigestPasswordEncoder { /** * Initializes the ShaPasswordEncoder for SHA-1 strength */ public ShaPasswordEncoder() { this(1); } /** * Initialize the ShaPasswordEncoder with a given SHA stength as supported by the JVM * EX: ShaPasswordEncoder encoder = new ShaPasswordEncoder(256); initializes with SHA-256 * * @param strength EX: 1, 256, 384, 512 */ public ShaPasswordEncoder(int strength) { super("SHA-" + strength); } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encoding/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encod0000644000000000000000000000010111623517156030601 0ustar Password encoding implementations. ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encoding/Md4.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encod0000644000000000000000000001225511623517156030616 0ustar /* Copyright 2004, 2005, 2006, 2007 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.encoding; /** * Implementation of the MD4 message digest derived from the RSA Data Security, Inc, MD4 Message-Digest Algorithm. * * @author Alan Stewart */ class Md4 { private static final int BLOCK_SIZE = 64; private static final int HASH_SIZE = 16; private final byte[] buffer = new byte[BLOCK_SIZE]; private int bufferOffset; private long byteCount; private int[] state = new int[4]; private int[] tmp = new int[16]; Md4() { reset(); } public void reset() { bufferOffset = 0; byteCount = 0; state[0] = 0x67452301; state[1] = 0xEFCDAB89; state[2] = 0x98BADCFE; state[3] = 0x10325476; } public byte[] digest() { byte[] resBuf = new byte[HASH_SIZE]; digest(resBuf, 0, HASH_SIZE); return resBuf; } private void digest(byte[] buffer, int off) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { buffer[off + (i * 4 + j)] = (byte) (state[i] >>> (8 * j)); } } } private void digest(byte[] buffer, int offset, int len) { this.buffer[this.bufferOffset++] = (byte) 0x80; int lenOfBitLen = 8; int C = BLOCK_SIZE - lenOfBitLen; if (this.bufferOffset > C) { while (this.bufferOffset < BLOCK_SIZE) { this.buffer[this.bufferOffset++] = (byte) 0x00; } update(this.buffer, 0); this.bufferOffset = 0; } while (this.bufferOffset < C) { this.buffer[this.bufferOffset++] = (byte) 0x00; } long bitCount = byteCount * 8; for (int i = 0; i < 64; i += 8) { this.buffer[this.bufferOffset++] = (byte) (bitCount >>> (i)); } update(this.buffer, 0); digest(buffer, offset); } public void update(byte[] input, int offset, int length) { byteCount += length; int todo; while (length >= (todo = BLOCK_SIZE - this.bufferOffset)) { System.arraycopy(input, offset, this.buffer, this.bufferOffset, todo); update(this.buffer, 0); length -= todo; offset += todo; this.bufferOffset = 0; } System.arraycopy(input, offset, this.buffer, this.bufferOffset, length); bufferOffset += length; } private void update(byte[] block, int offset) { for (int i = 0; i < 16; i++) { tmp[i] = (block[offset++] & 0xFF) | (block[offset++] & 0xFF) << 8 | (block[offset++] & 0xFF) << 16 | (block[offset++] & 0xFF) << 24; } int A = state[0]; int B = state[1]; int C = state[2]; int D = state[3]; A = FF(A, B, C, D, tmp[0], 3); D = FF(D, A, B, C, tmp[1], 7); C = FF(C, D, A, B, tmp[2], 11); B = FF(B, C, D, A, tmp[3], 19); A = FF(A, B, C, D, tmp[4], 3); D = FF(D, A, B, C, tmp[5], 7); C = FF(C, D, A, B, tmp[6], 11); B = FF(B, C, D, A, tmp[7], 19); A = FF(A, B, C, D, tmp[8], 3); D = FF(D, A, B, C, tmp[9], 7); C = FF(C, D, A, B, tmp[10], 11); B = FF(B, C, D, A, tmp[11], 19); A = FF(A, B, C, D, tmp[12], 3); D = FF(D, A, B, C, tmp[13], 7); C = FF(C, D, A, B, tmp[14], 11); B = FF(B, C, D, A, tmp[15], 19); A = GG(A, B, C, D, tmp[0], 3); D = GG(D, A, B, C, tmp[4], 5); C = GG(C, D, A, B, tmp[8], 9); B = GG(B, C, D, A, tmp[12], 13); A = GG(A, B, C, D, tmp[1], 3); D = GG(D, A, B, C, tmp[5], 5); C = GG(C, D, A, B, tmp[9], 9); B = GG(B, C, D, A, tmp[13], 13); A = GG(A, B, C, D, tmp[2], 3); D = GG(D, A, B, C, tmp[6], 5); C = GG(C, D, A, B, tmp[10], 9); B = GG(B, C, D, A, tmp[14], 13); A = GG(A, B, C, D, tmp[3], 3); D = GG(D, A, B, C, tmp[7], 5); C = GG(C, D, A, B, tmp[11], 9); B = GG(B, C, D, A, tmp[15], 13); A = HH(A, B, C, D, tmp[0], 3); D = HH(D, A, B, C, tmp[8], 9); C = HH(C, D, A, B, tmp[4], 11); B = HH(B, C, D, A, tmp[12], 15); A = HH(A, B, C, D, tmp[2], 3); D = HH(D, A, B, C, tmp[10], 9); C = HH(C, D, A, B, tmp[6], 11); B = HH(B, C, D, A, tmp[14], 15); A = HH(A, B, C, D, tmp[1], 3); D = HH(D, A, B, C, tmp[9], 9); C = HH(C, D, A, B, tmp[5], 11); B = HH(B, C, D, A, tmp[13], 15); A = HH(A, B, C, D, tmp[3], 3); D = HH(D, A, B, C, tmp[11], 9); C = HH(C, D, A, B, tmp[7], 11); B = HH(B, C, D, A, tmp[15], 15); state[0] += A; state[1] += B; state[2] += C; state[3] += D; } private int FF(int a, int b, int c, int d, int x, int s) { int t = a + ((b & c) | (~b & d)) + x; return t << s | t >>> (32 - s); } private int GG(int a, int b, int c, int d, int x, int s) { int t = a + ((b & (c | d)) | (c & d)) + x + 0x5A827999; return t << s | t >>> (32 - s); } private int HH(int a, int b, int c, int d, int x, int s) { int t = a + (b ^ c ^ d) + x + 0x6ED9EBA1; return t << s | t >>> (32 - s); } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encoding/Md5PasswordEncoder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encod0000644000000000000000000000241411623517156030612 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.encoding; /** *

    MD5 implementation of PasswordEncoder.

    *

    If a null password is presented, it will be treated as an empty String ("") * password.

    *

    As MD5 is a one-way hash, the salt can contain any characters.

    * * This is a convenience class that extends the * {@link MessageDigestPasswordEncoder} and passes MD5 as the algorithm to use. * * @author Ray Krueger * @author colin sampaleanu * @author Ben Alex * @version $Id$ */ public class Md5PasswordEncoder extends MessageDigestPasswordEncoder { public Md5PasswordEncoder() { super("MD5"); } } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encoding/BaseDigestPasswordEncoder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encod0000644000000000000000000000323211623517156030611 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.encoding; /** *

    Convenience base for digest password encoders.

    * * @author colin sampaleanu * @version $Id$ */ public abstract class BaseDigestPasswordEncoder extends BasePasswordEncoder { //~ Instance fields ================================================================================================ private boolean encodeHashAsBase64 = false; //~ Methods ======================================================================================================== public boolean getEncodeHashAsBase64() { return encodeHashAsBase64; } /** * The encoded password is normally returned as Hex (32 char) version of the hash bytes. Setting this * property to true will cause the encoded pass to be returned as Base64 text, which will consume 24 characters. * * @param encodeHashAsBase64 set to true for Base64 output */ public void setEncodeHashAsBase64(boolean encodeHashAsBase64) { this.encodeHashAsBase64 = encodeHashAsBase64; } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encoding/PlaintextPasswordEncoder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encod0000644000000000000000000000611111623517156030610 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.encoding; /** *

    Plaintext implementation of PasswordEncoder.

    *

    As callers may wish to extract the password and salts separately from the encoded password, the salt must * not contain reserved characters (specifically '{' and '}').

    * * @author colin sampaleanu * @author Ben Alex * @version $Id$ */ public class PlaintextPasswordEncoder extends BasePasswordEncoder { //~ Instance fields ================================================================================================ private boolean ignorePasswordCase = false; //~ Methods ======================================================================================================== public String encodePassword(String rawPass, Object salt) { return mergePasswordAndSalt(rawPass, salt, true); } public boolean isIgnorePasswordCase() { return ignorePasswordCase; } public boolean isPasswordValid(String encPass, String rawPass, Object salt) { String pass1 = encPass + ""; // Strict delimiters is false because pass2 never persisted anywhere // and we want to avoid unnecessary exceptions as a result (the // authentication will fail as the encodePassword never allows them) String pass2 = mergePasswordAndSalt(rawPass, salt, false); if (!ignorePasswordCase) { return pass1.equals(pass2); } else { return pass1.equalsIgnoreCase(pass2); } } /** * Demerges the previously {@link #encodePassword(String, Object)}String.

    The resulting * array is guaranteed to always contain two elements. The first is the password, and the second is the salt.

    *

    Throws an exception if null or an empty String is passed to the method.

    * * @param password from {@link #encodePassword(String, Object)} * * @return an array containing the password and salt */ public String[] obtainPasswordAndSalt(String password) { return demergePasswordAndSalt(password); } /** * Indicates whether the password comparison is case sensitive.

    Defaults to false, meaning * an exact case match is required.

    * * @param ignorePasswordCase set to true for less stringent comparison */ public void setIgnorePasswordCase(boolean ignorePasswordCase) { this.ignorePasswordCase = ignorePasswordCase; } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encoding/BasePasswordEncoder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encod0000644000000000000000000000744111623517156030617 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.encoding; /** *

    Convenience base for all password encoders.

    * * @author Ben Alex * @version $Id$ */ public abstract class BasePasswordEncoder implements PasswordEncoder { //~ Methods ======================================================================================================== /** * Used by subclasses to extract the password and salt from a merged String created using * {@link #mergePasswordAndSalt(String,Object,boolean)}.

    The first element in the returned array is the * password. The second element is the salt. The salt array element will always be present, even if no salt was * found in the mergedPasswordSalt argument.

    * * @param mergedPasswordSalt as generated by mergePasswordAndSalt * * @return an array, in which the first element is the password and the second the salt * * @throws IllegalArgumentException if mergedPasswordSalt is null or empty. */ protected String[] demergePasswordAndSalt(String mergedPasswordSalt) { if ((mergedPasswordSalt == null) || "".equals(mergedPasswordSalt)) { throw new IllegalArgumentException("Cannot pass a null or empty String"); } String password = mergedPasswordSalt; String salt = ""; int saltBegins = mergedPasswordSalt.lastIndexOf("{"); if ((saltBegins != -1) && ((saltBegins + 1) < mergedPasswordSalt.length())) { salt = mergedPasswordSalt.substring(saltBegins + 1, mergedPasswordSalt.length() - 1); password = mergedPasswordSalt.substring(0, saltBegins); } return new String[] {password, salt}; } /** * Used by subclasses to generate a merged password and salt String.

    The generated password * will be in the form of password{salt}.

    *

    A null can be passed to either method, and will be handled correctly. If the * salt is null or empty, the resulting generated password will simply be the passed * password. The toString method of the salt will be used to represent the * salt.

    * * @param password the password to be used (can be null) * @param salt the salt to be used (can be null) * @param strict ensures salt doesn't contain the delimiters * * @return a merged password and salt String * * @throws IllegalArgumentException if the salt contains '{' or '}' characters. */ protected String mergePasswordAndSalt(String password, Object salt, boolean strict) { if (password == null) { password = ""; } if (strict && (salt != null)) { if ((salt.toString().lastIndexOf("{") != -1) || (salt.toString().lastIndexOf("}") != -1)) { throw new IllegalArgumentException("Cannot use { or } in salt.toString()"); } } if ((salt == null) || "".equals(salt)) { return password; } else { return password + "{" + salt.toString() + "}"; } } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encoding/PasswordEncoder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/encod0000644000000000000000000000724111623517156030615 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.encoding; import org.springframework.dao.DataAccessException; /** *

    * Interface for performing authentication operations on a password. *

    * * @author colin sampaleanu * @version $Id$ */ public interface PasswordEncoder { //~ Methods ======================================================================================================== /** *

    Encodes the specified raw password with an implementation specific algorithm.

    *

    This will generally be a one-way message digest such as MD5 or SHA, but may also be a plaintext * variant which does no encoding at all, but rather returns the same password it was fed. The latter is useful to * plug in when the original password must be stored as-is.

    *

    The specified salt will potentially be used by the implementation to "salt" the initial value before * encoding. A salt is usually a user-specific value which is added to the password before the digest is computed. * This means that computation of digests for common dictionary words will be different than those in the backend * store, because the dictionary word digests will not reflect the addition of the salt. If a per-user salt is * used (rather than a system-wide salt), it also means users with the same password will have different digest * encoded passwords in the backend store.

    *

    If a salt value is provided, the same salt value must be use when calling the {@link * #isPasswordValid(String, String, Object)} method. Note that a specific implementation may choose to ignore the * salt value (via null), or provide its own.

    * * @param rawPass the password to encode * @param salt optionally used by the implementation to "salt" the raw password before encoding. A * null value is legal. * * @return encoded password * * @throws DataAccessException DOCUMENT ME! */ String encodePassword(String rawPass, Object salt) throws DataAccessException; /** *

    Validates a specified "raw" password against an encoded password.

    *

    The encoded password should have previously been generated by {@link #encodePassword(String, * Object)}. This method will encode the rawPass (using the optional salt), and then * compared it with the presented encPass.

    *

    For a discussion of salts, please refer to {@link #encodePassword(String, Object)}.

    * * @param encPass a pre-encoded password * @param rawPass a raw password to encode and compare against the pre-encoded password * @param salt optionally used by the implementation to "salt" the raw password before encoding. A * null value is legal. * * @return true if the password is valid , false otherwise * * @throws DataAccessException DOCUMENT ME! */ boolean isPasswordValid(String encPass, String rawPass, Object salt) throws DataAccessException; } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/packa0000644000000000000000000000014411623517156030577 0ustar Implements a provider-based approach to authentication decisions.

    spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000755000000000000000000000000011623517156030303 5ustar ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/populator/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000755000000000000000000000000011623517156030303 5ustar ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/populator/DaoX509AuthoritiesPopulator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000644000000000000000000001157711623517156030320 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.x509.populator; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.AuthenticationException; import org.springframework.security.BadCredentialsException; import org.springframework.security.AuthenticationServiceException; import org.springframework.security.providers.x509.X509AuthoritiesPopulator; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.security.cert.X509Certificate; import java.util.regex.Pattern; import java.util.regex.Matcher; /** * Populates the X509 authorities via an {@link org.springframework.security.userdetails.UserDetailsService}. * * @author Luke Taylor * @deprecated This package is now deprecated. Use the X.509 authentication support in * org.springframework.security.ui.preauth.x509 instead. * @version $Id$ */ public class DaoX509AuthoritiesPopulator implements X509AuthoritiesPopulator, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(DaoX509AuthoritiesPopulator.class); //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private Pattern subjectDNPattern; private String subjectDNRegex = "CN=(.*?),"; private UserDetailsService userDetailsService; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(userDetailsService, "An authenticationDao must be set"); Assert.notNull(this.messages, "A message source must be set"); subjectDNPattern = Pattern.compile(subjectDNRegex, Pattern.CASE_INSENSITIVE); } public UserDetails getUserDetails(X509Certificate clientCert) throws AuthenticationException { String subjectDN = clientCert.getSubjectDN().getName(); Matcher matcher = subjectDNPattern.matcher(subjectDN); if (!matcher.find()) { throw new BadCredentialsException(messages.getMessage("DaoX509AuthoritiesPopulator.noMatching", new Object[] {subjectDN}, "No matching pattern was found in subjectDN: {0}")); } if (matcher.groupCount() != 1) { throw new IllegalArgumentException("Regular expression must contain a single group "); } String userName = matcher.group(1); UserDetails user = this.userDetailsService.loadUserByUsername(userName); if (user == null) { throw new AuthenticationServiceException( "UserDetailsService returned null, which is an interface contract violation"); } return user; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } /** * Sets the regular expression which will by used to extract the user name from the certificate's Subject * DN. *

    It should contain a single group; for example the default expression "CN=(.?)," matches the common * name field. So "CN=Jimi Hendrix, OU=..." will give a user name of "Jimi Hendrix".

    *

    The matches are case insensitive. So "emailAddress=(.?)," will match "EMAILADDRESS=jimi@hendrix.org, * CN=..." giving a user name "jimi@hendrix.org"

    * * @param subjectDNRegex the regular expression to find in the subject */ public void setSubjectDNRegex(String subjectDNRegex) { this.subjectDNRegex = subjectDNRegex; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/populator/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000644000000000000000000000036411623517156030310 0ustar This package is now deprecated and will be removed in a future version. Use the X.509 authentication support in org.springframework.security.ui.preauth.x509 instead. Authorities are loaded by a UserDetailsService. ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/X509UserCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000644000000000000000000000274011623517156030310 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.x509; import org.springframework.security.userdetails.UserDetails; import java.security.cert.X509Certificate; /** * Provides a cache of {@link UserDetails} objects for the * {@link X509AuthenticationProvider}. *

    * Similar in function to the {@link org.springframework.security.providers.dao.UserCache} * used by the Dao provider, but the cache is keyed with the user's certificate * rather than the user name. *

    * * @author Luke Taylor * @deprecated * @version $Id$ */ public interface X509UserCache { //~ Methods ======================================================================================================== UserDetails getUserFromCache(X509Certificate userCertificate); void putUserInCache(X509Certificate key, UserDetails user); void removeUserFromCache(X509Certificate key); } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000644000000000000000000000030411623517156030302 0ustar This package is now deprecated and will be removed in a future version. Use the X.509 authentication support in org.springframework.security.ui.preauth.x509 instead. ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/X509AuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000644000000000000000000001310711623517156030307 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.x509; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.BadCredentialsException; import org.springframework.security.providers.AuthenticationProvider; import org.springframework.security.providers.x509.cache.NullX509UserCache; import org.springframework.security.userdetails.UserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import java.security.cert.X509Certificate; /** * Processes an X.509 authentication request.

    The request will typically originate from {@link * org.springframework.security.ui.x509.X509ProcessingFilter}).

    * * @author Luke Taylor * @deprecated superceded by the preauth provider. Use the X.509 authentication support in org.springframework.security.ui.preauth.x509 instead * or namespace support via the <x509 /> element. * @version $Id$ */ public class X509AuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(X509AuthenticationProvider.class); //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private X509AuthoritiesPopulator x509AuthoritiesPopulator; private X509UserCache userCache = new NullX509UserCache(); //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(userCache, "An x509UserCache must be set"); Assert.notNull(x509AuthoritiesPopulator, "An X509AuthoritiesPopulator must be set"); Assert.notNull(this.messages, "A message source must be set"); } /** * If the supplied authentication token contains a certificate then this will be passed to the configured * {@link X509AuthoritiesPopulator} to obtain the user details and authorities for the user identified by the * certificate.

    If no certificate is present (for example, if the filter is applied to an HttpRequest for * which client authentication hasn't been configured in the container) then a BadCredentialsException will be * raised.

    * * @param authentication the authentication request. * * @return an X509AuthenticationToken containing the authorities of the principal represented by the certificate. * * @throws AuthenticationException if the {@link X509AuthoritiesPopulator} rejects the certficate. * @throws BadCredentialsException if no certificate was presented in the authentication request. */ public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } if (logger.isDebugEnabled()) { logger.debug("X509 authentication request: " + authentication); } X509Certificate clientCertificate = (X509Certificate) authentication.getCredentials(); if (clientCertificate == null) { throw new BadCredentialsException(messages.getMessage("X509AuthenticationProvider.certificateNull", "Certificate is null")); } UserDetails user = userCache.getUserFromCache(clientCertificate); if (user == null) { if (logger.isDebugEnabled()) { logger.debug("Authenticating with certificate " + clientCertificate); } user = x509AuthoritiesPopulator.getUserDetails(clientCertificate); userCache.putUserInCache(clientCertificate, user); } X509AuthenticationToken result = new X509AuthenticationToken(user, clientCertificate, user.getAuthorities()); result.setDetails(authentication.getDetails()); return result; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public void setX509AuthoritiesPopulator(X509AuthoritiesPopulator x509AuthoritiesPopulator) { this.x509AuthoritiesPopulator = x509AuthoritiesPopulator; } public void setX509UserCache(X509UserCache cache) { this.userCache = cache; } public boolean supports(Class authentication) { return X509AuthenticationToken.class.isAssignableFrom(authentication); } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/X509AuthenticationToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000644000000000000000000000541711623517156030314 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.x509; import org.springframework.security.GrantedAuthority; import org.springframework.security.providers.AbstractAuthenticationToken; import java.security.cert.X509Certificate; /** * Authentication implementation for X.509 client-certificate authentication. * * @author Luke Taylor * @deprecated superceded by the preauth provider. Use the X.509 authentication support in org.springframework.security.ui.preauth.x509 instead. * @version $Id$ */ public class X509AuthenticationToken extends AbstractAuthenticationToken { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Object principal; private X509Certificate credentials; //~ Constructors =================================================================================================== /** * Used for an authentication request. The {@link org.springframework.security.Authentication#isAuthenticated()} will return * false. * * @param credentials the certificate */ public X509AuthenticationToken(X509Certificate credentials) { super(null); this.credentials = credentials; } /** * Used for an authentication response object. The {@link org.springframework.security.Authentication#isAuthenticated()} * will return true. * * @param principal the principal, which is generally a * UserDetails * @param credentials the certificate * @param authorities the authorities */ public X509AuthenticationToken(Object principal, X509Certificate credentials, GrantedAuthority[] authorities) { super(authorities); this.principal = principal; this.credentials = credentials; setAuthenticated(true); } //~ Methods ======================================================================================================== public Object getCredentials() { return credentials; } public Object getPrincipal() { return principal; } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/X509AuthoritiesPopulator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000644000000000000000000000421411623517156030306 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.x509; import org.springframework.security.AuthenticationException; import org.springframework.security.userdetails.UserDetails; import java.security.cert.X509Certificate; /** * Populates the UserDetails associated with the X.509 * certificate presented by a client. *

    * Although the certificate will already have been validated by the web container, * implementations may choose to perform additional application-specific checks on * the certificate content here. If an implementation chooses to reject the certificate, * it should throw a {@link org.springframework.security.BadCredentialsException}. *

    * * @author Luke Taylor * @deprecated * @version $Id$ */ public interface X509AuthoritiesPopulator { //~ Methods ======================================================================================================== /** * Obtains the granted authorities for the specified user.

    May throw any * AuthenticationException or return null if the authorities are unavailable.

    * * @param userCertificate the X.509 certificate supplied * * @return the details of the indicated user (at minimum the granted authorities and the username) * * @throws AuthenticationException if the user details are not available or the certificate isn't valid for the * application's purpose. */ UserDetails getUserDetails(X509Certificate userCertificate) throws AuthenticationException; } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/cache/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000755000000000000000000000000011623517156030303 5ustar ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/cache/EhCacheBasedX509UserCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000644000000000000000000000665111623517156030315 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.x509.cache; import net.sf.ehcache.CacheException; import net.sf.ehcache.Element; import net.sf.ehcache.Ehcache; import org.springframework.security.providers.x509.X509UserCache; import org.springframework.security.userdetails.UserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.util.Assert; import java.security.cert.X509Certificate; /** * Caches User objects using a Spring IoC defined EHCACHE. * * @author Luke Taylor * @author Ben Alex * @deprecated use the X509 preauthenticated * @version $Id$ */ public class EhCacheBasedX509UserCache implements X509UserCache, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(EhCacheBasedX509UserCache.class); //~ Instance fields ================================================================================================ private Ehcache cache; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "cache is mandatory"); } public UserDetails getUserFromCache(X509Certificate userCert) { Element element = null; try { element = cache.get(userCert); } catch (CacheException cacheException) { throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage()); } if (logger.isDebugEnabled()) { String subjectDN = "unknown"; if ((userCert != null) && (userCert.getSubjectDN() != null)) { subjectDN = userCert.getSubjectDN().toString(); } logger.debug("X.509 Cache hit. SubjectDN: " + subjectDN); } if (element == null) { return null; } else { return (UserDetails) element.getValue(); } } public void putUserInCache(X509Certificate userCert, UserDetails user) { Element element = new Element(userCert, user); if (logger.isDebugEnabled()) { logger.debug("Cache put: " + userCert.getSubjectDN()); } cache.put(element); } public void removeUserFromCache(X509Certificate userCert) { if (logger.isDebugEnabled()) { logger.debug("Cache remove: " + userCert.getSubjectDN()); } cache.remove(userCert); } public void setCache(Ehcache cache) { this.cache = cache; } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/cache/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000644000000000000000000000017411623517156030307 0ustar Deprecated and will be removed in a future version. Use a caching UserDetailsService instead. ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/cache/NullX509UserCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/x509/0000644000000000000000000000256111623517156030311 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.x509.cache; import org.springframework.security.providers.x509.X509UserCache; import org.springframework.security.userdetails.UserDetails; import java.security.cert.X509Certificate; /** * "Cache" that doesn't do any caching. * * @author Luke Taylor * @deprecated * @version $Id$ */ public class NullX509UserCache implements X509UserCache { //~ Methods ======================================================================================================== public UserDetails getUserFromCache(X509Certificate certificate) { return null; } public void putUserInCache(X509Certificate certificate, UserDetails user) {} public void removeUserFromCache(X509Certificate certificate) {} } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rcp/0000755000000000000000000000000011623517156030362 5ustar ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rcp/RemoteAuthenticationManagerImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rcp/R0000644000000000000000000000511111623517156030504 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.rcp; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationManager; import org.springframework.security.GrantedAuthority; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Server-side processor of a remote authentication request.

    This bean requires no security interceptor to * protect it. Instead, the bean uses the configured AuthenticationManager to resolve an authentication * request.

    * * @author Ben Alex * @version $Id$ */ public class RemoteAuthenticationManagerImpl implements RemoteAuthenticationManager, InitializingBean { //~ Instance fields ================================================================================================ private AuthenticationManager authenticationManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.authenticationManager, "authenticationManager is required"); } public GrantedAuthority[] attemptAuthentication(String username, String password) throws RemoteAuthenticationException { UsernamePasswordAuthenticationToken request = new UsernamePasswordAuthenticationToken(username, password); try { return authenticationManager.authenticate(request).getAuthorities(); } catch (AuthenticationException authEx) { throw new RemoteAuthenticationException(authEx.getMessage()); } } public AuthenticationManager getAuthenticationManager() { return authenticationManager; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rcp/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rcp/p0000644000000000000000000000020011623517156030534 0ustar Allows remote clients to authenticate and obtain a populated Authentication object. ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rcp/RemoteAuthenticationManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rcp/R0000644000000000000000000000410211623517156030503 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.rcp; import org.springframework.security.GrantedAuthority; /** * Allows remote clients to attempt authentication. * * @author Ben Alex * @version $Id$ */ public interface RemoteAuthenticationManager { //~ Methods ======================================================================================================== /** * Attempts to authenticate the remote client using the presented username and password. If authentication * is successful, an array of GrantedAuthority[] objects will be returned.

    In order to * maximise remoting protocol compatibility, a design decision was taken to operate with minimal arguments and * return only the minimal amount of information required for remote clients to enable/disable relevant user * interface commands etc. There is nothing preventing users from implementing their own equivalent package that * works with more complex object types.

    * * @param username the username the remote client wishes to authenticate with. * @param password the password the remote client wishes to authenticate with. * * @return all of the granted authorities the specified username and password have access to. * * @throws RemoteAuthenticationException if the authentication failed. */ GrantedAuthority[] attemptAuthentication(String username, String password) throws RemoteAuthenticationException; } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rcp/RemoteAuthenticationException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rcp/R0000644000000000000000000000303311623517156030505 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.rcp; import org.springframework.security.SpringSecurityException; /** * Thrown if a RemoteAuthenticationManager cannot validate the presented authentication request.

    This * is thrown rather than the normal AuthenticationException because AuthenticationException * contains additional properties which may cause issues for the remoting protocol.

    * * @author Ben Alex * @version $Id$ */ public class RemoteAuthenticationException extends SpringSecurityException { //~ Constructors =================================================================================================== /** * Constructs a RemoteAuthenticationException with the * specified message and no root cause. * * @param msg the detail message */ public RemoteAuthenticationException(String msg) { super(msg); } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rcp/RemoteAuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/rcp/R0000644000000000000000000000721311623517156030511 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.rcp; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.GrantedAuthority; import org.springframework.security.providers.AuthenticationProvider; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * Client-side object which queries a {@link RemoteAuthenticationManager} to validate an authentication request.

    A * new Authentication object is created by this class comprising the request Authentication * object's principal, credentials and the GrantedAuthority[]s returned by the * RemoteAuthenticationManager.

    *

    The RemoteAuthenticationManager should not require any special username or password setting on * the remoting client proxy factory to execute the call. Instead the entire authentication request must be * encapsulated solely within the Authentication request object. In practical terms this means the * RemoteAuthenticationManager will not be protected by BASIC or any other HTTP-level * authentication.

    *

    If authentication fails, a RemoteAuthenticationException will be thrown. This exception should * be caught and displayed to the user, enabling them to retry with alternative credentials etc.

    * * @author Ben Alex * @version $Id$ */ public class RemoteAuthenticationProvider implements AuthenticationProvider, InitializingBean { //~ Instance fields ================================================================================================ private RemoteAuthenticationManager remoteAuthenticationManager; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.remoteAuthenticationManager, "remoteAuthenticationManager is mandatory"); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getPrincipal().toString(); String password = authentication.getCredentials().toString(); GrantedAuthority[] authorities = remoteAuthenticationManager.attemptAuthentication(username, password); return new UsernamePasswordAuthenticationToken(username, password, authorities); } public RemoteAuthenticationManager getRemoteAuthenticationManager() { return remoteAuthenticationManager; } public void setRemoteAuthenticationManager(RemoteAuthenticationManager remoteAuthenticationManager) { this.remoteAuthenticationManager = remoteAuthenticationManager; } public boolean supports(Class authentication) { return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ProviderManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/Provi0000644000000000000000000004006211623517156030622 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers; import org.springframework.security.AbstractAuthenticationManager; import org.springframework.security.AccountExpiredException; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationServiceException; import org.springframework.security.BadCredentialsException; import org.springframework.security.CredentialsExpiredException; import org.springframework.security.DisabledException; import org.springframework.security.LockedException; import org.springframework.security.AccountStatusException; import org.springframework.security.concurrent.ConcurrentLoginException; import org.springframework.security.concurrent.ConcurrentSessionController; import org.springframework.security.concurrent.NullConcurrentSessionController; import org.springframework.security.event.authentication.AbstractAuthenticationEvent; import org.springframework.security.event.authentication.AuthenticationFailureBadCredentialsEvent; import org.springframework.security.event.authentication.AuthenticationFailureConcurrentLoginEvent; import org.springframework.security.event.authentication.AuthenticationFailureCredentialsExpiredEvent; import org.springframework.security.event.authentication.AuthenticationFailureDisabledEvent; import org.springframework.security.event.authentication.AuthenticationFailureExpiredEvent; import org.springframework.security.event.authentication.AuthenticationFailureLockedEvent; import org.springframework.security.event.authentication.AuthenticationFailureProviderNotFoundEvent; import org.springframework.security.event.authentication.AuthenticationFailureProxyUntrustedEvent; import org.springframework.security.event.authentication.AuthenticationFailureServiceExceptionEvent; import org.springframework.security.event.authentication.AuthenticationSuccessEvent; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Iterator; import java.util.List; import java.util.Properties; /** * Iterates an {@link Authentication} request through a list of {@link AuthenticationProvider}s. * * Can optionally be configured with a {@link ConcurrentSessionController} to limit the number of sessions a user can * have. *

    * AuthenticationProviders are usually tried in order until one provides a non-null response. * A non-null response indicates the provider had authority to decide on the authentication request and no further * providers are tried. * If a subsequent provider successfully authenticates the request, the earlier authentication exception is disregarded * and the successful authentication will be used. If no subsequent provider provides a non-null response, or a new * AuthenticationException, the last AuthenticationException received will be used. * If no provider returns a non-null response, or indicates it can even process an Authentication, * the ProviderManager will throw a ProviderNotFoundException. *

    * The exception to this process is when a provider throws an {@link AccountStatusException} or if the configured * concurrent session controller throws a {@link ConcurrentLoginException}. In both these cases, no further providers * in the list will be queried. * *

    * If a valid Authentication is returned by an AuthenticationProvider, the * ProviderManager will publish an * {@link org.springframework.security.event.authentication.AuthenticationSuccessEvent}. If an * AuthenticationException is detected, the final AuthenticationException thrown will be * used to publish an appropriate failure event. By default ProviderManager maps common exceptions to * events, but this can be fine-tuned by providing a new exceptionMappingsjava.util.Properties * object. In the properties object, each of the keys represent the fully qualified classname of the exception, and * each of the values represent the name of an event class which subclasses * {@link org.springframework.security.event.authentication.AbstractAuthenticationFailureEvent} * and provides its constructor. * * * @author Ben Alex * @version $Id$ * @see ConcurrentSessionController */ public class ProviderManager extends AbstractAuthenticationManager implements InitializingBean, MessageSourceAware, ApplicationEventPublisherAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(ProviderManager.class); private static final Properties DEFAULT_EXCEPTION_MAPPINGS = new Properties(); //~ Instance fields ================================================================================================ private ApplicationEventPublisher applicationEventPublisher; private ConcurrentSessionController sessionController = new NullConcurrentSessionController(); private List providers; protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private Properties exceptionMappings = new Properties(); private Properties additionalExceptionMappings = new Properties(); static { DEFAULT_EXCEPTION_MAPPINGS.put(AccountExpiredException.class.getName(), AuthenticationFailureExpiredEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(AuthenticationServiceException.class.getName(), AuthenticationFailureServiceExceptionEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(LockedException.class.getName(), AuthenticationFailureLockedEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(CredentialsExpiredException.class.getName(), AuthenticationFailureCredentialsExpiredEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(DisabledException.class.getName(), AuthenticationFailureDisabledEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(BadCredentialsException.class.getName(), AuthenticationFailureBadCredentialsEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(UsernameNotFoundException.class.getName(), AuthenticationFailureBadCredentialsEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(ConcurrentLoginException.class.getName(), AuthenticationFailureConcurrentLoginEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put(ProviderNotFoundException.class.getName(), AuthenticationFailureProviderNotFoundEvent.class.getName()); DEFAULT_EXCEPTION_MAPPINGS.put("org.springframework.security.providers.cas.ProxyUntrustedException", AuthenticationFailureProxyUntrustedEvent.class.getName()); } public ProviderManager() { exceptionMappings.putAll(DEFAULT_EXCEPTION_MAPPINGS); } //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(this.messages, "A message source must be set"); exceptionMappings.putAll(additionalExceptionMappings); } /** * Attempts to authenticate the passed {@link Authentication} object. *

    * The list of {@link AuthenticationProvider}s will be successively tried until an * AuthenticationProvider indicates it is capable of authenticating the type of * Authentication object passed. Authentication will then be attempted with that * AuthenticationProvider. *

    * If more than one AuthenticationProvider supports the passed Authentication * object, only the first AuthenticationProvider tried will determine the result. No subsequent * AuthenticationProviders will be tried. * * @param authentication the authentication request object. * * @return a fully authenticated object including credentials. * * @throws AuthenticationException if authentication fails. */ public Authentication doAuthentication(Authentication authentication) throws AuthenticationException { Iterator iter = getProviders().iterator(); Class toTest = authentication.getClass(); AuthenticationException lastException = null; while (iter.hasNext()) { AuthenticationProvider provider = (AuthenticationProvider) iter.next(); if (!provider.supports(toTest)) { continue; } logger.debug("Authentication attempt using " + provider.getClass().getName()); Authentication result; try { result = provider.authenticate(authentication); if (result != null) { copyDetails(authentication, result); sessionController.checkAuthenticationAllowed(result); } } catch (AuthenticationException ae) { lastException = ae; result = null; } // SEC-546: Avoid polling additional providers if auth failure is due to invalid account status or // disallowed concurrent login. if (lastException instanceof AccountStatusException || lastException instanceof ConcurrentLoginException) { break; } if (result != null) { sessionController.registerSuccessfulAuthentication(result); publishEvent(new AuthenticationSuccessEvent(result)); return result; } } if (lastException == null) { lastException = new ProviderNotFoundException(messages.getMessage("ProviderManager.providerNotFound", new Object[] {toTest.getName()}, "No AuthenticationProvider found for {0}")); } publishAuthenticationFailure(lastException, authentication); throw lastException; } private void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) { String className = exceptionMappings.getProperty(exception.getClass().getName()); AbstractAuthenticationEvent event = null; if (className != null) { try { Class clazz = getClass().getClassLoader().loadClass(className); Constructor constructor = clazz.getConstructor(new Class[] { Authentication.class, AuthenticationException.class }); Object obj = constructor.newInstance(new Object[] {authentication, exception}); Assert.isInstanceOf(AbstractAuthenticationEvent.class, obj, "Must be an AbstractAuthenticationEvent"); event = (AbstractAuthenticationEvent) obj; } catch (ClassNotFoundException ignored) {} catch (NoSuchMethodException ignored) {} catch (IllegalAccessException ignored) {} catch (InstantiationException ignored) {} catch (InvocationTargetException ignored) {} } if (event != null) { publishEvent(event); } else { if (logger.isDebugEnabled()) { logger.debug("No event was found for the exception " + exception.getClass().getName()); } } } /** * Copies the authentication details from a source Authentication object to a destination one, provided the * latter does not already have one set. * * @param source source authentication * @param dest the destination authentication object */ private void copyDetails(Authentication source, Authentication dest) { if ((dest instanceof AbstractAuthenticationToken) && (dest.getDetails() == null)) { AbstractAuthenticationToken token = (AbstractAuthenticationToken) dest; token.setDetails(source.getDetails()); } } public List getProviders() { if (providers == null || providers.size() == 0) { throw new IllegalArgumentException("A list of AuthenticationProviders is required"); } return providers; } /** * The configured {@link ConcurrentSessionController} is returned or the {@link * NullConcurrentSessionController} if a specific one has not been set. * * @return {@link ConcurrentSessionController} instance */ public ConcurrentSessionController getSessionController() { return sessionController; } public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } /** * Sets the {@link AuthenticationProvider} objects to be used for authentication. * * @param providers the list of authentication providers which will be used to process authentication requests. * * @throws IllegalArgumentException if the list is empty or null, or any of the elements in the list is not an * AuthenticationProvider instance. */ public void setProviders(List providers) { Assert.notEmpty(providers, "A list of AuthenticationProviders is required"); Iterator iter = providers.iterator(); while (iter.hasNext()) { Object currentObject = iter.next(); Assert.isInstanceOf(AuthenticationProvider.class, currentObject, "Can only provide AuthenticationProvider instances"); } this.providers = providers; } /** * Set the {@link ConcurrentSessionController} to be used for limiting users' sessions. The {@link * NullConcurrentSessionController} is used by default. * * @param sessionController {@link ConcurrentSessionController} */ public void setSessionController(ConcurrentSessionController sessionController) { this.sessionController = sessionController; } private void publishEvent(ApplicationEvent event) { if (applicationEventPublisher != null) { applicationEventPublisher.publishEvent(event); } } /** * Sets additional exception to event mappings. These are automatically merged with the default * exception to event mappings that ProviderManager defines. * * @param additionalExceptionMappings where keys are the fully-qualified string name of the exception class and the * values are the fully-qualified string name of the event class to fire. */ public void setAdditionalExceptionMappings(Properties additionalExceptionMappings) { this.additionalExceptionMappings = additionalExceptionMappings; } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000755000000000000000000000000011623520776030516 5ustar ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/JaasAuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000004624711623520776030535 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas; import org.springframework.security.SpringSecurityException; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.GrantedAuthority; import org.springframework.security.context.HttpSessionContextIntegrationFilter; import org.springframework.security.context.SecurityContext; import org.springframework.security.providers.AuthenticationProvider; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.providers.jaas.event.JaasAuthenticationFailedEvent; import org.springframework.security.providers.jaas.event.JaasAuthenticationSuccessEvent; import org.springframework.security.ui.session.HttpSessionDestroyedEvent; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.*; import org.springframework.core.io.Resource; import org.springframework.util.Assert; import java.io.IOException; import java.security.Principal; import java.security.Security; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.Configuration; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; /** * An {@link AuthenticationProvider} implementation that retrieves user details from a JAAS login configuration. * *

    This AuthenticationProvider is capable of validating {@link * org.springframework.security.providers.UsernamePasswordAuthenticationToken} requests contain the correct username and * password.

    *

    This implementation is backed by a JAAS configuration. The * loginConfig property must be set to a given JAAS configuration file. This setter accepts a Spring {@link * org.springframework.core.io.Resource} instance. It should point to a JAAS configuration file containing an index * matching the {@link #setLoginContextName(java.lang.String) loginContextName} property. *

    *

    * For example: If this JaasAuthenticationProvider were configured in a Spring WebApplicationContext the xml to * set the loginConfiguration could be as follows... *

     * <property name="loginConfig">
     *   <value>/WEB-INF/login.conf</value>
     * </property>
     * 
    *

    *

    * The loginContextName should coincide with a given index in the loginConfig specifed. The loginConfig file * used in the JUnit tests appears as the following... *

     JAASTest {
     *   org.springframework.security.providers.jaas.TestLoginModule required;
     * };
     * 
    * Using the example login configuration above, the loginContextName property would be set as JAASTest... *
     *  <property name="loginContextName"> <value>JAASTest</value> </property>
     * 
    *

    *

    When using JAAS login modules as the authentication source, sometimes the * LoginContext will * require CallbackHandlers. The JaasAuthenticationProvider uses an internal * CallbackHandler * to wrap the {@link JaasAuthenticationCallbackHandler}s configured in the ApplicationContext. * When the LoginContext calls the internal CallbackHandler, control is passed to each * {@link JaasAuthenticationCallbackHandler} for each Callback passed. *

    *

    {@link JaasAuthenticationCallbackHandler}s are passed to the JaasAuthenticationProvider through the {@link * #setCallbackHandlers(org.springframework.security.providers.jaas.JaasAuthenticationCallbackHandler[]) callbackHandlers} * property. *

     * <property name="callbackHandlers">
     *   <list>
     *     <bean class="org.springframework.security.providers.jaas.TestCallbackHandler"/>
     *     <bean class="{@link JaasNameCallbackHandler org.springframework.security.providers.jaas.JaasNameCallbackHandler}"/>
     *     <bean class="{@link JaasPasswordCallbackHandler org.springframework.security.providers.jaas.JaasPasswordCallbackHandler}"/>
     *  </list>
     * </property>
     * 
    *

    *

    * After calling LoginContext.login(), the JaasAuthenticationProvider will retrieve the returned Principals * from the Subject (LoginContext.getSubject().getPrincipals). Each returned principal is then passed to the * configured {@link AuthorityGranter}s. An AuthorityGranter is a mapping between a returned Principal, and a role * name. If an AuthorityGranter wishes to grant an Authorization a role, it returns that role name from it's {@link * AuthorityGranter#grant(java.security.Principal)} method. The returned role will be applied to the Authorization * object as a {@link GrantedAuthority}.

    *

    AuthorityGranters are configured in spring xml as follows... *

     * <property name="authorityGranters">
     *   <list>
     *     <bean class="org.springframework.security.providers.jaas.TestAuthorityGranter"/>
     *   </list>
     *  </property>
     * 
    * A configuration note: The JaasAuthenticationProvider uses the security properites * "e;login.config.url.X"e; to configure jaas. If you would like to customize the way Jaas gets configured, * create a subclass of this and override the {@link #configureJaas(Resource)} method. *

    * * @author Ray Krueger * @version $Id$ */ public class JaasAuthenticationProvider implements AuthenticationProvider, ApplicationEventPublisherAware, InitializingBean, ApplicationListener { //~ Static fields/initializers ===================================================================================== protected static final Log log = LogFactory.getLog(JaasAuthenticationProvider.class); //~ Instance fields ================================================================================================ private LoginExceptionResolver loginExceptionResolver = new DefaultLoginExceptionResolver(); private Resource loginConfig; private String loginContextName = "SPRINGSECURITY"; private AuthorityGranter[] authorityGranters; private JaasAuthenticationCallbackHandler[] callbackHandlers; private ApplicationEventPublisher applicationEventPublisher; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(loginConfig, "loginConfig must be set on " + getClass()); Assert.hasLength(loginContextName, "loginContextName must be set on " + getClass()); configureJaas(loginConfig); Assert.notNull(Configuration.getConfiguration(), "As per http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/login/Configuration.html " + "\"If a Configuration object was set via the Configuration.setConfiguration method, then that object is " + "returned. Otherwise, a default Configuration object is returned\". Your JRE returned null to " + "Configuration.getConfiguration()."); } /** * Attempts to login the user given the Authentication objects principal and credential * * @param auth The Authentication object to be authenticated. * * @return The authenticated Authentication object, with it's grantedAuthorities set. * * @throws AuthenticationException This implementation does not handle 'locked' or 'disabled' accounts. This method * only throws a AuthenticationServiceException, with the message of the LoginException that will be * thrown, should the loginContext.login() method fail. */ public Authentication authenticate(Authentication auth) throws AuthenticationException { if (auth instanceof UsernamePasswordAuthenticationToken) { UsernamePasswordAuthenticationToken request = (UsernamePasswordAuthenticationToken) auth; try { //Create the LoginContext object, and pass our InternallCallbackHandler LoginContext loginContext = new LoginContext(loginContextName, new InternalCallbackHandler(auth)); //Attempt to login the user, the LoginContext will call our InternalCallbackHandler at this point. loginContext.login(); //create a set to hold the authorities Set authorities = new HashSet(); //get the subject principals and pass them to each of the AuthorityGranters Set principals = loginContext.getSubject().getPrincipals(); for (Iterator iterator = principals.iterator(); iterator.hasNext();) { Principal principal = (Principal) iterator.next(); for (int i = 0; i < authorityGranters.length; i++) { AuthorityGranter granter = authorityGranters[i]; Set roles = granter.grant(principal); //If the granter doesn't wish to grant any authorities, it should return null. if ((roles != null) && !roles.isEmpty()) { for (Iterator roleIterator = roles.iterator(); roleIterator.hasNext();) { String role = roleIterator.next().toString(); authorities.add(new JaasGrantedAuthority(role, principal)); } } } } //Convert the authorities set back to an array and apply it to the token. JaasAuthenticationToken result = new JaasAuthenticationToken(request.getPrincipal(), request.getCredentials(), (GrantedAuthority[]) authorities.toArray(new GrantedAuthority[authorities.size()]), loginContext); //Publish the success event publishSuccessEvent(result); //we're done, return the token. return result; } catch (LoginException loginException) { SpringSecurityException ase = loginExceptionResolver.resolveException(loginException); publishFailureEvent(request, ase); throw ase; } } return null; } /** * Hook method for configuring Jaas * * @param loginConfig URL to Jaas login configuration * * @throws IOException if there is a problem reading the config resource. */ protected void configureJaas(Resource loginConfig) throws IOException { configureJaasUsingLoop(); // Overcome issue in SEC-760 Configuration.getConfiguration().refresh(); } /** * Loops through the login.config.url.1,login.config.url.2 properties looking for the login configuration. * If it is not set, it will be set to the last available login.config.url.X property. * */ private void configureJaasUsingLoop() throws IOException { String loginConfigUrl = loginConfig.getURL().toString(); boolean alreadySet = false; int n = 1; String prefix = "login.config.url."; String existing = null; while ((existing = Security.getProperty(prefix + n)) != null) { alreadySet = existing.equals(loginConfigUrl); if (alreadySet) { break; } n++; } if (!alreadySet) { String key = prefix + n; log.debug("Setting security property [" + key + "] to: " + loginConfigUrl); Security.setProperty(key, loginConfigUrl); } } /** * Returns the AuthorityGrannter array that was passed to the {@link * #setAuthorityGranters(AuthorityGranter[])} method, or null if it none were ever set. * * @return The AuthorityGranter array, or null * * @see #setAuthorityGranters(AuthorityGranter[]) */ public AuthorityGranter[] getAuthorityGranters() { return authorityGranters; } /** * Returns the current JaasAuthenticationCallbackHandler array, or null if none are set. * * @return the JAASAuthenticationCallbackHandlers. * * @see #setCallbackHandlers(JaasAuthenticationCallbackHandler[]) */ public JaasAuthenticationCallbackHandler[] getCallbackHandlers() { return callbackHandlers; } public Resource getLoginConfig() { return loginConfig; } public String getLoginContextName() { return loginContextName; } public LoginExceptionResolver getLoginExceptionResolver() { return loginExceptionResolver; } /** * Handles the logout by getting the SecurityContext for the session that was destroyed. MUST NOT use * SecurityContextHolder we are logging out a session that is not related to the current user. * * @param event */ protected void handleLogout(HttpSessionDestroyedEvent event) { SecurityContext context = (SecurityContext) event.getSession().getAttribute(HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY); if (context == null) { log.debug("The destroyed session has no SecurityContext"); return; } Authentication auth = context.getAuthentication(); if ((auth != null) && (auth instanceof JaasAuthenticationToken)) { JaasAuthenticationToken token = (JaasAuthenticationToken) auth; try { LoginContext loginContext = token.getLoginContext(); if (loginContext != null) { log.debug("Logging principal: [" + token.getPrincipal() + "] out of LoginContext"); loginContext.logout(); } else { log.debug("Cannot logout principal: [" + token.getPrincipal() + "] from LoginContext. " + "The LoginContext is unavailable"); } } catch (LoginException e) { log.warn("Error error logging out of LoginContext", e); } } } public void onApplicationEvent(ApplicationEvent applicationEvent) { if (applicationEvent instanceof HttpSessionDestroyedEvent) { HttpSessionDestroyedEvent event = (HttpSessionDestroyedEvent) applicationEvent; handleLogout(event); } } /** * Publishes the {@link JaasAuthenticationFailedEvent}. Can be overridden by subclasses for different * functionality * * @param token The {@link UsernamePasswordAuthenticationToken} being processed * @param ase The {@link SpringSecurityException} that caused the failure */ protected void publishFailureEvent(UsernamePasswordAuthenticationToken token, SpringSecurityException ase) { applicationEventPublisher.publishEvent(new JaasAuthenticationFailedEvent(token, ase)); } /** * Publishes the {@link JaasAuthenticationSuccessEvent}. Can be overridden by subclasses for different * functionality. * * @param token The {@link UsernamePasswordAuthenticationToken} being processed */ protected void publishSuccessEvent(UsernamePasswordAuthenticationToken token) { if (applicationEventPublisher != null) { applicationEventPublisher.publishEvent(new JaasAuthenticationSuccessEvent(token)); } } /** * Set the AuthorityGranters that should be consulted for role names to be granted to the Authentication. * * @param authorityGranters AuthorityGranter array * * @see JaasAuthenticationProvider */ public void setAuthorityGranters(AuthorityGranter[] authorityGranters) { this.authorityGranters = authorityGranters; } /** * Set the JAASAuthentcationCallbackHandler array to handle callback objects generated by the * LoginContext.login method. * * @param callbackHandlers Array of JAASAuthenticationCallbackHandlers */ public void setCallbackHandlers(JaasAuthenticationCallbackHandler[] callbackHandlers) { this.callbackHandlers = callbackHandlers; } /** * Set the JAAS login configuration file. * * @param loginConfig Spring * Resource * * @see JAAS Reference */ public void setLoginConfig(Resource loginConfig) { this.loginConfig = loginConfig; } /** * Set the loginContextName, this name is used as the index to the configuration specified in the * loginConfig property. * * @param loginContextName */ public void setLoginContextName(String loginContextName) { this.loginContextName = loginContextName; } public void setLoginExceptionResolver(LoginExceptionResolver loginExceptionResolver) { this.loginExceptionResolver = loginExceptionResolver; } public boolean supports(Class aClass) { return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass); } public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } protected ApplicationEventPublisher getApplicationEventPublisher() { return applicationEventPublisher; } //~ Inner Classes ================================================================================================== /** * Wrapper class for JAASAuthenticationCallbackHandlers */ private class InternalCallbackHandler implements CallbackHandler { private Authentication authentication; public InternalCallbackHandler(Authentication authentication) { this.authentication = authentication; } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbackHandlers.length; i++) { JaasAuthenticationCallbackHandler handler = callbackHandlers[i]; for (int j = 0; j < callbacks.length; j++) { Callback callback = callbacks[j]; handler.handle(callback, authentication); } } } } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/JaasAuthenticationToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000404111623517156030515 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas; import org.springframework.security.GrantedAuthority; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import javax.security.auth.login.LoginContext; /** * UsernamePasswordAuthenticationToken extension to carry the Jaas LoginContext that the user was logged into * * @author Ray Krueger */ public class JaasAuthenticationToken extends UsernamePasswordAuthenticationToken { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private transient LoginContext loginContext = null; //~ Constructors =================================================================================================== public JaasAuthenticationToken(Object principal, Object credentials, LoginContext loginContext) { super(principal, credentials); this.loginContext = loginContext; } public JaasAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities, LoginContext loginContext) { super(principal, credentials, authorities); this.loginContext = loginContext; } //~ Methods ======================================================================================================== public LoginContext getLoginContext() { return loginContext; } } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/DefaultLoginExceptionResolver.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000253711623517156030525 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas; import org.springframework.security.SpringSecurityException; import org.springframework.security.AuthenticationServiceException; import javax.security.auth.login.LoginException; /** * This LoginExceptionResolver simply wraps the LoginException with an AuthenticationServiceException. * * @author Ray Krueger * @version $Revision: 2142 $ */ public class DefaultLoginExceptionResolver implements LoginExceptionResolver { //~ Methods ======================================================================================================== public SpringSecurityException resolveException(LoginException e) { return new AuthenticationServiceException(e.getMessage(), e); } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/JaasPasswordCallbackHandler.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000450311623517156030520 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas; import org.springframework.security.Authentication; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; /** * The most basic Callbacks to be handled when using a LoginContext from JAAS, are the NameCallback and * PasswordCallback. Spring Security provides the JaasPasswordCallbackHandler specifically tailored to * handling the PasswordCallback.
    * * @author Ray Krueger * @version $Id$ * * @see Callback * @see * PasswordCallback */ public class JaasPasswordCallbackHandler implements JaasAuthenticationCallbackHandler { //~ Methods ======================================================================================================== /** * If the callback passed to the 'handle' method is an instance of PasswordCallback, the * JaasPasswordCallbackHandler will call, callback.setPassword(authentication.getCredentials().toString()). * * @param callback * @param auth * * @throws IOException * @throws UnsupportedCallbackException */ public void handle(Callback callback, Authentication auth) throws IOException, UnsupportedCallbackException { if (callback instanceof PasswordCallback) { PasswordCallback pc = (PasswordCallback) callback; pc.setPassword(auth.getCredentials().toString().toCharArray()); } } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000010311623517156030510 0ustar An authentication provider for JAAS. ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/event/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000755000000000000000000000000011623517156030514 5ustar ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/event/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000014511623517156030516 0ustar Enables JAAS events to be published to the Spring application context. ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/event/JaasAuthenticationFailedEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000307511623517156030523 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas.event; import org.springframework.security.Authentication; /** * Fired when LoginContext.login throws a LoginException, or if any other exception is thrown during that time. * * @author Ray Krueger * @version $Id$ */ public class JaasAuthenticationFailedEvent extends JaasAuthenticationEvent { //~ Instance fields ================================================================================================ private Exception exception; //~ Constructors =================================================================================================== public JaasAuthenticationFailedEvent(Authentication auth, Exception exception) { super(auth); this.exception = exception; } //~ Methods ======================================================================================================== public Exception getException() { return exception; } } ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/event/JaasAuthenticationSuccessEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000245711623517156030526 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas.event; import org.springframework.security.Authentication; /** * Fired by the {@link org.springframework.security.providers.jaas.JaasAuthenticationProvider JaasAuthenticationProvider} * after successfully logging the user into the LoginContext, handling all callbacks, and calling all * AuthorityGranters. * * @author Ray Krueger * @version $Id$ */ public class JaasAuthenticationSuccessEvent extends JaasAuthenticationEvent { //~ Constructors =================================================================================================== public JaasAuthenticationSuccessEvent(Authentication auth) { super(auth); } } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/event/JaasAuthenticationEvent.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000327711623517156030527 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas.event; import org.springframework.security.Authentication; import org.springframework.context.ApplicationEvent; /** * Parent class for events fired by the {@link org.springframework.security.providers.jaas.JaasAuthenticationProvider * JaasAuthenticationProvider}. * * @author Ray Krueger * @version $Id$ */ public abstract class JaasAuthenticationEvent extends ApplicationEvent { //~ Constructors =================================================================================================== /** * The Authentication object is stored as the ApplicationEvent 'source'. * * @param auth */ public JaasAuthenticationEvent(Authentication auth) { super(auth); } //~ Methods ======================================================================================================== /** * Pre-casted method that returns the 'source' of the event. * * @return the Authentication */ public Authentication getAuthentication() { return (Authentication) source; } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/JaasAuthenticationCallbackHandler.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000516211623517156030522 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas; import org.springframework.security.Authentication; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.UnsupportedCallbackException; /** * The JaasAuthenticationCallbackHandler is similar to the * javax.security.auth.callback.CallbackHandler interface in that it defines a * handle method. The JaasAuthenticationCallbackHandler is only asked to * handle one Callback instance at at time rather than an array of all * Callbacks, as the javax... CallbackHandler defines. * *

    * Before a JaasAuthenticationCallbackHandler is asked to 'handle' any * callbacks, it is first passed the Authentication object that the login * attempt is for. NOTE: The Authentication object has not been * 'authenticated' yet. *

    * * @author Ray Krueger * @version $Id$ * * @see JaasNameCallbackHandler * @see JaasPasswordCallbackHandler * @see Callback * @see * CallbackHandler */ public interface JaasAuthenticationCallbackHandler { //~ Methods ======================================================================================================== /** * Handle the Callback. The * handle method will be called for every callback instance sent from the LoginContext. Meaning that The handle * method may be called multiple times for a given JaasAuthenticationCallbackHandler. * * @param callback * @param auth The Authentication object currently being authenticated. * * @throws IOException * @throws UnsupportedCallbackException */ void handle(Callback callback, Authentication auth) throws IOException, UnsupportedCallbackException; } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/JaasNameCallbackHandler.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000514611623517156030524 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas; import org.springframework.security.Authentication; import org.springframework.security.userdetails.UserDetails; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.UnsupportedCallbackException; /** * The most basic Callbacks to be handled when using a LoginContext from JAAS, are the NameCallback and * PasswordCallback. Spring Security provides the JaasNameCallbackHandler specifically tailored to * handling the NameCallback.
    * * @author Ray Krueger * @version $Id$ * * @see Callback * @see NameCallback */ public class JaasNameCallbackHandler implements JaasAuthenticationCallbackHandler { //~ Methods ======================================================================================================== /** * If the callback passed to the 'handle' method is an instance of NameCallback, the * JaasNameCallbackHandler will call, callback.setName(authentication.getPrincipal().toString()). * * @param callback * @param authentication * * @throws IOException * @throws UnsupportedCallbackException */ public void handle(Callback callback, Authentication authentication) throws IOException, UnsupportedCallbackException { if (callback instanceof NameCallback) { NameCallback ncb = (NameCallback) callback; String username = ""; Object principal = authentication.getPrincipal(); if (principal instanceof UserDetails) { username = ((UserDetails) principal).getUsername(); } else { username = principal.toString(); } ncb.setName(username); } } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/LoginExceptionResolver.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000334411623517156030522 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas; import org.springframework.security.SpringSecurityException; import javax.security.auth.login.LoginException; /** * The JaasAuthenticationProvider takes an instance of LoginExceptionResolver * to resolve LoginModule specific exceptions to Spring Security exceptions. For * instance, a configured login module could throw a * ScrewedUpPasswordException that extends LoginException, in this instance * the LoginExceptionResolver implementation would return a {@link * org.springframework.security.BadCredentialsException}. * * @author Ray Krueger * @version $Revision: 2176 $ */ public interface LoginExceptionResolver { //~ Methods ======================================================================================================== /** * Translates a Jaas LoginException to an SpringSecurityException. * * @param e The LoginException thrown by the configured LoginModule. * * @return The SpringSecurityException that the JaasAuthenticationProvider should throw. */ SpringSecurityException resolveException(LoginException e); } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/AuthorityGranter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000375511623517156030530 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas; import java.security.Principal; import java.util.Set; /** * The AuthorityGranter interface is used to map a given principal to role * names. * *

    * If a Windows NT login module were to be used from JAAS, an AuthrityGranter * implementation could be created to map a NT Group Principal to a ROLE_USER * role for instance.
    *

    * * @author Ray Krueger * @version $Id$ */ public interface AuthorityGranter { //~ Methods ======================================================================================================== /** * The grant method is called for each principal returned from the LoginContext subject. If the * AuthorityGranter wishes to grant any authorities, it should return a java.util.Set containing the role names it * wishes to grant, such as ROLE_USER. If the AuthrityGranter does not wish to grant any authorities it should * return null.
    * The set may contain any object as all objects in the returned set will be passed to the JaasGrantedAuthority * constructor using toString(). * * @param principal One of the principals from the LoginContext.getSubect().getPrincipals() method. * * @return A java.util.Set of role names to grant, or null meaning no roles should be granted for the principal. */ Set grant(Principal principal); } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/SecurityContextLoginModule.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000001357711623517156030533 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas; import org.springframework.security.Authentication; import org.springframework.security.context.SecurityContextHolder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; /** * An implementation of {@link LoginModule} that uses a Spring Security {@link * org.springframework.security.context.SecurityContext SecurityContext} to provide authentication.

    This LoginModule * provides opposite functionality to the {@link JaasAuthenticationProvider} API, and should not really be used in * conjunction with it.

    *

    The {@link JaasAuthenticationProvider} allows Spring Security to authenticate against Jaas.

    *

    The SecurityContextLoginModule allows a Jaas based application to authenticate against Spring Security. * If there is no Authentication in the {@link SecurityContextHolder} the login() method will throw a LoginException * by default. * This functionality can be changed with the ignoreMissingAuthentication option by setting it to "true". * Setting ignoreMissingAuthentication=true will tell the SecurityContextLoginModule to simply return false and be * ignored if the authentication is null.

    * * @author Brian Moseley * @author Ray Krueger */ public class SecurityContextLoginModule implements LoginModule { //~ Static fields/initializers ===================================================================================== private static final Log log = LogFactory.getLog(SecurityContextLoginModule.class); //~ Instance fields ================================================================================================ private Authentication authen; private Subject subject; private boolean ignoreMissingAuthentication = false; //~ Methods ======================================================================================================== /** * Abort the authentication process by forgetting the Spring Security Authentication. * * @return true if this method succeeded, or false if this LoginModule should be ignored. * * @exception LoginException if the abort fails */ public boolean abort() throws LoginException { if (authen == null) { return false; } authen = null; return true; } /** * Authenticate the Subject (phase two) by adding the Spring Security * Authentication to the Subject's principals. * * @return true if this method succeeded, or false if this LoginModule should be ignored. * * @exception LoginException if the commit fails */ public boolean commit() throws LoginException { if (authen == null) { return false; } subject.getPrincipals().add(authen); return true; } Authentication getAuthentication() { return authen; } Subject getSubject() { return subject; } /** * Initialize this LoginModule. Ignores the callback handler, since the code establishing the * LoginContext likely won't provide one that understands Spring Security. Also ignores the * sharedState and options parameters, since none are recognized. * * @param subject the Subject to be authenticated.

    * @param callbackHandler is ignored * @param sharedState is ignored * @param options are ignored */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { this.subject = subject; if (options != null) { ignoreMissingAuthentication = "true".equals(options.get("ignoreMissingAuthentication")); } } /** * Authenticate the Subject (phase one) by extracting the Spring Security * Authentication from the current SecurityContext. * * @return true if the authentication succeeded, or false if this LoginModule should be ignored. * * @throws LoginException if the authentication fails */ public boolean login() throws LoginException { authen = SecurityContextHolder.getContext().getAuthentication(); if (authen == null) { String msg = "Login cannot complete, authentication not found in security context"; if (ignoreMissingAuthentication) { log.warn(msg); return false; } else { throw new LoginException(msg); } } return true; } /** * Log out the Subject. * * @return true if this method succeeded, or false if this LoginModule should be ignored. * * @exception LoginException if the logout fails */ public boolean logout() throws LoginException { if (authen == null) { return false; } subject.getPrincipals().remove(authen); authen = null; return true; } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/JaasGrantedAuthority.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/jaas/0000644000000000000000000000325011623517156030516 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.jaas; import org.springframework.security.GrantedAuthorityImpl; import java.security.Principal; /** * Extends GrantedAuthorityImpl to hold the principal that an AuthorityGranter justified as a reason to grant this * Authority.
    * * @author Ray Krueger * @version $Id$ * * @see AuthorityGranter */ public class JaasGrantedAuthority extends GrantedAuthorityImpl { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Principal principal; //~ Constructors =================================================================================================== public JaasGrantedAuthority(String role, Principal principal) { super(role); this.principal = principal; } //~ Methods ======================================================================================================== public Principal getPrincipal() { return principal; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/AuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/Authe0000644000000000000000000000571011623517156030572 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; /** * Indicates a class can process a specific {@link * org.springframework.security.Authentication} implementation. * * @author Ben Alex * @version $Id$ */ public interface AuthenticationProvider { //~ Methods ======================================================================================================== /** * Performs authentication with the same contract as {@link * org.springframework.security.AuthenticationManager#authenticate(Authentication)}. * * @param authentication the authentication request object. * * @return a fully authenticated object including credentials. May return null if the * AuthenticationProvider is unable to support authentication of the passed * Authentication object. In such a case, the next AuthenticationProvider that * supports the presented Authentication class will be tried. * * @throws AuthenticationException if authentication fails. */ Authentication authenticate(Authentication authentication) throws AuthenticationException; /** * Returns true if this AuthenticationProvider supports the indicated * Authentication object. *

    * Returning true does not guarantee an AuthenticationProvider will be able to * authenticate the presented instance of the Authentication class. It simply indicates it can support * closer evaluation of it. An AuthenticationProvider can still return null from the * {@link #authenticate(Authentication)} method to indicate another AuthenticationProvider should be * tried. *

    *

    Selection of an AuthenticationProvider capable of performing authentication is * conducted at runtime the ProviderManager.

    * * @param authentication DOCUMENT ME! * * @return true if the implementation can more closely evaluate the Authentication class * presented */ boolean supports(Class authentication); } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/AbstractAuthenticationToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/Abstr0000644000000000000000000001656511623517156030611 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers; import java.security.Principal; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; import org.springframework.security.userdetails.UserDetails; import org.springframework.util.Assert; /** * Base class for Authentication objects.

    Implementations which use this class should be immutable.

    * * @author Ben Alex * @author Luke Taylor * @version $Id$ */ public abstract class AbstractAuthenticationToken implements Authentication { //~ Instance fields ================================================================================================ private Object details; private GrantedAuthority[] authorities; private boolean authenticated = false; //~ Constructors =================================================================================================== /** * Retained for compatibility with subclasses written before the * AbstractAuthenticationToken(GrantedAuthority[]) constructor * was introduced. * * @deprecated in favour of the constructor which takes a * GrantedAuthority[] argument. */ public AbstractAuthenticationToken() { } /** * Creates a token with the supplied array of authorities. * * @param authorities the list of GrantedAuthoritys for the * principal represented by this authentication object. A * null value indicates that no authorities have been * granted (pursuant to the interface contract specified by {@link * Authentication#getAuthorities()}null should only be * presented if the principal has not been authenticated). */ public AbstractAuthenticationToken(GrantedAuthority[] authorities) { if (authorities != null) { for (int i = 0; i < authorities.length; i++) { Assert.notNull(authorities[i], "Granted authority element " + i + " is null - GrantedAuthority[] cannot contain any null elements"); } } this.authorities = authorities; } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (obj instanceof AbstractAuthenticationToken) { AbstractAuthenticationToken test = (AbstractAuthenticationToken) obj; if (!((this.getAuthorities() == null) && (test.getAuthorities() == null))) { if ((this.getAuthorities() == null) || (test.getAuthorities() == null)) { return false; } if (this.getAuthorities().length != test.getAuthorities().length) { return false; } for (int i = 0; i < this.getAuthorities().length; i++) { if (!this.getAuthorities()[i].equals(test.getAuthorities()[i])) { return false; } } } if ((this.details == null) && (test.getDetails() != null)) { return false; } if ((this.details != null) && (test.getDetails() == null)) { return false; } if ((this.details != null) && (!this.details.equals(test.getDetails()))) { return false; } if ((this.getCredentials() == null) && (test.getCredentials() != null)) { return false; } if ((this.getCredentials() != null) && !this.getCredentials().equals(test.getCredentials())) { return false; } if (this.getPrincipal() == null && test.getPrincipal() != null) { return false; } if (this.getPrincipal() != null && !this.getPrincipal().equals(test.getPrincipal())) { return false; } return this.isAuthenticated() == test.isAuthenticated(); } return false; } public GrantedAuthority[] getAuthorities() { if (authorities == null) { return null; } GrantedAuthority[] copy = new GrantedAuthority[authorities.length]; System.arraycopy(authorities, 0, copy, 0, authorities.length); return copy; } public Object getDetails() { return details; } public String getName() { if (this.getPrincipal() instanceof UserDetails) { return ((UserDetails) this.getPrincipal()).getUsername(); } if (getPrincipal() instanceof Principal) { return ((Principal)getPrincipal()).getName(); } return (this.getPrincipal() == null) ? "" : this.getPrincipal().toString(); } public int hashCode() { int code = 31; // Copy authorities to local variable for performance (SEC-223) GrantedAuthority[] authorities = this.getAuthorities(); if (authorities != null) { for (int i = 0; i < authorities.length; i++) { code ^= authorities[i].hashCode(); } } if (this.getPrincipal() != null) { code ^= this.getPrincipal().hashCode(); } if (this.getCredentials() != null) { code ^= this.getCredentials().hashCode(); } if (this.getDetails() != null) { code ^= this.getDetails().hashCode(); } if (this.isAuthenticated()) { code ^= -37; } return code; } public boolean isAuthenticated() { return authenticated; } public void setAuthenticated(boolean authenticated) { this.authenticated = authenticated; } public void setDetails(Object details) { this.details = details; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString()).append(": "); sb.append("Principal: ").append(this.getPrincipal()).append("; "); sb.append("Password: [PROTECTED]; "); sb.append("Authenticated: ").append(this.isAuthenticated()).append("; "); sb.append("Details: ").append(this.getDetails()).append("; "); if (this.getAuthorities() != null) { sb.append("Granted Authorities: "); for (int i = 0; i < this.getAuthorities().length; i++) { if (i > 0) { sb.append(", "); } sb.append(this.getAuthorities()[i].toString()); } } else { sb.append("Not granted any authorities"); } return sb.toString(); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/0000755000000000000000000000000011623517156030516 5ustar ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/LdapAuthenticator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/0000644000000000000000000000322411623517156030521 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.ldap; import org.springframework.security.Authentication; import org.springframework.ldap.core.DirContextOperations; /** * The strategy interface for locating and authenticating an Ldap user. *

    * The LdapAuthenticationProvider calls this interface to authenticate a user * and obtain the information for that user from the directory. * * @author Luke Taylor * @version $Id$ * * @see org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator * @see org.springframework.security.ldap.populator.UserDetailsServiceLdapAuthoritiesPopulator */ public interface LdapAuthenticator { //~ Methods ======================================================================================================== /** * Authenticates as a user and obtains additional user information from the directory. * * @param authentication * @return the details of the successfully authenticated user. */ DirContextOperations authenticate(Authentication authentication); } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/0000644000000000000000000000064211623517156030522 0ustar

    The LDAP authentication provider package. Interfaces are provided for both authentication and retrieval of user roles from an LDAP server.

    The main provider class is LdapAuthenticationProvider. This is configured with an LdapAuthenticator instance and an LdapAuthoritiesPopulator. The latter is used to obtain the list of roles for the user.

    ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/authenticator/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/0000755000000000000000000000000011623517156030516 5ustar ././@LongLink0000000000000000000000000000022700000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/authenticator/PasswordComparisonAuthenticator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/0000644000000000000000000001205211623517156030520 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.ldap.authenticator; import org.springframework.security.Authentication; import org.springframework.security.BadCredentialsException; import org.springframework.security.ldap.LdapUtils; import org.springframework.security.ldap.SpringSecurityLdapTemplate; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.providers.encoding.PasswordEncoder; import org.springframework.security.userdetails.UsernameNotFoundException; import org.springframework.ldap.NameNotFoundException; import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.support.BaseLdapPathContextSource; import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Iterator; /** * An {@link org.springframework.security.providers.ldap.LdapAuthenticator LdapAuthenticator} which compares the login * password with the value stored in the directory using a remote LDAP "compare" operation. * *

    * If passwords are stored in digest form in the repository, then a suitable {@link PasswordEncoder} * implementation must be supplied. By default, passwords are encoded using the {@link LdapShaPasswordEncoder}. * * @author Luke Taylor * @version $Id$ */ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthenticator { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(PasswordComparisonAuthenticator.class); //~ Instance fields ================================================================================================ private PasswordEncoder passwordEncoder = new LdapShaPasswordEncoder(); private String passwordAttributeName = "userPassword"; //~ Constructors =================================================================================================== public PasswordComparisonAuthenticator(BaseLdapPathContextSource contextSource) { super(contextSource); } //~ Methods ======================================================================================================== public DirContextOperations authenticate(final Authentication authentication) { Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, "Can only process UsernamePasswordAuthenticationToken objects"); // locate the user and check the password DirContextOperations user = null; String username = authentication.getName(); String password = (String)authentication.getCredentials(); Iterator dns = getUserDns(username).iterator(); SpringSecurityLdapTemplate ldapTemplate = new SpringSecurityLdapTemplate(getContextSource()); while (dns.hasNext() && user == null) { final String userDn = (String) dns.next(); try { user = ldapTemplate.retrieveEntry(userDn, getUserAttributes()); } catch (NameNotFoundException ignore) { } } if (user == null && getUserSearch() != null) { user = getUserSearch().searchForUser(username); } if (user == null) { throw new UsernameNotFoundException("User not found: " + username, username); } if (logger.isDebugEnabled()) { logger.debug("Performing LDAP compare of password attribute '" + passwordAttributeName + "' for user '" + user.getDn() +"'"); } String encodedPassword = passwordEncoder.encodePassword(password, null); byte[] passwordBytes = LdapUtils.getUtf8Bytes(encodedPassword); if (!ldapTemplate.compare(user.getDn().toString(), passwordAttributeName, passwordBytes)) { throw new BadCredentialsException(messages.getMessage("PasswordComparisonAuthenticator.badCredentials", "Bad credentials")); } return user; } public void setPasswordAttributeName(String passwordAttribute) { Assert.hasLength(passwordAttribute, "passwordAttributeName must not be empty or null"); this.passwordAttributeName = passwordAttribute; } public void setPasswordEncoder(PasswordEncoder passwordEncoder) { Assert.notNull(passwordEncoder, "passwordEncoder must not be null."); this.passwordEncoder = passwordEncoder; } } ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/authenticator/LdapShaPasswordEncoder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/0000644000000000000000000001471011623517156030523 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.ldap.authenticator; import org.springframework.security.providers.encoding.PasswordEncoder; import org.springframework.security.providers.encoding.ShaPasswordEncoder; import org.apache.commons.codec.binary.Base64; import org.springframework.util.Assert; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; /** * A version of {@link ShaPasswordEncoder} which supports Ldap SHA and SSHA (salted-SHA) encodings. The values are * base-64 encoded and have the label "{SHA}" (or "{SSHA}") prepended to the encoded hash. These can be made lower-case * in the encoded password, if required, by setting the forceLowerCasePrefix property to true. * * Also supports plain text passwords, so can safely be used in cases when both encoded and non-encoded passwords are in * use or when a null implementation is required. * * @author Luke Taylor * @version $Id$ */ public class LdapShaPasswordEncoder implements PasswordEncoder { //~ Static fields/initializers ===================================================================================== /** The number of bytes in a SHA hash */ private static final int SHA_LENGTH = 20; private static final String SSHA_PREFIX = "{SSHA}"; private static final String SSHA_PREFIX_LC = SSHA_PREFIX.toLowerCase(); private static final String SHA_PREFIX = "{SHA}"; private static final String SHA_PREFIX_LC = SHA_PREFIX.toLowerCase(); //~ Instance fields ================================================================================================ private boolean forceLowerCasePrefix; //~ Constructors =================================================================================================== public LdapShaPasswordEncoder() {} //~ Methods ======================================================================================================== private byte[] combineHashAndSalt(byte[] hash, byte[] salt) { if (salt == null) { return hash; } byte[] hashAndSalt = new byte[hash.length + salt.length]; System.arraycopy(hash, 0, hashAndSalt, 0, hash.length); System.arraycopy(salt, 0, hashAndSalt, hash.length, salt.length); return hashAndSalt; } /** * Calculates the hash of password (and salt bytes, if supplied) and returns a base64 encoded concatenation * of the hash and salt, prefixed with {SHA} (or {SSHA} if salt was used). * * @param rawPass the password to be encoded. * @param salt the salt. Must be a byte array or null. * * @return the encoded password in the specified format * */ public String encodePassword(String rawPass, Object salt) { MessageDigest sha; try { sha = MessageDigest.getInstance("SHA"); sha.update(rawPass.getBytes("UTF-8")); } catch (java.security.NoSuchAlgorithmException e) { throw new IllegalStateException("No SHA implementation available!"); } catch (UnsupportedEncodingException ue) { throw new IllegalStateException("UTF-8 not supported!"); } if (salt != null) { Assert.isInstanceOf(byte[].class, salt, "Salt value must be a byte array"); sha.update((byte[]) salt); } byte[] hash = combineHashAndSalt(sha.digest(), (byte[]) salt); String prefix; if (salt == null) { prefix = forceLowerCasePrefix ? SHA_PREFIX_LC : SHA_PREFIX; } else { prefix = forceLowerCasePrefix ? SSHA_PREFIX_LC : SSHA_PREFIX; } return prefix + new String(Base64.encodeBase64(hash)); } private byte[] extractSalt(String encPass) { String encPassNoLabel = encPass.substring(6); byte[] hashAndSalt = Base64.decodeBase64(encPassNoLabel.getBytes()); int saltLength = hashAndSalt.length - SHA_LENGTH; byte[] salt = new byte[saltLength]; System.arraycopy(hashAndSalt, SHA_LENGTH, salt, 0, saltLength); return salt; } /** * Checks the validity of an unencoded password against an encoded one in the form * "{SSHA}sQuQF8vj8Eg2Y1hPdh3bkQhCKQBgjhQI". * * @param encPass the actual SSHA or SHA encoded password * @param rawPass unencoded password to be verified. * @param salt ignored. If the format is SSHA the salt bytes will be extracted from the encoded password. * * @return true if they match (independent of the case of the prefix). */ public boolean isPasswordValid(final String encPass, final String rawPass, Object salt) { String prefix = extractPrefix(encPass); if (prefix == null) { return encPass.equals(rawPass); } if (prefix.equals(SSHA_PREFIX) || prefix.equals(SSHA_PREFIX_LC)) { salt = extractSalt(encPass); } else if (!prefix.equals(SHA_PREFIX) && !prefix.equals(SHA_PREFIX_LC)) { throw new IllegalArgumentException("Unsupported password prefix '" + prefix + "'"); } else { // Standard SHA salt = null; } int startOfHash = prefix.length(); String encodedRawPass = encodePassword(rawPass, salt).substring(startOfHash); return encodedRawPass.equals(encPass.substring(startOfHash)); } /** * Returns the hash prefix or null if there isn't one. */ private String extractPrefix(String encPass) { if (!encPass.startsWith("{")) { return null; } int secondBrace = encPass.lastIndexOf('}'); if (secondBrace < 0) { throw new IllegalArgumentException("Couldn't find closing brace for SHA prefix"); } return encPass.substring(0, secondBrace + 1); } public void setForceLowerCasePrefix(boolean forceLowerCasePrefix) { this.forceLowerCasePrefix = forceLowerCasePrefix; } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/authenticator/BindAuthenticator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/0000644000000000000000000001470411623517156030526 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.ldap.authenticator; import java.util.Iterator; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.dao.DataAccessException; import org.springframework.ldap.NamingException; import org.springframework.ldap.core.ContextSource; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.DistinguishedName; import org.springframework.ldap.core.support.BaseLdapPathContextSource; import org.springframework.ldap.support.LdapUtils; import org.springframework.security.Authentication; import org.springframework.security.BadCredentialsException; import org.springframework.security.ldap.SpringSecurityContextSource; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.util.Assert; /** * An authenticator which binds as a user. * * @author Luke Taylor * @version $Id$ * * @see AbstractLdapAuthenticator */ public class BindAuthenticator extends AbstractLdapAuthenticator { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(BindAuthenticator.class); //~ Constructors =================================================================================================== /** * Create an initialized instance using the {@link SpringSecurityContextSource} provided. * * @param contextSource the SpringSecurityContextSource instance against which bind operations will be * performed. * */ public BindAuthenticator(SpringSecurityContextSource contextSource) { super(contextSource); } //~ Methods ======================================================================================================== public DirContextOperations authenticate(Authentication authentication) { DirContextOperations user = null; Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, "Can only process UsernamePasswordAuthenticationToken objects"); String username = authentication.getName(); String password = (String)authentication.getCredentials(); // If DN patterns are configured, try authenticating with them directly Iterator dns = getUserDns(username).iterator(); while (dns.hasNext() && user == null) { user = bindWithDn((String) dns.next(), username, password); } // Otherwise use the configured locator to find the user // and authenticate with the returned DN. if (user == null && getUserSearch() != null) { DirContextOperations userFromSearch = getUserSearch().searchForUser(username); user = bindWithDn(userFromSearch.getDn().toString(), username, password); } if (user == null) { throw new BadCredentialsException( messages.getMessage("BindAuthenticator.badCredentials", "Bad credentials")); } return user; } private DirContextOperations bindWithDn(String userDnStr, String username, String password) { BaseLdapPathContextSource ctxSource = (BaseLdapPathContextSource) getContextSource(); DistinguishedName userDn = new DistinguishedName(userDnStr); DistinguishedName fullDn = new DistinguishedName(userDn); fullDn.prepend(ctxSource.getBaseLdapPath()); BindWithSpecificDnContextSource specificDnContextSource = new BindWithSpecificDnContextSource( (SpringSecurityContextSource) getContextSource(), fullDn, password); logger.debug("Attemptimg to bind as " + fullDn); DirContext ctx = null; try { ctx = specificDnContextSource.getReadOnlyContext(); Attributes attrs = ctx.getAttributes(userDn, getUserAttributes()); DirContextAdapter result = new DirContextAdapter(attrs, userDn, ctxSource.getBaseLdapPath()); return result; } catch (NamingException e) { // This will be thrown if an invalid user name is used and the method may // be called multiple times to try different names, so we trap the exception // unless a subclass wishes to implement more specialized behaviour. if ((e instanceof org.springframework.ldap.AuthenticationException) || (e instanceof org.springframework.ldap.OperationNotSupportedException)) { handleBindException(userDnStr, username, e); } else { throw e; } } catch (javax.naming.NamingException e) { throw LdapUtils.convertLdapException(e); } finally { LdapUtils.closeContext(ctx); } return null; } /** * Allows subclasses to inspect the exception thrown by an attempt to bind with a particular DN. * The default implementation just reports the failure to the debug log. */ protected void handleBindException(String userDn, String username, Throwable cause) { if (logger.isDebugEnabled()) { logger.debug("Failed to bind as " + userDn + ": " + cause); } } private class BindWithSpecificDnContextSource implements ContextSource { private SpringSecurityContextSource ctxFactory; private DistinguishedName userDn; private String password; public BindWithSpecificDnContextSource(SpringSecurityContextSource ctxFactory, DistinguishedName userDn, String password) { this.ctxFactory = ctxFactory; this.userDn = userDn; this.password = password; } public DirContext getReadOnlyContext() throws DataAccessException { return ctxFactory.getReadWriteContext(userDn.toString(), password); } public DirContext getReadWriteContext() throws DataAccessException { return getReadOnlyContext(); } } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/authenticator/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/0000644000000000000000000000010211623517156030511 0ustar LDAP authenticator implementations. ././@LongLink0000000000000000000000000000022100000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/authenticator/AbstractLdapAuthenticator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/0000644000000000000000000001252111623517156030521 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.ldap.authenticator; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.ldap.LdapUserSearch; import org.springframework.security.providers.ldap.LdapAuthenticator; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.ldap.core.ContextSource; import org.springframework.util.Assert; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Base class for the authenticator implementations. * * @author Luke Taylor * @version $Id$ */ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, InitializingBean, MessageSourceAware { //~ Instance fields ================================================================================================ private ContextSource contextSource; /** Optional search object which can be used to locate a user when a simple DN match isn't sufficient */ private LdapUserSearch userSearch; protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); /** The attributes which will be retrieved from the directory. Null means all attributes */ private String[] userAttributes = null; //private String[] userDnPattern = null; /** Stores the patterns which are used as potential DN matches */ private MessageFormat[] userDnFormat = null; //~ Constructors =================================================================================================== /** * Create an initialized instance with the {@link ContextSource} provided. * * @param contextSource */ public AbstractLdapAuthenticator(ContextSource contextSource) { Assert.notNull(contextSource, "contextSource must not be null."); this.contextSource = contextSource; } //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.isTrue((userDnFormat != null) || (userSearch != null), "Either an LdapUserSearch or DN pattern (or both) must be supplied."); } protected ContextSource getContextSource() { return contextSource; } public String[] getUserAttributes() { return userAttributes; } /** * Builds list of possible DNs for the user, worked out from the userDnPatterns property. * * @param username the user's login name * * @return the list of possible DN matches, empty if userDnPatterns wasn't set. */ protected List getUserDns(String username) { if (userDnFormat == null) { return Collections.EMPTY_LIST; } List userDns = new ArrayList(userDnFormat.length); String[] args = new String[] {username}; synchronized (userDnFormat) { for (int i = 0; i < userDnFormat.length; i++) { userDns.add(userDnFormat[i].format(args)); } } return userDns; } protected LdapUserSearch getUserSearch() { return userSearch; } public void setMessageSource(MessageSource messageSource) { Assert.notNull("Message source must not be null"); this.messages = new MessageSourceAccessor(messageSource); } /** * Sets the user attributes which will be retrieved from the directory. * * @param userAttributes */ public void setUserAttributes(String[] userAttributes) { Assert.notNull(userAttributes, "The userAttributes property cannot be set to null"); this.userAttributes = userAttributes; } /** * Sets the pattern which will be used to supply a DN for the user. The pattern should be the name relative * to the root DN. The pattern argument {0} will contain the username. An example would be "cn={0},ou=people". * * @param dnPattern the array of patterns which will be tried when converting a username to a DN. */ public void setUserDnPatterns(String[] dnPattern) { Assert.notNull(dnPattern, "The array of DN patterns cannot be set to null"); // this.userDnPattern = dnPattern; userDnFormat = new MessageFormat[dnPattern.length]; for (int i = 0; i < dnPattern.length; i++) { userDnFormat[i] = new MessageFormat(dnPattern[i]); } } public void setUserSearch(LdapUserSearch userSearch) { Assert.notNull(userSearch, "The userSearch cannot be set to null"); this.userSearch = userSearch; } } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/LdapAuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/providers/ldap/0000644000000000000000000003170111623517156030522 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.providers.ldap; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.AuthenticationServiceException; import org.springframework.security.BadCredentialsException; import org.springframework.security.GrantedAuthority; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.ldap.LdapAuthoritiesPopulator; import org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator; import org.springframework.security.providers.AuthenticationProvider; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.ldap.LdapUserDetailsMapper; import org.springframework.security.userdetails.ldap.UserDetailsContextMapper; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.ldap.NamingException; import org.springframework.ldap.core.DirContextOperations; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * An {@link org.springframework.security.providers.AuthenticationProvider} implementation that authenticates * against an LDAP server. *

    * There are many ways in which an LDAP directory can be configured so this class delegates most of * its responsibilites to two separate strategy interfaces, {@link LdapAuthenticator} * and {@link LdapAuthoritiesPopulator}. * *

    LdapAuthenticator

    * This interface is responsible for performing the user authentication and retrieving * the user's information from the directory. Example implementations are {@link * org.springframework.security.providers.ldap.authenticator.BindAuthenticator BindAuthenticator} which authenticates * the user by "binding" as that user, and * {@link org.springframework.security.providers.ldap.authenticator.PasswordComparisonAuthenticator PasswordComparisonAuthenticator} * which compares the supplied password with the value stored in the directory, using an LDAP "compare" * operation. *

    * The task of retrieving the user attributes is delegated to the authenticator because the permissions on the * attributes may depend on the type of authentication being used; for example, if binding as the user, it may be * necessary to read them with the user's own permissions (using the same context used for the bind operation). * *

    LdapAuthoritiesPopulator

    * Once the user has been authenticated, this interface is called to obtain the set of granted authorities for the * user. * The {@link DefaultLdapAuthoritiesPopulator DefaultLdapAuthoritiesPopulator} * can be configured to obtain user role information from the user's attributes and/or to perform a search for * "groups" that the user is a member of and map these to roles. * *

    * A custom implementation could obtain the roles from a completely different source, for example from a database. * *

    Configuration

    * * A simple configuration might be as follows: *
     *   <bean id="contextSource"
     *       class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
     *     <constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/>
     *     <property name="userDn" value="cn=manager,dc=springframework,dc=org"/>
     *     <property name="password" value="password"/>
     *   </bean>
     *
     *   <bean id="ldapAuthProvider"
     *       class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
     *     <constructor-arg>
     *       <bean class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
     *           <constructor-arg ref="contextSource"/>
     *           <property name="userDnPatterns"><list><value>uid={0},ou=people</value></list></property>
     *       </bean>
     *     </constructor-arg>
     *     <constructor-arg>
     *       <bean class="org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator">
     *           <constructor-arg ref="contextSource"/>
     *           <constructor-arg value="ou=groups"/>
     *           <property name="groupRoleAttribute" value="ou"/>
     *       </bean>
     *     </constructor-arg>
     *   </bean>
     *    
    * *

    * This would set up the provider to access an LDAP server with URL * ldap://monkeymachine:389/dc=springframework,dc=org. Authentication will be performed by attempting to bind * with the DN uid=<user-login-name>,ou=people,dc=springframework,dc=org. After successful * authentication, roles will be assigned to the user by searching under the DN * ou=groups,dc=springframework,dc=org with the default filter (member=<user's-DN>). The role * name will be taken from the "ou" attribute of each match. *

    * The authenticate method will reject empty passwords outright. LDAP servers may allow an anonymous * bind operation with an empty password, even if a DN is supplied. In practice this means that if * the LDAP directory is configured to allow unauthenticated access, it might be possible to * authenticate as any user just by supplying an empty password. * More information on the misuse of unauthenticated access can be found in * * draft-ietf-ldapbis-authmeth-19.txt. * * * @author Luke Taylor * @version $Id$ * * @see org.springframework.security.providers.ldap.authenticator.BindAuthenticator * @see DefaultLdapAuthoritiesPopulator */ public class LdapAuthenticationProvider implements AuthenticationProvider { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(LdapAuthenticationProvider.class); //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private LdapAuthenticator authenticator; private LdapAuthoritiesPopulator authoritiesPopulator; private UserDetailsContextMapper userDetailsContextMapper = new LdapUserDetailsMapper(); private boolean useAuthenticationRequestCredentials = true; //~ Constructors =================================================================================================== /** * Create an instance with the supplied authenticator and authorities populator implementations. * * @param authenticator the authentication strategy (bind, password comparison, etc) * to be used by this provider for authenticating users. * @param authoritiesPopulator the strategy for obtaining the authorities for a given user after they've been * authenticated. */ public LdapAuthenticationProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) { this.setAuthenticator(authenticator); this.setAuthoritiesPopulator(authoritiesPopulator); } /** * Creates an instance with the supplied authenticator and a null authorities populator. * In this case, the authorities must be mapped from the user context. * * @param authenticator the authenticator strategy. */ public LdapAuthenticationProvider(LdapAuthenticator authenticator) { this.setAuthenticator(authenticator); this.setAuthoritiesPopulator(new NullAuthoritiesPopulator()); } //~ Methods ======================================================================================================== private void setAuthenticator(LdapAuthenticator authenticator) { Assert.notNull(authenticator, "An LdapAuthenticator must be supplied"); this.authenticator = authenticator; } private LdapAuthenticator getAuthenticator() { return authenticator; } private void setAuthoritiesPopulator(LdapAuthoritiesPopulator authoritiesPopulator) { Assert.notNull(authoritiesPopulator, "An LdapAuthoritiesPopulator must be supplied"); this.authoritiesPopulator = authoritiesPopulator; } protected LdapAuthoritiesPopulator getAuthoritiesPopulator() { return authoritiesPopulator; } public void setUserDetailsContextMapper(UserDetailsContextMapper userDetailsContextMapper) { Assert.notNull(userDetailsContextMapper, "UserDetailsContextMapper must not be null"); this.userDetailsContextMapper = userDetailsContextMapper; } protected UserDetailsContextMapper getUserDetailsContextMapper() { return userDetailsContextMapper; } /** * Determines whether the supplied password will be used as the credentials in the successful authentication * token. If set to false, then the password will be obtained from the UserDetails object * created by the configured mapper. Often it will not be possible to read the password from the directory, so * defaults to true. * * @param useAuthenticationRequestCredentials */ public void setUseAuthenticationRequestCredentials(boolean useAuthenticationRequestCredentials) { this.useAuthenticationRequestCredentials = useAuthenticationRequestCredentials; } public Authentication authenticate(Authentication authentication) throws AuthenticationException { Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports", "Only UsernamePasswordAuthenticationToken is supported")); UsernamePasswordAuthenticationToken userToken = (UsernamePasswordAuthenticationToken)authentication; String username = userToken.getName(); if (!StringUtils.hasLength(username)) { throw new BadCredentialsException(messages.getMessage("LdapAuthenticationProvider.emptyUsername", "Empty Username")); } String password = (String) authentication.getCredentials(); Assert.notNull(password, "Null password was supplied in authentication token"); if (password.length() == 0) { logger.debug("Rejecting empty password for user " + username); throw new BadCredentialsException(messages.getMessage("LdapAuthenticationProvider.emptyPassword", "Empty Password")); } try { DirContextOperations userData = getAuthenticator().authenticate(authentication); GrantedAuthority[] extraAuthorities = loadUserAuthorities(userData, username, password); UserDetails user = userDetailsContextMapper.mapUserFromContext(userData, username, extraAuthorities); return createSuccessfulAuthentication(userToken, user); } catch (NamingException ldapAccessFailure) { throw new AuthenticationServiceException(ldapAccessFailure.getMessage(), ldapAccessFailure); } } protected GrantedAuthority[] loadUserAuthorities(DirContextOperations userData, String username, String password) { return getAuthoritiesPopulator().getGrantedAuthorities(userData, username); } protected Authentication createSuccessfulAuthentication(UsernamePasswordAuthenticationToken authentication, UserDetails user) { Object password = useAuthenticationRequestCredentials ? authentication.getCredentials() : user.getPassword(); return new UsernamePasswordAuthenticationToken(user, password, user.getAuthorities()); } public boolean supports(Class authentication) { return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); } //~ Inner Classes ================================================================================================== private static class NullAuthoritiesPopulator implements LdapAuthoritiesPopulator { public GrantedAuthority[] getGrantedAuthorities(DirContextOperations userDetails, String username) { return new GrantedAuthority[0]; } } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_es_ES.propertiesspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/messages_es_ES.0000644000000000000000000001076311623517156030456 0ustar AuthByAdapterProvider.incorrectKey=La actual implementación de AuthByAdapter no contiene la clave esperada BasicAclEntryAfterInvocationProvider.noPermission=Authentication {0} NO tiene permisos para el objeto de dominio {1} BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentication {0} tiene permisos ACL para objeto de dominio, pero no los permisos ACL requeridos para el objeto de dominio {1} ConcurrentSessionControllerImpl.exceededAllowed=Sesiones máximas de {0} para esta Identificación excedidas ProviderManager.providerNotFound=AuthenticationProvider no encontrado para {0} AnonymousAuthenticationProvider.incorrectKey=El actual AnonymousAuthenticationToken no contiene la clave esperada CasAuthenticationProvider.incorrectKey=El actual CasAuthenticationToken no contiene la clave esperada CasAuthenticationProvider.noServiceTicket=No se ha podido proporcionar un billete de servicio CAS para validar NamedCasProxyDecider.untrusted=El proxy más cercano {0} no es confiable RejectProxyTickets.reject=Las entradas del proxy han sido rechazadas AbstractSecurityInterceptor.authenticationNotFound=El objeto Authentication no ha sido encontrado en el SecurityContext AbstractUserDetailsAuthenticationProvider.onlySupports=Sólo UsernamePasswordAuthenticationToken es soportada AbstractUserDetailsAuthenticationProvider.locked=La cuenta del usuario está bloqueada AbstractUserDetailsAuthenticationProvider.disabled=El usuario está deshabilitado AbstractUserDetailsAuthenticationProvider.expired=La cuenta del usuario ha expirado AbstractUserDetailsAuthenticationProvider.credentialsExpired=Las credenciales del usuario han expirado AbstractUserDetailsAuthenticationProvider.badCredentials=Credenciales erróneas X509AuthenticationProvider.certificateNull=Cerfificado nulo DaoX509AuthoritiesPopulator.noMatching=No se ha encontrado un patrón coincidente en subjectDN: {0} RememberMeAuthenticationProvider.incorrectKey=El actual RememberMeAuthenticationToken no contiene la clave esperada RunAsImplAuthenticationProvider.incorrectKey=El actual RunAsUserToken no contiene la clave esperada DigestProcessingFilter.missingMandatory=Valor digest obligatorio perdido; header recibido {0} DigestProcessingFilter.missingAuth=Valor digest obligatorio perdido para 'auth' QOP; header recibido {0} DigestProcessingFilter.incorrectRealm=Respuesta realm de nombre {0} no coincide con realm del sistema de nombre {1} DigestProcessingFilter.nonceExpired=Nonce ha expirado/fuera de tiempo DigestProcessingFilter.nonceEncoding=Nonce no está codificado en Base64; nonce recibido {0} DigestProcessingFilter.nonceNotTwoTokens=Nonce token debería tener dos fichas pero tenía {0} DigestProcessingFilter.nonceNotNumeric=Nonce token debería tener primero un token numérico, pero tenía {0} DigestProcessingFilter.nonceCompromised=Nonce token comprometido {0} DigestProcessingFilter.usernameNotFound=Usuario y nombre {0} no encontrado DigestProcessingFilter.incorrectResponse=Respuesta incorrecta JdbcDaoImpl.notFound=Usuario {0} no encontrado JdbcDaoImpl.noAuthority=Usuario {0} no tiene GrantedAuthority SwitchUserProcessingFilter.noCurrentUser=No hay usuario actual asociado con esta petición SwitchUserProcessingFilter.noOriginalAuthentication=No se puede encontrar el objeto Authentication original SwitchUserProcessingFilter.usernameNotFound=Usuario y nombre {0} no encontrado SwitchUserProcessingFilter.locked=La cuenta del usuario está bloqueada SwitchUserProcessingFilter.disabled=El usuario está deshabilitado SwitchUserProcessingFilter.expired=La cuenta del usuario ha expirado SwitchUserProcessingFilter.credentialsExpired=Las credenciales del usuario han expirado AbstractAccessDecisionManager.accessDenied=Acceso denegado LdapAuthenticationProvider.emptyUsername=Usuario y nombre no permitido LdapAuthenticationProvider.emptyPassword=Credenciales erróneas DefaultIntitalDirContextFactory.communicationFailure=No se puede conectar con el servidor LDAP DefaultIntitalDirContextFactory.badCredentials=Credenciales erróneas DefaultIntitalDirContextFactory.unexpectedException=Error al obtener el InitialDirContext debido a una excepción inesperada PasswordComparisonAuthenticator.badCredentials=Credenciales erróneas BindAuthenticator.badCredentials=Credenciales erróneas BindAuthenticator.failedToLoadAttributes=Credenciales erróneas UserDetailsService.locked=La cuenta del usuario está bloqueada UserDetailsService.disabled=El usuario está deshabilitado UserDetailsService.expired=La cuenta del usuario ha expirado UserDetailsService.credentialsExpired=Las credenciales del usuario han expiradospring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/0000755000000000000000000000000011623517156030400 5ustar ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/ChannelDecisionManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/C0000644000000000000000000000444011623517156030507 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.securechannel; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.web.FilterInvocation; import java.io.IOException; import javax.servlet.ServletException; /** * Decides whether a web channel provides sufficient security. * * @author Ben Alex * @version $Id$ */ public interface ChannelDecisionManager { //~ Methods ======================================================================================================== /** * Decided whether the presented {@link FilterInvocation} provides the appropriate level of channel * security based on the requested {@link ConfigAttributeDefinition}. * * @param invocation DOCUMENT ME! * @param config DOCUMENT ME! * * @throws IOException DOCUMENT ME! * @throws ServletException DOCUMENT ME! */ void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException; /** * Indicates whether this ChannelDecisionManager is able to process the passed * ConfigAttribute.

    This allows the ChannelProcessingFilter to check every * configuration attribute can be consumed by the configured ChannelDecisionManager.

    * * @param attribute a configuration attribute that has been configured against the * ChannelProcessingFilter * * @return true if this ChannelDecisionManager can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/ChannelProcessor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/C0000644000000000000000000000511111623517156030503 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.securechannel; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.web.FilterInvocation; import java.io.IOException; import javax.servlet.ServletException; /** * Decides whether a web channel meets a specific security condition. * *

    * ChannelProcessor implementations are iterated by the {@link * ChannelDecisionManagerImpl}. *

    * *

    * If an implementation has an issue with the channel security, they should * take action themselves. The callers of the implementation do not take any * action. *

    * * @author Ben Alex * @version $Id$ */ public interface ChannelProcessor { //~ Methods ======================================================================================================== /** * Decided whether the presented {@link FilterInvocation} provides the appropriate level of channel * security based on the requested {@link ConfigAttributeDefinition}. * * @param invocation DOCUMENT ME! * @param config DOCUMENT ME! * * @throws IOException DOCUMENT ME! * @throws ServletException DOCUMENT ME! */ void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException; /** * Indicates whether this ChannelProcessor is able to process the passed * ConfigAttribute.

    This allows the ChannelProcessingFilter to check every * configuration attribute can be consumed by the configured ChannelDecisionManager.

    * * @param attribute a configuration attribute that has been configured against the * ChannelProcessingFilter * * @return true if this ChannelProcessor can support the passed configuration attribute */ boolean supports(ConfigAttribute attribute); } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/AbstractRetryEntryPoint.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/A0000644000000000000000000000671711623517156030516 0ustar package org.springframework.security.securechannel; import org.springframework.security.util.PortMapper; import org.springframework.security.util.PortResolver; import org.springframework.security.util.PortMapperImpl; import org.springframework.security.util.PortResolverImpl; import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author Luke Taylor * @version $Id$ */ public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(RetryWithHttpEntryPoint.class); //~ Instance fields ================================================================================================ private PortMapper portMapper = new PortMapperImpl(); private PortResolver portResolver = new PortResolverImpl(); /** The scheme ("http://" or "https://") */ private String scheme; /** The standard port for the scheme (80 for http, 443 for https) */ private int standardPort; //~ Constructors =================================================================================================== public AbstractRetryEntryPoint(String scheme, int standardPort) { this.scheme = scheme; this.standardPort = standardPort; } //~ Methods ======================================================================================================== public void commence(ServletRequest req, ServletResponse res) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; String pathInfo = request.getPathInfo(); String queryString = request.getQueryString(); String contextPath = request.getContextPath(); String destination = request.getServletPath() + ((pathInfo == null) ? "" : pathInfo) + ((queryString == null) ? "" : ("?" + queryString)); String redirectUrl = contextPath; Integer currentPort = new Integer(portResolver.getServerPort(request)); Integer redirectPort = getMappedPort(currentPort); if (redirectPort != null) { boolean includePort = redirectPort.intValue() != standardPort; redirectUrl = scheme + request.getServerName() + ((includePort) ? (":" + redirectPort) : "") + contextPath + destination; } if (logger.isDebugEnabled()) { logger.debug("Redirecting to: " + redirectUrl); } ((HttpServletResponse) res).sendRedirect(((HttpServletResponse) res).encodeRedirectURL(redirectUrl)); } protected abstract Integer getMappedPort(Integer mapFromPort); protected PortMapper getPortMapper() { return portMapper; } protected PortResolver getPortResolver() { return portResolver; } public void setPortMapper(PortMapper portMapper) { Assert.notNull(portMapper, "portMapper cannot be null"); this.portMapper = portMapper; } public void setPortResolver(PortResolver portResolver) { Assert.notNull(portResolver, "portResolver cannot be null"); this.portResolver = portResolver; } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/InsecureChannelProcessor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/I0000644000000000000000000000717511623517156030525 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.securechannel; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.web.FilterInvocation; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import java.util.Iterator; import javax.servlet.ServletException; /** *

    Ensures channel security is inactive by review of HttpServletRequest.isSecure() responses.

    *

    The class responds to one case-sensitive keyword, {@link #getInsecureKeyword}. If this keyword is detected, * HttpServletRequest.isSecure() is used to determine the channel security offered. If channel security * is present, the configured ChannelEntryPoint is called. By default the entry point is {@link * RetryWithHttpEntryPoint}.

    *

    The default insecureKeyword is REQUIRES_INSECURE_CHANNEL.

    * * @author Ben Alex * @version $Id$ */ public class InsecureChannelProcessor implements InitializingBean, ChannelProcessor { //~ Instance fields ================================================================================================ private ChannelEntryPoint entryPoint = new RetryWithHttpEntryPoint(); private String insecureKeyword = "REQUIRES_INSECURE_CHANNEL"; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(insecureKeyword, "insecureKeyword required"); Assert.notNull(entryPoint, "entryPoint required"); } public void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException { if ((invocation == null) || (config == null)) { throw new IllegalArgumentException("Nulls cannot be provided"); } Iterator iter = config.getConfigAttributes().iterator(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (supports(attribute)) { if (invocation.getHttpRequest().isSecure()) { entryPoint.commence(invocation.getRequest(), invocation.getResponse()); } } } } public ChannelEntryPoint getEntryPoint() { return entryPoint; } public String getInsecureKeyword() { return insecureKeyword; } public void setEntryPoint(ChannelEntryPoint entryPoint) { this.entryPoint = entryPoint; } public void setInsecureKeyword(String secureKeyword) { this.insecureKeyword = secureKeyword; } public boolean supports(ConfigAttribute attribute) { if ((attribute != null) && (attribute.getAttribute() != null) && attribute.getAttribute().equals(getInsecureKeyword())) { return true; } else { return false; } } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/ChannelProcessingFilter.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/C0000644000000000000000000001244511623517156030513 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.securechannel; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.web.FilterInvocation; import org.springframework.security.intercept.web.FilterInvocationDefinitionSource; import org.springframework.security.ui.SpringSecurityFilter; import org.springframework.security.ui.FilterChainOrder; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.Collection; /** * Ensures a web request is delivered over the required channel. *

    Internally uses a {@link FilterInvocation} to represent the request, so that the * FilterInvocation-related property editors and lookup classes can be used.

    *

    Delegates the actual channel security decisions and necessary actions to the configured * {@link ChannelDecisionManager}. If a response is committed by the ChannelDecisionManager, * the filter chain will not proceed.

    * * @author Ben Alex * @version $Id$ */ public class ChannelProcessingFilter extends SpringSecurityFilter implements InitializingBean { //~ Instance fields ================================================================================================ private ChannelDecisionManager channelDecisionManager; private FilterInvocationDefinitionSource filterInvocationDefinitionSource; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(filterInvocationDefinitionSource, "filterInvocationDefinitionSource must be specified"); Assert.notNull(channelDecisionManager, "channelDecisionManager must be specified"); Collection attrDefs = this.filterInvocationDefinitionSource.getConfigAttributeDefinitions(); if (attrDefs == null) { if (logger.isWarnEnabled()) { logger.warn("Could not validate configuration attributes as the FilterInvocationDefinitionSource did " + "not return a ConfigAttributeDefinition Iterator"); } return; } Iterator iter = attrDefs.iterator(); Set set = new HashSet(); while (iter.hasNext()) { ConfigAttributeDefinition def = (ConfigAttributeDefinition) iter.next(); Iterator attributes = def.getConfigAttributes().iterator(); while (attributes.hasNext()) { ConfigAttribute attr = (ConfigAttribute) attributes.next(); if (!this.channelDecisionManager.supports(attr)) { set.add(attr); } } } if (set.size() == 0) { if (logger.isInfoEnabled()) { logger.info("Validated configuration attributes"); } } else { throw new IllegalArgumentException("Unsupported configuration attributes: " + set.toString()); } } public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); ConfigAttributeDefinition attr = this.filterInvocationDefinitionSource.getAttributes(fi); if (attr != null) { if (logger.isDebugEnabled()) { logger.debug("Request: " + fi.toString() + "; ConfigAttributes: " + attr.toString()); } channelDecisionManager.decide(fi, attr); if (fi.getResponse().isCommitted()) { return; } } chain.doFilter(request, response); } public ChannelDecisionManager getChannelDecisionManager() { return channelDecisionManager; } public FilterInvocationDefinitionSource getFilterInvocationDefinitionSource() { return filterInvocationDefinitionSource; } public void setChannelDecisionManager(ChannelDecisionManager channelDecisionManager) { this.channelDecisionManager = channelDecisionManager; } public void setFilterInvocationDefinitionSource(FilterInvocationDefinitionSource filterInvocationDefinitionSource) { this.filterInvocationDefinitionSource = filterInvocationDefinitionSource; } public int getOrder() { return FilterChainOrder.CHANNEL_FILTER; } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/ChannelDecisionManagerImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/C0000644000000000000000000001024411623517156030506 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.securechannel; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.web.FilterInvocation; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import java.util.Iterator; import java.util.List; import javax.servlet.ServletException; /** * Implementation of {@link ChannelDecisionManager}. *

    * Iterates through each configured {@link ChannelProcessor}. If a ChannelProcessor has any issue with the * security of the request, it should cause a redirect, exception or whatever other action is appropriate for the * ChannelProcessor implementation. *

    * Once any response is committed (ie a redirect is written to the response object), the * ChannelDecisionManagerImpl will not iterate through any further ChannelProcessors. *

    * The attribute "ANY_CHANNEL" if applied to a particular URL, the iteration through the channel processors will be * skipped (see SEC-494, SEC-335). * * @author Ben Alex * @version $Id$ */ public class ChannelDecisionManagerImpl implements ChannelDecisionManager, InitializingBean { public static final String ANY_CHANNEL = "ANY_CHANNEL"; //~ Instance fields ================================================================================================ private List channelProcessors; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { checkIfValidList(this.channelProcessors); } private void checkIfValidList(List listToCheck) { Assert.notEmpty(listToCheck, "A list of ChannelProcessors is required"); } public void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException { Iterator attrs = config.getConfigAttributes().iterator(); while (attrs.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) attrs.next(); if (ANY_CHANNEL.equals(attribute.getAttribute())) { return; } } Iterator iter = this.channelProcessors.iterator(); while (iter.hasNext()) { ChannelProcessor processor = (ChannelProcessor) iter.next(); processor.decide(invocation, config); if (invocation.getResponse().isCommitted()) { break; } } } protected List getChannelProcessors() { return this.channelProcessors; } public void setChannelProcessors(List newList) { checkIfValidList(newList); Iterator iter = newList.iterator(); while (iter.hasNext()) { Object currentObject = iter.next(); Assert.isInstanceOf(ChannelProcessor.class, currentObject, "ChannelProcessor " + currentObject.getClass().getName() + " must implement ChannelProcessor"); } this.channelProcessors = newList; } public boolean supports(ConfigAttribute attribute) { if (ANY_CHANNEL.equals(attribute.getAttribute())) { return true; } Iterator iter = this.channelProcessors.iterator(); while (iter.hasNext()) { ChannelProcessor processor = (ChannelProcessor) iter.next(); if (processor.supports(attribute)) { return true; } } return false; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/p0000644000000000000000000000015611623517156030564 0ustar Classes that ensure web requests are received over required transport channels. ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/RetryWithHttpsEntryPoint.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/R0000644000000000000000000000237011623517156030526 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.securechannel; /** * Commences a secure channel by retrying the original request using HTTPS. *

    * This entry point should suffice in most circumstances. However, it is not intended to properly handle HTTP POSTs * or other usage where a standard redirect would cause an issue.

    * * @author Ben Alex * @version $Id$ */ public class RetryWithHttpsEntryPoint extends AbstractRetryEntryPoint { public RetryWithHttpsEntryPoint() { super("https://", 443); } protected Integer getMappedPort(Integer mapFromPort) { return getPortMapper().lookupHttpsPort(mapFromPort); } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/ChannelEntryPoint.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/C0000644000000000000000000000367411623517156030517 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.securechannel; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * May be used by a {@link ChannelProcessor} to launch a web channel. * *

    * ChannelProcessors can elect to launch a new web channel * directly, or they can delegate to another class. The * ChannelEntryPoint is a pluggable interface to assist * ChannelProcessors in performing this delegation. *

    * * @author Ben Alex * @version $Id$ */ public interface ChannelEntryPoint { //~ Methods ======================================================================================================== /** * Commences a secure channel.

    Implementations should modify the headers on the * ServletResponse as necessary to commence the user agent using the implementation's supported * channel type.

    * * @param request that a ChannelProcessor has rejected * @param response so that the user agent can begin using a new channel * * @throws IOException DOCUMENT ME! * @throws ServletException DOCUMENT ME! */ void commence(ServletRequest request, ServletResponse response) throws IOException, ServletException; } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/RetryWithHttpEntryPoint.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/R0000644000000000000000000000236211623517156030527 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.securechannel; /** * Commences an insecure channel by retrying the original request using HTTP. *

    * This entry point should suffice in most circumstances. However, it is not intended to properly handle HTTP POSTs or * other usage where a standard redirect would cause an issue. * * @author Ben Alex * @version $Id$ */ public class RetryWithHttpEntryPoint extends AbstractRetryEntryPoint { public RetryWithHttpEntryPoint() { super("http://", 80); } protected Integer getMappedPort(Integer mapFromPort) { return getPortMapper().lookupHttpPort(mapFromPort); } } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/SecureChannelProcessor.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/securechannel/S0000644000000000000000000000706711623517156030537 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.securechannel; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.web.FilterInvocation; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.io.IOException; import java.util.Iterator; import javax.servlet.ServletException; /** *

    Ensures channel security is active by review of HttpServletRequest.isSecure() responses.

    *

    The class responds to one case-sensitive keyword, {@link #getSecureKeyword}. If this keyword is detected, * HttpServletRequest.isSecure() is used to determine the channel security offered. If channel security * is not present, the configured ChannelEntryPoint is called. By default the entry point is {@link * RetryWithHttpsEntryPoint}.

    *

    The default secureKeyword is REQUIRES_SECURE_CHANNEL.

    * * @author Ben Alex * @version $Id$ */ public class SecureChannelProcessor implements InitializingBean, ChannelProcessor { //~ Instance fields ================================================================================================ private ChannelEntryPoint entryPoint = new RetryWithHttpsEntryPoint(); private String secureKeyword = "REQUIRES_SECURE_CHANNEL"; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(secureKeyword, "secureKeyword required"); Assert.notNull(entryPoint, "entryPoint required"); } public void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException, ServletException { Assert.isTrue((invocation != null) && (config != null), "Nulls cannot be provided"); Iterator iter = config.getConfigAttributes().iterator(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (supports(attribute)) { if (!invocation.getHttpRequest().isSecure()) { entryPoint.commence(invocation.getRequest(), invocation.getResponse()); } } } } public ChannelEntryPoint getEntryPoint() { return entryPoint; } public String getSecureKeyword() { return secureKeyword; } public void setEntryPoint(ChannelEntryPoint entryPoint) { this.entryPoint = entryPoint; } public void setSecureKeyword(String secureKeyword) { this.secureKeyword = secureKeyword; } public boolean supports(ConfigAttribute attribute) { if ((attribute != null) && (attribute.getAttribute() != null) && attribute.getAttribute().equals(getSecureKeyword())) { return true; } else { return false; } } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthorizationServiceException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AuthorizationSe0000644000000000000000000000320511623517156030634 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Thrown if an authorization request could not be processed due to a system problem.

    This might be thrown if an * AccessDecisionManager implementation could not locate a required method argument, for example.

    * * @author Ben Alex * @version $Id$ */ public class AuthorizationServiceException extends AccessDeniedException { //~ Constructors =================================================================================================== /** * Constructs an AuthorizationServiceException with the * specified message. * * @param msg the detail message */ public AuthorizationServiceException(String msg) { super(msg); } /** * Constructs an AuthorizationServiceException with the * specified message and root cause. * * @param msg the detail message * @param t root cause */ public AuthorizationServiceException(String msg, Throwable t) { super(msg, t); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/token/0000755000000000000000000000000011623517156026701 5ustar ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/token/SecureRandomFactoryBean.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/token/SecureRan0000644000000000000000000000362311623517156030517 0ustar package org.springframework.security.token; import java.io.InputStream; import java.security.SecureRandom; import org.springframework.beans.factory.FactoryBean; import org.springframework.core.io.Resource; import org.springframework.util.Assert; import org.springframework.util.FileCopyUtils; /** * Creates a {@link SecureRandom} instance. * * @author Ben Alex * @since 2.0.1 * */ public class SecureRandomFactoryBean implements FactoryBean { private String algorithm = "SHA1PRNG"; private Resource seed; public Object getObject() throws Exception { SecureRandom rnd = SecureRandom.getInstance(algorithm); if (seed != null) { // Seed specified, so use it byte[] seedBytes = FileCopyUtils.copyToByteArray(seed.getInputStream()); rnd.setSeed(seedBytes); } else { // Request the next bytes, thus eagerly incurring the expense of default seeding rnd.nextBytes(new byte[1]); } return rnd; } public Class getObjectType() { return SecureRandom.class; } public boolean isSingleton() { return false; } /** * Allows the Pseudo Random Number Generator (PRNG) algorithm to be nominated. Defaults to * SHA1PRNG. * * @param algorithm to use (mandatory) */ public void setAlgorithm(String algorithm) { Assert.hasText(algorithm, "Algorithm required"); this.algorithm = algorithm; } /** * Allows the user to specify a resource which will act as a seed for the {@link SecureRandom} * instance. Specifically, the resource will be read into an {@link InputStream} and those * bytes presented to the {@link SecureRandom#setSeed(byte[])} method. Note that this will * simply supplement, rather than replace, the existing seed. As such, it is always safe to * set a seed using this method (it never reduces randomness). * * @param seed to use, or null if no additional seeding is needed */ public void setSeed(Resource seed) { this.seed = seed; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/token/KeyBasedPersistenceTokenService.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/token/KeyBasedP0000644000000000000000000001430311623517156030434 0ustar package org.springframework.security.token; import java.io.UnsupportedEncodingException; import java.security.SecureRandom; import java.util.Date; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.util.Sha512DigestUtils; import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** * Basic implementation of {@link TokenService} that is compatible with clusters and across machine restarts, * without requiring database persistence. * *

    * Keys are produced in the format: *

    * *

    * Base64(creationTime + ":" + hex(pseudoRandomNumber) + ":" + extendedInformation + ":" + * Sha512Hex(creationTime + ":" + hex(pseudoRandomNumber) + ":" + extendedInformation + ":" + serverSecret) ) *

    * *

    * In the above, creationTime, tokenKey and extendedInformation * are equal to that stored in {@link Token}. The Sha512Hex includes the same payload, * plus a serverSecret. *

    * *

    * The serverSecret varies every millisecond. It relies on two static server-side secrets. The first * is a password, and the second is a server integer. Both of these must remain the same for any issued keys * to subsequently be recognised. The applicable serverSecret in any millisecond is computed by * password + ":" + (creationTime % serverInteger). This approach * further obfuscates the actual server secret and renders attempts to compute the server secret more * limited in usefulness (as any false tokens would be forced to have a creationTime equal * to the computed hash). Recall that framework features depending on token services should reject tokens * that are relatively old in any event. *

    * *

    * A further consideration of this class is the requirement for cryptographically strong pseudo-random numbers. * To this end, the use of {@link SecureRandomFactoryBean} is recommended to inject the property. *

    * *

    * This implementation uses UTF-8 encoding internally for string manipulation. *

    * * @author Ben Alex * */ public class KeyBasedPersistenceTokenService implements TokenService, InitializingBean { private int pseudoRandomNumberBits = 256; private String serverSecret; private Integer serverInteger; private SecureRandom secureRandom; public Token allocateToken(String extendedInformation) { Assert.notNull(extendedInformation, "Must provided non-null extendedInformation (but it can be empty)"); long creationTime = new Date().getTime(); String serverSecret = computeServerSecretApplicableAt(creationTime); String pseudoRandomNumber = generatePseudoRandomNumber(); String content = new Long(creationTime).toString() + ":" + pseudoRandomNumber + ":" + extendedInformation; // Compute key String sha512Hex = Sha512DigestUtils.shaHex(content + ":" + serverSecret); String keyPayload = content + ":" + sha512Hex; String key = convertToString(Base64.encodeBase64(convertToBytes(keyPayload))); return new DefaultToken(key, creationTime, extendedInformation); } public Token verifyToken(String key) { if (key == null || "".equals(key)) { return null; } String[] tokens = StringUtils.delimitedListToStringArray(convertToString(Base64.decodeBase64(convertToBytes(key))), ":"); Assert.isTrue(tokens.length >= 4, "Expected 4 or more tokens but found " + tokens.length); long creationTime; try { creationTime = Long.decode(tokens[0]).longValue(); } catch (NumberFormatException nfe) { throw new IllegalArgumentException("Expected number but found " + tokens[0]); } String serverSecret = computeServerSecretApplicableAt(creationTime); String pseudoRandomNumber = tokens[1]; // Permit extendedInfo to itself contain ":" characters StringBuffer extendedInfo = new StringBuffer(); for (int i = 2; i < tokens.length-1; i++) { if (i > 2) { extendedInfo.append(":"); } extendedInfo.append(tokens[i]); } String sha1Hex = tokens[tokens.length-1]; // Verification String content = new Long(creationTime).toString() + ":" + pseudoRandomNumber + ":" + extendedInfo.toString(); String expectedSha512Hex = Sha512DigestUtils.shaHex(content + ":" + serverSecret); Assert.isTrue(expectedSha512Hex.equals(sha1Hex), "Key verification failure"); return new DefaultToken(key, creationTime, extendedInfo.toString()); } private byte[] convertToBytes(String input) { try { return input.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } private String convertToString(byte[] bytes) { try { return new String(bytes, "UTF-8"); } catch (Exception e) { throw new RuntimeException(e); } } /** * @return a pseduo random number (hex encoded) */ private String generatePseudoRandomNumber() { byte[] randomizedBits = new byte[pseudoRandomNumberBits]; secureRandom.nextBytes(randomizedBits); return new String(Hex.encodeHex(randomizedBits)); } private String computeServerSecretApplicableAt(long time) { return serverSecret + ":" + new Long(time % serverInteger.intValue()).intValue(); } /** * @param serverSecret the new secret, which can contain a ":" if desired (never being sent to the client) */ public void setServerSecret(String serverSecret) { this.serverSecret = serverSecret; } public void setSecureRandom(SecureRandom secureRandom) { this.secureRandom = secureRandom; } /** * @param pseudoRandomNumberBits changes the number of bits issued (must be >= 0; defaults to 256) */ public void setPseudoRandomNumberBits(int pseudoRandomNumberBits) { Assert.isTrue(pseudoRandomNumberBits >= 0, "Must have a positive pseudo random number bit size"); this.pseudoRandomNumberBits = pseudoRandomNumberBits; } public void setServerInteger(Integer serverInteger) { this.serverInteger = serverInteger; } public void afterPropertiesSet() throws Exception { Assert.hasText(serverSecret, "Server secret required"); Assert.notNull(serverInteger, "Server integer required"); Assert.notNull(secureRandom, "SecureRandom instance required"); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/token/Token.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/token/Token.jav0000644000000000000000000000317011623517156030464 0ustar package org.springframework.security.token; /** * A token issued by {@link TokenService}. * *

    * It is important that the keys assigned to tokens are sufficiently randomised and secured that * they can serve as identifying a unique user session. Implementations of {@link TokenService} * are free to use encryption or encoding strategies of their choice. It is strongly recommended that * keys are of sufficient length to balance safety against persistence cost. In relation to persistence * cost, it is strongly recommended that returned keys are small enough for encoding in a cookie. *

    * * @author Ben Alex * @since 2.0.1 */ public interface Token { /** * Obtains the randomised, secure key assigned to this token. Presentation of this token to * {@link TokenService} will always return a Token that is equal to the original * Token issued for that key. * * @return a key with appropriate randomness and security. */ String getKey(); /** * The time the token key was initially created is available from this method. Note that a given * token must never have this creation time changed. If necessary, a new token can be * requested from the {@link TokenService} to replace the original token. * * @return the time this token key was created, in the same format as specified by {@link Date#getTime()). */ long getKeyCreationTime(); /** * Obtains the extended information associated within the token, which was presented when the token * was first created. * * @return the user-specified extended information, if any */ String getExtendedInformation(); } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/token/TokenService.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/token/TokenServ0000644000000000000000000000374011623517156030550 0ustar package org.springframework.security.token; /** * Provides a mechanism to allocate and rebuild secure, randomised tokens. * *

    * Implementations are solely concern with issuing a new {@link Token} on demand. The * issued Token may contain user-specified extended information. The token also * contains a cryptographically strong, byte array-based key. This permits the token to be * used to identify a user session, if desired. The key can subsequently be re-presented * to the TokenService for verification and reconstruction of a Token * equal to the original Token. *

    * *

    * Given the tightly-focused behaviour provided by this interface, it can serve as a building block * for more sophisticated token-based solutions. For example, authentication systems that depend on * stateless session keys. These could, for instance, place the username inside the user-specified * extended information associated with the key). It is important to recognise that we do not intend * for this interface to be expanded to provide such capabilities directly. *

    * * @author Ben Alex * @since 2.0.1 * */ public interface TokenService { /** * Forces the allocation of a new {@link Token}. * * @param the extended information desired in the token (cannot be null, but can be empty) * @return a new token that has not been issued previously, and is guaranteed to be recognised * by this implementation's {@link #verifyToken(String)} at any future time. */ Token allocateToken(String extendedInformation); /** * Permits verification the <{@link Token#getKey()} was issued by this TokenService and * reconstructs the corresponding Token. * * @param key as obtained from {@link Token#getKey()} and created by this implementation * @return the token, or null if the token was not issued by this TokenService */ Token verifyToken(String key); } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/token/DefaultToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/token/DefaultTo0000644000000000000000000000300611623517156030512 0ustar package org.springframework.security.token; import java.util.Date; import org.springframework.util.Assert; /** * The default implementation of {@link Token}. * * @author Ben Alex * @since 2.0.1 */ public class DefaultToken implements Token { private String key; private long keyCreationTime; private String extendedInformation; public DefaultToken(String key, long keyCreationTime, String extendedInformation) { Assert.hasText(key, "Key required"); Assert.notNull(extendedInformation, "Extended information cannot be null"); this.key = key; this.keyCreationTime = keyCreationTime; this.extendedInformation = extendedInformation; } public String getKey() { return key; } public long getKeyCreationTime() { return keyCreationTime; } public String getExtendedInformation() { return extendedInformation; } public boolean equals(Object obj) { if (obj != null && obj instanceof DefaultToken) { DefaultToken rhs = (DefaultToken) obj; return this.key.equals(rhs.key) && this.keyCreationTime == rhs.keyCreationTime && this.extendedInformation.equals(rhs.extendedInformation); } return false; } public int hashCode() { int code = 979; code = code * key.hashCode(); code = code * new Long(keyCreationTime).hashCode(); code = code * extendedInformation.hashCode(); return code; } public String toString() { return "DefaultToken[key=" + new String(key) + "; creation=" + new Date(keyCreationTime) + "; extended=" + extendedInformation + "]"; } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/DisabledException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/DisabledExcepti0000644000000000000000000000315711623517156030543 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Thrown if an authentication request is rejected because the account is disabled. Makes no assertion as to * whether or not the credentials were valid. * * @author Ben Alex * @version $Id$ */ public class DisabledException extends AccountStatusException { //~ Constructors =================================================================================================== /** * Constructs a DisabledException with the specified message. * * @param msg the detail message */ public DisabledException(String msg) { super(msg); } /** * Constructs a DisabledException with the specified message * and root cause. * * @param msg the detail message * @param t root cause */ public DisabledException(String msg, Throwable t) { super(msg, t); } public DisabledException(String msg, Object extraInformation) { super(msg, extraInformation); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/0000755000000000000000000000000011623517156026501 5ustar ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapUsernameToDnMapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapUserna0000644000000000000000000000045611623517156030467 0ustar package org.springframework.security.ldap; import org.springframework.ldap.core.DistinguishedName; /** * Constructs an Ldap Distinguished Name from a username. * * @author Luke Taylor * @version $Id$ */ public interface LdapUsernameToDnMapper { DistinguishedName buildDn(String username); } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/NamingExceptionTranslator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/NamingExce0000644000000000000000000000213611623517156030444 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap; import org.springframework.dao.DataAccessException; import javax.naming.NamingException; /** * @author Luke Taylor * @deprecated Spring ldap is used instead. * @version $Id$ */ public interface NamingExceptionTranslator { //~ Methods ======================================================================================================== DataAccessException translate(String task, NamingException e); } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapUserSearch.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapUserSe0000644000000000000000000000303511623517156030434 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap; import org.springframework.ldap.core.DirContextOperations; /** * Obtains a user's information from the LDAP directory given a login name. *

    * May be optionally used to configure the LDAP authentication implementation when * a more sophisticated approach is required than just using a simple username->DN * mapping. *

    * * @author Luke Taylor * @version $Id$ */ public interface LdapUserSearch { //~ Methods ======================================================================================================== /** * Locates a single user in the directory and returns the LDAP information for that user. * * @param username the login name supplied to the authentication service. * * @return a DirContextOperations object containing the user's full DN and requested attributes. */ DirContextOperations searchForUser(String username); } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/populator/0000755000000000000000000000000011623517156030526 5ustar ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/populator/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/populator/0000644000000000000000000000010711623517156030526 0ustar LdapAuthoritiesPopulator implementations. ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/populator/DefaultLdapAuthoritiesPopulator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/populator/0000644000000000000000000002650511623517156030540 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap.populator; import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthorityImpl; import org.springframework.security.ldap.SpringSecurityLdapTemplate; import org.springframework.security.ldap.LdapAuthoritiesPopulator; import org.springframework.ldap.core.ContextSource; import org.springframework.ldap.core.DirContextOperations; import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.naming.directory.SearchControls; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * The default strategy for obtaining user role information from the directory. *

    * It obtains roles by performing a search for "groups" the user is a member of. *

    * A typical group search scenario would be where each group/role is specified using the groupOfNames * (or groupOfUniqueNames) LDAP objectClass and the user's DN is listed in the member (or * uniqueMember) attribute to indicate that they should be assigned that role. The following LDIF sample has * the groups stored under the DN ou=groups,dc=springframework,dc=org and a group called "developers" with * "ben" and "luke" as members: *

     * dn: ou=groups,dc=springframework,dc=org
     * objectClass: top
     * objectClass: organizationalUnit
     * ou: groups
     *
     * dn: cn=developers,ou=groups,dc=springframework,dc=org
     * objectClass: groupOfNames
     * objectClass: top
     * cn: developers
     * description: Spring Security Developers
     * member: uid=ben,ou=people,dc=springframework,dc=org
     * member: uid=luke,ou=people,dc=springframework,dc=org
     * ou: developer
     * 
    *

    * The group search is performed within a DN specified by the groupSearchBase property, which should * be relative to the root DN of its InitialDirContextFactory. If the search base is null, group searching is * disabled. The filter used in the search is defined by the groupSearchFilter property, with the filter * argument {0} being the full DN of the user. You can also optionally use the parameter {1}, which will be substituted * with the username. You can also specify which attribute defines the role name by setting * the groupRoleAttribute property (the default is "cn"). *

    * The configuration below shows how the group search might be performed with the above schema. *

     * <bean id="ldapAuthoritiesPopulator"
     *       class="org.springframework.security.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
     *   <constructor-arg ref="contextSource"/>
     *   <constructor-arg value="ou=groups"/>
     *   <property name="groupRoleAttribute" value="ou"/>
     * <!-- the following properties are shown with their default values -->
     *   <property name="searchSubTree" value="false"/>
     *   <property name="rolePrefix" value="ROLE_"/>
     *   <property name="convertToUpperCase" value="true"/>
     * </bean>
     * 
    * A search for roles for user "uid=ben,ou=people,dc=springframework,dc=org" would return the single granted authority * "ROLE_DEVELOPER". *

    * The single-level search is performed by default. Setting the searchSubTree property to true will enable * a search of the entire subtree under groupSearchBase. * * @author Luke Taylor * @version $Id$ */ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(DefaultLdapAuthoritiesPopulator.class); //~ Instance fields ================================================================================================ /** * A default role which will be assigned to all authenticated users if set */ private GrantedAuthority defaultRole; private SpringSecurityLdapTemplate ldapTemplate; /** * Controls used to determine whether group searches should be performed over the full sub-tree from the * base DN. Modified by searchSubTree property */ private SearchControls searchControls = new SearchControls(); /** * The ID of the attribute which contains the role name for a group */ private String groupRoleAttribute = "cn"; /** * The base DN from which the search for group membership should be performed */ private String groupSearchBase; /** * The pattern to be used for the user search. {0} is the user's DN */ private String groupSearchFilter = "(member={0})"; /** * Attributes of the User's LDAP Object that contain role name information. */ // private String[] userRoleAttributes = null; private String rolePrefix = "ROLE_"; private boolean convertToUpperCase = true; //~ Constructors =================================================================================================== /** * Constructor for group search scenarios. userRoleAttributes may still be * set as a property. * * @param contextSource supplies the contexts used to search for user roles. * @param groupSearchBase if this is an empty string the search will be performed from the root DN of the * context factory. */ public DefaultLdapAuthoritiesPopulator(ContextSource contextSource, String groupSearchBase) { Assert.notNull(contextSource, "contextSource must not be null"); ldapTemplate = new SpringSecurityLdapTemplate(contextSource); ldapTemplate.setSearchControls(searchControls); setGroupSearchBase(groupSearchBase); } //~ Methods ======================================================================================================== /** * This method should be overridden if required to obtain any additional * roles for the given user (on top of those obtained from the standard * search implemented by this class). * * @param user the context representing the user who's roles are required * @return the extra roles which will be merged with those returned by the group search */ protected Set getAdditionalRoles(DirContextOperations user, String username) { return null; } /** * Obtains the authorities for the user who's directory entry is represented by * the supplied LdapUserDetails object. * * @param user the user who's authorities are required * @return the set of roles granted to the user. */ public final GrantedAuthority[] getGrantedAuthorities(DirContextOperations user, String username) { String userDn = user.getNameInNamespace(); if (logger.isDebugEnabled()) { logger.debug("Getting authorities for user " + userDn); } Set roles = getGroupMembershipRoles(userDn, username); Set extraRoles = getAdditionalRoles(user, username); if (extraRoles != null) { roles.addAll(extraRoles); } if (defaultRole != null) { roles.add(defaultRole); } return (GrantedAuthority[]) roles.toArray(new GrantedAuthority[roles.size()]); } public Set getGroupMembershipRoles(String userDn, String username) { Set authorities = new HashSet(); if (getGroupSearchBase() == null) { return authorities; } if (logger.isDebugEnabled()) { logger.debug("Searching for roles for user '" + username + "', DN = " + "'" + userDn + "', with filter " + groupSearchFilter + " in search base '" + getGroupSearchBase() + "'"); } Set userRoles = ldapTemplate.searchForSingleAttributeValues(getGroupSearchBase(), groupSearchFilter, new String[]{userDn, username}, groupRoleAttribute); if (logger.isDebugEnabled()) { logger.debug("Roles from search: " + userRoles); } Iterator it = userRoles.iterator(); while (it.hasNext()) { String role = (String) it.next(); if (convertToUpperCase) { role = role.toUpperCase(); } authorities.add(new GrantedAuthorityImpl(rolePrefix + role)); } return authorities; } protected ContextSource getContextSource() { return ldapTemplate.getContextSource(); } /** * Set the group search base (name to search under) * * @param groupSearchBase if this is an empty string the search will be performed from the root DN of the context * factory. */ private void setGroupSearchBase(String groupSearchBase) { Assert.notNull(groupSearchBase, "The groupSearchBase (name to search under), must not be null."); this.groupSearchBase = groupSearchBase; if (groupSearchBase.length() == 0) { logger.info("groupSearchBase is empty. Searches will be performed from the context source base"); } } protected String getGroupSearchBase() { return groupSearchBase; } public void setConvertToUpperCase(boolean convertToUpperCase) { this.convertToUpperCase = convertToUpperCase; } /** * The default role which will be assigned to all users. * * @param defaultRole the role name, including any desired prefix. */ public void setDefaultRole(String defaultRole) { Assert.notNull(defaultRole, "The defaultRole property cannot be set to null"); this.defaultRole = new GrantedAuthorityImpl(defaultRole); } public void setGroupRoleAttribute(String groupRoleAttribute) { Assert.notNull(groupRoleAttribute, "groupRoleAttribute must not be null"); this.groupRoleAttribute = groupRoleAttribute; } public void setGroupSearchFilter(String groupSearchFilter) { Assert.notNull(groupSearchFilter, "groupSearchFilter must not be null"); this.groupSearchFilter = groupSearchFilter; } /** * Sets the prefix which will be prepended to the values loaded from the directory. * Defaults to "ROLE_" for compatibility with RoleVoter/tt>. */ public void setRolePrefix(String rolePrefix) { Assert.notNull(rolePrefix, "rolePrefix must not be null"); this.rolePrefix = rolePrefix; } /** * If set to true, a subtree scope search will be performed. If false a single-level search is used. * * @param searchSubtree set to true to enable searching of the entire tree below the groupSearchBase. */ public void setSearchSubtree(boolean searchSubtree) { int searchScope = searchSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE; searchControls.setSearchScope(searchScope); } } ././@LongLink0000000000000000000000000000022400000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/populator/UserDetailsServiceLdapAuthoritiesPopulator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/populator/0000644000000000000000000000211711623517156030531 0ustar package org.springframework.security.ldap.populator; import org.springframework.security.ldap.LdapAuthoritiesPopulator; import org.springframework.security.GrantedAuthority; import org.springframework.security.userdetails.UserDetailsService; import org.springframework.ldap.core.DirContextOperations; import org.springframework.util.Assert; /** * Simple LdapAuthoritiesPopulator which delegates to a UserDetailsService, using the name which * was supplied at login as the username. * * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class UserDetailsServiceLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator { private UserDetailsService userDetailsService; public UserDetailsServiceLdapAuthoritiesPopulator(UserDetailsService userService) { Assert.notNull(userService, "userDetailsService cannot be null"); this.userDetailsService = userService; } public GrantedAuthority[] getGrantedAuthorities(DirContextOperations userData, String username) { return userDetailsService.loadUserByUsername(username).getAuthorities(); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapCallback.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapCallba0000644000000000000000000000222211623517156030401 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap; import javax.naming.NamingException; import javax.naming.directory.DirContext; /** * Callback object for use with SpringSecurityLdapTemplate. * * @deprecated use spring-ldap ContextExecutor instead. * @TODO: Delete before 2.0 release * * @author Ben Alex */ public interface LdapCallback { //~ Methods ======================================================================================================== Object doInDirContext(DirContext dirContext) throws NamingException; } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapDataAccessException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapDataAc0000644000000000000000000000247111623517156030346 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap; import org.springframework.dao.DataAccessException; /** * Used to wrap unexpected NamingExceptions while accessing the LDAP server or for other LDAP-related data problems * such as data we can't handle. * * @deprecated Spring LDAP classes are now used instead. * @author Luke Taylor * @version $Id$ */ public class LdapDataAccessException extends DataAccessException { //~ Constructors =================================================================================================== public LdapDataAccessException(String msg) { super(msg); } public LdapDataAccessException(String msg, Throwable ex) { super(msg, ex); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/search/0000755000000000000000000000000011623517156027746 5ustar ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/search/FilterBasedLdapUserSearch.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/search/Fil0000644000000000000000000001576611623517156030422 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap.search; import org.springframework.security.ldap.SpringSecurityLdapTemplate; import org.springframework.security.ldap.LdapUserSearch; import org.springframework.security.userdetails.UsernameNotFoundException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.util.Assert; import org.springframework.ldap.core.ContextSource; import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.support.BaseLdapPathContextSource; import javax.naming.directory.SearchControls; /** * LdapUserSearch implementation which uses an Ldap filter to locate the user. * * @author Robert Sanders * @author Luke Taylor * @version $Id$ * * @see SearchControls */ public class FilterBasedLdapUserSearch implements LdapUserSearch { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(FilterBasedLdapUserSearch.class); //~ Instance fields ================================================================================================ private ContextSource contextSource; /** * The LDAP SearchControls object used for the search. Shared between searches so shouldn't be modified * once the bean has been configured. */ private SearchControls searchControls = new SearchControls(); /** Context name to search in, relative to the base of the configured ContextSource. */ private String searchBase = ""; /** * The filter expression used in the user search. This is an LDAP search filter (as defined in 'RFC 2254') * with optional arguments. See the documentation for the search methods in {@link * javax.naming.directory.DirContext DirContext} for more information. * *

    In this case, the username is the only parameter.

    * Possible examples are: *
      *
    • (uid={0}) - this would search for a username match on the uid attribute.
    • *
    */ private String searchFilter; //~ Constructors =================================================================================================== public FilterBasedLdapUserSearch(String searchBase, String searchFilter, BaseLdapPathContextSource contextSource) { Assert.notNull(contextSource, "contextSource must not be null"); Assert.notNull(searchFilter, "searchFilter must not be null."); Assert.notNull(searchBase, "searchBase must not be null (an empty string is acceptable)."); this.searchFilter = searchFilter; this.contextSource = contextSource; this.searchBase = searchBase; setSearchSubtree(true); if (searchBase.length() == 0) { logger.info("SearchBase not set. Searches will be performed from the root: " + contextSource.getBaseLdapPath()); } } //~ Methods ======================================================================================================== /** * Return the LdapUserDetails containing the user's information * * @param username the username to search for. * * @return An LdapUserDetails object containing the details of the located user's directory entry * * @throws UsernameNotFoundException if no matching entry is found. */ public DirContextOperations searchForUser(String username) { if (logger.isDebugEnabled()) { logger.debug("Searching for user '" + username + "', with user search " + this); } SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(contextSource); template.setSearchControls(searchControls); try { return template.searchForSingleEntry(searchBase, searchFilter, new String[] {username}); } catch (IncorrectResultSizeDataAccessException notFound) { if (notFound.getActualSize() == 0) { throw new UsernameNotFoundException("User " + username + " not found in directory.", username); } // Search should never return multiple results if properly configured, so just rethrow throw notFound; } } /** * Sets the corresponding property on the {@link SearchControls} instance used in the search. * * @param deref the derefLinkFlag value as defined in SearchControls.. */ public void setDerefLinkFlag(boolean deref) { searchControls.setDerefLinkFlag(deref); } /** * If true then searches the entire subtree as identified by context, if false (the default) then only * searches the level identified by the context. * * @param searchSubtree true the underlying search controls should be set to SearchControls.SUBTREE_SCOPE * rather than SearchControls.ONELEVEL_SCOPE. */ public void setSearchSubtree(boolean searchSubtree) { searchControls.setSearchScope(searchSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE); } /** * The time to wait before the search fails; the default is zero, meaning forever. * * @param searchTimeLimit the time limit for the search (in milliseconds). */ public void setSearchTimeLimit(int searchTimeLimit) { searchControls.setTimeLimit(searchTimeLimit); } /** * Specifies the attributes that will be returned as part of the search. *

    * null indicates that all attributes will be returned. * An empty array indicates no attributes are returned. * * @param attrs An array of attribute names identifying the attributes that * will be returned. Can be null. */ public void setReturningAttributes(String[] attrs) { searchControls.setReturningAttributes(attrs); } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("[ searchFilter: '").append(searchFilter).append("', "); sb.append("searchBase: '").append(searchBase).append("'"); sb.append(", scope: ") .append(searchControls.getSearchScope() == SearchControls.SUBTREE_SCOPE ? "subtree" : "single-level, "); sb.append(", searchTimeLimit: ").append(searchControls.getTimeLimit()); sb.append(", derefLinkFlag: ").append(searchControls.getDerefLinkFlag()).append(" ]"); return sb.toString(); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/search/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/search/pac0000644000000000000000000000017611623517156030440 0ustar LdapUserSearch implementations. These may be used to locate the user in the directory. ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/SpringSecurityAuthenticationSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/SpringSecu0000644000000000000000000000507311623517156030513 0ustar package org.springframework.security.ldap; import org.springframework.security.Authentication; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; import org.springframework.security.userdetails.ldap.LdapUserDetails; import org.springframework.ldap.core.AuthenticationSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * An AuthenticationSource to retrieve authentication information stored in Spring Security's * {@link SecurityContextHolder}. *

    * This is a copy of Spring LDAP's AcegiAuthenticationSource, updated for use with Spring Security 2.0. * * @author Mattias Arthursson * @author Luke Taylor * @since 2.0 * @version $Id$ */ public class SpringSecurityAuthenticationSource implements AuthenticationSource { private static final Log log = LogFactory.getLog(SpringSecurityAuthenticationSource.class); /** * Get the principals of the logged in user, in this case the distinguished * name. * * @return the distinguished name of the logged in user. */ public String getPrincipal() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { log.warn("No Authentication object set in SecurityContext - returning empty String as Principal"); return ""; } Object principal = authentication.getPrincipal(); if (principal instanceof LdapUserDetails) { LdapUserDetails details = (LdapUserDetails) principal; return details.getDn(); } else if (authentication instanceof AnonymousAuthenticationToken) { if (log.isDebugEnabled()) { log.debug("Anonymous Authentication, returning empty String as Principal"); } return ""; } else { throw new IllegalArgumentException("The principal property of the authentication object" + "needs to be an LdapUserDetails."); } } /** * @see org.springframework.ldap.core.AuthenticationSource#getCredentials() */ public String getCredentials() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { log.warn("No Authentication object set in SecurityContext - returning empty String as Credentials"); return ""; } return (String) authentication.getCredentials(); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapUtils.0000644000000000000000000001410111623517156030400 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DistinguishedName; import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.naming.Context; import javax.naming.NamingException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; /** * LDAP Utility methods. * * @author Luke Taylor * @version $Id$ */ public final class LdapUtils { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(LdapUtils.class); //~ Constructors =================================================================================================== private LdapUtils() { } //~ Methods ======================================================================================================== public static void closeContext(Context ctx) { if(ctx instanceof DirContextAdapter) { return; } try { if (ctx != null) { ctx.close(); } } catch (NamingException e) { logger.error("Failed to close context.", e); } } /** * Obtains the part of a DN relative to a supplied base context. *

    If the DN is "cn=bob,ou=people,dc=springframework,dc=org" and the base context name is * "ou=people,dc=springframework,dc=org" it would return "cn=bob". *

    * * @param fullDn the DN * @param baseCtx the context to work out the name relative to. * * @return the * * @throws NamingException any exceptions thrown by the context are propagated. */ public static String getRelativeName(String fullDn, Context baseCtx) throws NamingException { String baseDn = baseCtx.getNameInNamespace(); if (baseDn.length() == 0) { return fullDn; } DistinguishedName base = new DistinguishedName(baseDn); DistinguishedName full = new DistinguishedName(fullDn); if(base.equals(full)) { return ""; } Assert.isTrue(full.startsWith(base), "Full DN does not start with base DN"); full.removeFirst(base); return full.toString(); } /** * Gets the full dn of a name by prepending the name of the context it is relative to. * If the name already contains the base name, it is returned unaltered. */ public static DistinguishedName getFullDn(DistinguishedName dn, Context baseCtx) throws NamingException { DistinguishedName baseDn = new DistinguishedName(baseCtx.getNameInNamespace()); if(dn.contains(baseDn)) { return dn; } baseDn.append(dn); return baseDn; } public static byte[] getUtf8Bytes(String s) { try { return s.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { // Should be impossible since UTF-8 is required by all implementations throw new IllegalStateException("Failed to convert string to UTF-8 bytes. Shouldn't be possible"); } } public static String getUtf8BytesAsString(byte[] utf8) { try { return new String(utf8, "UTF-8"); } catch (UnsupportedEncodingException e) { // Should be impossible since UTF-8 is required by all implementations throw new IllegalStateException("Failed to convert string to UTF-8 bytes. Shouldn't be possible"); } } public static String convertPasswordToString(Object passObj) { Assert.notNull(passObj, "Password object to convert must not be null"); if(passObj instanceof byte[]) { return getUtf8BytesAsString((byte[])passObj); } else if (passObj instanceof String) { return (String)passObj; } else { throw new IllegalArgumentException("Password object was not a String or byte array."); } } /** * Works out the root DN for an LDAP URL.

    For example, the URL * ldap://monkeymachine:11389/dc=springframework,dc=org has the root DN "dc=springframework,dc=org".

    * * @param url the LDAP URL * * @return the root DN */ public static String parseRootDnFromUrl(String url) { Assert.hasLength(url); String urlRootDn = ""; if (url.startsWith("ldap:") || url.startsWith("ldaps:")) { URI uri = parseLdapUrl(url); urlRootDn = uri.getRawPath(); } else { // Assume it's an embedded server urlRootDn = url; } if (urlRootDn.startsWith("/")) { urlRootDn = urlRootDn.substring(1); } return urlRootDn; } /** * Parses the supplied LDAP URL. * @param url the URL (e.g. ldap://monkeymachine:11389/dc=springframework,dc=org). * @return the URI object created from the URL * @throws IllegalArgumentException if the URL is null, empty or the URI syntax is invalid. */ private static URI parseLdapUrl(String url) { Assert.hasLength(url); try { return new URI(url); } catch (URISyntaxException e) { IllegalArgumentException iae = new IllegalArgumentException("Unable to parse url: " + url); iae.initCause(e); throw iae; } } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapEntryMapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapEntryM0000644000000000000000000000241011623517156030440 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap; import javax.naming.NamingException; import javax.naming.directory.Attributes; /** * A mapper for use with {@link SpringSecurityLdapTemplate}. Creates a customized object from * a set of attributes retrieved from a directory entry. * * @author Luke Taylor * @deprecated in favour of Spring LDAP ContextMapper * @version $Id$ */ public interface LdapEntryMapper { //~ Methods ======================================================================================================== Object mapAttributes(String dn, Attributes attributes) throws NamingException; } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/DefaultInitialDirContextFactory.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/DefaultIni0000644000000000000000000003315711623517156030461 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.BadCredentialsException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; import org.springframework.ldap.UncategorizedLdapException; import org.springframework.ldap.core.support.DefaultDirObjectFactory; import org.springframework.ldap.core.DistinguishedName; import org.springframework.dao.DataAccessException; import java.util.Hashtable; import java.util.Map; import java.util.StringTokenizer; import javax.naming.CommunicationException; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.OperationNotSupportedException; import javax.naming.ldap.InitialLdapContext; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; /** * Encapsulates the information for connecting to an LDAP server and provides an access point for obtaining * DirContext references. *

    * The directory location is configured using by setting the constructor argument * providerUrl. This should be in the form ldap://monkeymachine.co.uk:389/dc=springframework,dc=org. * The Sun JNDI provider also supports lists of space-separated URLs, each of which will be tried in turn until a * connection is obtained. *

    *

    To obtain an initial context, the client calls the newInitialDirContext method. There are two * signatures - one with no arguments and one which allows binding with a specific username and password. *

    *

    The no-args version will bind anonymously unless a manager login has been configured using the properties * managerDn and managerPassword, in which case it will bind as the manager user.

    *

    Connection pooling is enabled by default for anonymous or manager connections, but not when binding as a * specific user.

    * * @author Robert Sanders * @author Luke Taylor * @version $Id$ * * * @deprecated use {@link DefaultSpringSecurityContextSource} instead. * * @see The Java tutorial's guide to LDAP * connection pooling */ public class DefaultInitialDirContextFactory implements InitialDirContextFactory, SpringSecurityContextSource, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(DefaultInitialDirContextFactory.class); private static final String CONNECTION_POOL_KEY = "com.sun.jndi.ldap.connect.pool"; private static final String AUTH_TYPE_NONE = "none"; //~ Instance fields ================================================================================================ /** Allows extra environment variables to be added at config time. */ private Map extraEnvVars = null; protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); /** Type of authentication within LDAP; default is simple. */ private String authenticationType = "simple"; /** * The INITIAL_CONTEXT_FACTORY used to create the JNDI Factory. Default is * "com.sun.jndi.ldap.LdapCtxFactory"; you should not need to set this unless you have unusual needs. */ private String initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory"; private String dirObjectFactoryClass = DefaultDirObjectFactory.class.getName(); /** * If your LDAP server does not allow anonymous searches then you will need to provide a "manager" user's * DN to log in with. */ private String managerDn = null; /** The manager user's password. */ private String managerPassword = "manager_password_not_set"; /** The LDAP url of the server (and root context) to connect to. */ private String providerUrl; /** * The root DN. This is worked out from the url. It is used by client classes when forming a full DN for * bind authentication (for example). */ private String rootDn = null; /** * Use the LDAP Connection pool; if true, then the LDAP environment property * "com.sun.jndi.ldap.connect.pool" is added to any other JNDI properties. */ private boolean useConnectionPool = true; /** Set to true for ldap v3 compatible servers */ private boolean useLdapContext = false; //~ Constructors =================================================================================================== /** * Create and initialize an instance to the LDAP url provided * * @param providerUrl a String of the form ldap://localhost:389/base_dn */ public DefaultInitialDirContextFactory(String providerUrl) { this.setProviderUrl(providerUrl); } //~ Methods ======================================================================================================== /** * Set the LDAP url * * @param providerUrl a String of the form ldap://localhost:389/base_dn */ private void setProviderUrl(String providerUrl) { Assert.hasLength(providerUrl, "An LDAP connection URL must be supplied."); this.providerUrl = providerUrl; StringTokenizer st = new StringTokenizer(providerUrl); // Work out rootDn from the first URL and check that the other URLs (if any) match while (st.hasMoreTokens()) { String url = st.nextToken(); String urlRootDn = LdapUtils.parseRootDnFromUrl(url); logger.info(" URL '" + url + "', root DN is '" + urlRootDn + "'"); if (rootDn == null) { rootDn = urlRootDn; } else if (!rootDn.equals(urlRootDn)) { throw new IllegalArgumentException("Root DNs must be the same when using multiple URLs"); } } // This doesn't necessarily hold for embedded servers. //Assert.isTrue(uri.getScheme().equals("ldap"), "Ldap URL must start with 'ldap://'"); } /** * Get the LDAP url * * @return the url */ private String getProviderUrl() { return providerUrl; } private InitialDirContext connect(Hashtable env) { if (logger.isDebugEnabled()) { Hashtable envClone = (Hashtable) env.clone(); if (envClone.containsKey(Context.SECURITY_CREDENTIALS)) { envClone.put(Context.SECURITY_CREDENTIALS, "******"); } logger.debug("Creating InitialDirContext with environment " + envClone); } try { return useLdapContext ? new InitialLdapContext(env, null) : new InitialDirContext(env); } catch (NamingException ne) { if ((ne instanceof javax.naming.AuthenticationException) || (ne instanceof OperationNotSupportedException)) { throw new BadCredentialsException(messages.getMessage("DefaultIntitalDirContextFactory.badCredentials", "Bad credentials"), ne); } if (ne instanceof CommunicationException) { throw new UncategorizedLdapException(messages.getMessage( "DefaultIntitalDirContextFactory.communicationFailure", "Unable to connect to LDAP server"), ne); } throw new UncategorizedLdapException(messages.getMessage( "DefaultIntitalDirContextFactory.unexpectedException", "Failed to obtain InitialDirContext due to unexpected exception"), ne); } } /** * Sets up the environment parameters for creating a new context. * * @return the Hashtable describing the base DirContext that will be created, minus the username/password if any. */ protected Hashtable getEnvironment() { Hashtable env = new Hashtable(); env.put(Context.SECURITY_AUTHENTICATION, authenticationType); env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory); env.put(Context.PROVIDER_URL, getProviderUrl()); if (useConnectionPool) { env.put(CONNECTION_POOL_KEY, "true"); } if ((extraEnvVars != null) && (extraEnvVars.size() > 0)) { env.putAll(extraEnvVars); } return env; } /** * Returns the root DN of the configured provider URL. For example, if the URL is * ldap://monkeymachine.co.uk:389/dc=springframework,dc=org the value will be * dc=springframework,dc=org. * * @return the root DN calculated from the path of the LDAP url. */ public String getRootDn() { return rootDn; } /** * Connects anonymously unless a manager user has been specified, in which case it will bind as the * manager. * * @return the resulting context object. */ public DirContext newInitialDirContext() { if (managerDn != null) { return newInitialDirContext(managerDn, managerPassword); } Hashtable env = getEnvironment(); env.put(Context.SECURITY_AUTHENTICATION, AUTH_TYPE_NONE); return connect(env); } public DirContext newInitialDirContext(String username, String password) { Hashtable env = getEnvironment(); // Don't pool connections for individual users if (!username.equals(managerDn)) { env.remove(CONNECTION_POOL_KEY); } env.put(Context.SECURITY_PRINCIPAL, username); env.put(Context.SECURITY_CREDENTIALS, password); if(dirObjectFactoryClass != null) { env.put(Context.OBJECT_FACTORIES, dirObjectFactoryClass); } return connect(env); } /** Spring LDAP ContextSource method */ public DirContext getReadOnlyContext() throws DataAccessException { return newInitialDirContext(); } /** Spring LDAP ContextSource method */ public DirContext getReadWriteContext() throws DataAccessException { return newInitialDirContext(); } public void setAuthenticationType(String authenticationType) { Assert.hasLength(authenticationType, "LDAP Authentication type must not be empty or null"); this.authenticationType = authenticationType; } /** * Sets any custom environment variables which will be added to the those returned * by the getEnvironment method. * * @param extraEnvVars extra environment variables to be added at config time. */ public void setExtraEnvVars(Map extraEnvVars) { Assert.notNull(extraEnvVars, "Extra environment map cannot be null."); this.extraEnvVars = extraEnvVars; } public void setInitialContextFactory(String initialContextFactory) { Assert.hasLength(initialContextFactory, "Initial context factory name cannot be empty or null"); this.initialContextFactory = initialContextFactory; } /** * Sets the directory user to authenticate as when obtaining a context using the * newInitialDirContext() method. * If no name is supplied then the context will be obtained anonymously. * * @param managerDn The name of the "manager" user for default authentication. */ public void setManagerDn(String managerDn) { Assert.hasLength(managerDn, "Manager user name cannot be empty or null."); this.managerDn = managerDn; } /** * Sets the password which will be used in combination with the manager DN. * * @param managerPassword The "manager" user's password. */ public void setManagerPassword(String managerPassword) { Assert.hasLength(managerPassword, "Manager password must not be empty or null."); this.managerPassword = managerPassword; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } /** * Connection pooling is enabled by default for anonymous or "manager" connections when using the default * Sun provider. To disable all connection pooling, set this property to false. * * @param useConnectionPool whether to pool connections for non-specific users. */ public void setUseConnectionPool(boolean useConnectionPool) { this.useConnectionPool = useConnectionPool; } public void setUseLdapContext(boolean useLdapContext) { this.useLdapContext = useLdapContext; } public void setDirObjectFactory(String dirObjectFactory) { this.dirObjectFactoryClass = dirObjectFactory; } public DirContext getReadWriteContext(String userDn, Object credentials) { return newInitialDirContext(userDn, (String) credentials); } public DistinguishedName getBaseLdapPath() { return new DistinguishedName(rootDn); } public String getBaseLdapPathAsString() { return getBaseLdapPath().toString(); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/InitialDirContextFactory.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/InitialDir0000644000000000000000000000364711623517156030466 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap; import javax.naming.directory.DirContext; /** * Access point for obtaining LDAP contexts. * * @see org.springframework.security.ldap.DefaultInitialDirContextFactory * * @deprecated Use SpringSecurityContextSource instead * @author Luke Taylor * @version $Id$ */ public interface InitialDirContextFactory { //~ Methods ======================================================================================================== /** * Returns the root DN of the contexts supplied by this factory. * The names for searches etc. which are performed against contexts * returned by this factory should be relative to the root DN. * * @return The DN of the contexts returned by this factory. */ String getRootDn(); /** * Provides an initial context without specific user information. * * @return An initial context for the LDAP directory */ DirContext newInitialDirContext(); /** * Provides an initial context by binding as a specific user. * * @param userDn the user to authenticate as when obtaining the context. * @param password the user's password. * * @return An initial context for the LDAP directory */ DirContext newInitialDirContext(String userDn, String password); } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/SpringSecurityLdapTemplate.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/SpringSecu0000644000000000000000000002436211623517156030515 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap; import java.text.MessageFormat; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.PartialResultException; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.ldap.core.ContextExecutor; import org.springframework.ldap.core.ContextMapper; import org.springframework.ldap.core.ContextSource; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.DistinguishedName; import org.springframework.ldap.core.LdapEncoder; import org.springframework.ldap.core.LdapTemplate; import org.springframework.util.Assert; /** * Extension of Spring LDAP's LdapTemplate class which adds extra functionality required by Spring Security. * * @author Ben Alex * @author Luke Taylor * @since 2.0 */ public class SpringSecurityLdapTemplate extends LdapTemplate { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(SpringSecurityLdapTemplate.class); public static final String[] NO_ATTRS = new String[0]; //~ Instance fields ================================================================================================ /** Default search controls */ private SearchControls searchControls = new SearchControls(); //~ Constructors =================================================================================================== public SpringSecurityLdapTemplate(ContextSource contextSource) { Assert.notNull(contextSource, "ContextSource cannot be null"); setContextSource(contextSource); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); } //~ Methods ======================================================================================================== /** * Performs an LDAP compare operation of the value of an attribute for a particular directory entry. * * @param dn the entry who's attribute is to be used * @param attributeName the attribute who's value we want to compare * @param value the value to be checked against the directory value * * @return true if the supplied value matches that in the directory */ public boolean compare(final String dn, final String attributeName, final Object value) { final String comparisonFilter = "(" + attributeName + "={0})"; class LdapCompareCallback implements ContextExecutor { public Object executeWithContext(DirContext ctx) throws NamingException { SearchControls ctls = new SearchControls(); ctls.setReturningAttributes(NO_ATTRS); ctls.setSearchScope(SearchControls.OBJECT_SCOPE); NamingEnumeration results = ctx.search(dn, comparisonFilter, new Object[] {value}, ctls); return Boolean.valueOf(results.hasMore()); } } Boolean matches = (Boolean) executeReadOnly(new LdapCompareCallback()); return matches.booleanValue(); } /** * Composes an object from the attributes of the given DN. * * @param dn the directory entry which will be read * @param attributesToRetrieve the named attributes which will be retrieved from the directory entry. * * @return the object created by the mapper */ public DirContextOperations retrieveEntry(final String dn, final String[] attributesToRetrieve) { return (DirContextOperations) executeReadOnly(new ContextExecutor() { public Object executeWithContext(DirContext ctx) throws NamingException { Attributes attrs = ctx.getAttributes(dn, attributesToRetrieve); // Object object = ctx.lookup(LdapUtils.getRelativeName(dn, ctx)); return new DirContextAdapter(attrs, new DistinguishedName(dn), new DistinguishedName(ctx.getNameInNamespace())); } }); } /** * Performs a search using the supplied filter and returns the union of the values of the named attribute * found in all entries matched by the search. Note that one directory entry may have several values for the * attribute. Intended for role searches and similar scenarios. * * @param base the DN to search in * @param filter search filter to use * @param params the parameters to substitute in the search filter * @param attributeName the attribute who's values are to be retrieved. * * @return the set of String values for the attribute as a union of the values found in all the matching entries. */ public Set searchForSingleAttributeValues(final String base, final String filter, final Object[] params, final String attributeName) { // Escape the params acording to RFC2254 Object[] encodedParams = new String[params.length]; for (int i=0; i < params.length; i++) { encodedParams[i] = LdapEncoder.filterEncode(params[i].toString()); } String formattedFilter = MessageFormat.format(filter, encodedParams); logger.debug("Using filter: " + formattedFilter); final HashSet set = new HashSet(); ContextMapper roleMapper = new ContextMapper() { public Object mapFromContext(Object ctx) { DirContextAdapter adapter = (DirContextAdapter) ctx; String[] values = adapter.getStringAttributes(attributeName); if (values == null || values.length == 0) { logger.debug("No attribute value found for '" + attributeName + "'"); } else { set.addAll(Arrays.asList(values)); } return null; } }; SearchControls ctls = new SearchControls(); ctls.setSearchScope(searchControls.getSearchScope()); ctls.setReturningAttributes(new String[] {attributeName}); ctls.setReturningObjFlag(false); search(base, formattedFilter, ctls, roleMapper); return set; } /** * Performs a search, with the requirement that the search shall return a single directory entry, and uses * the supplied mapper to create the object from that entry. *

    * Ignores PartialResultException if thrown, for compatibility with Active Directory * (see {@link LdapTemplate#setIgnorePartialResultException(boolean)}). * * @param base the search base, relative to the base context supplied by the context source. * @param filter the LDAP search filter * @param params parameters to be substituted in the search. * * @return a DirContextOperations instance created from the matching entry. * * @throws IncorrectResultSizeDataAccessException if no results are found or the search returns more than one * result. */ public DirContextOperations searchForSingleEntry(final String base, final String filter, final Object[] params) { return (DirContextOperations) executeReadOnly(new ContextExecutor() { public Object executeWithContext(DirContext ctx) throws NamingException { DistinguishedName ctxBaseDn = new DistinguishedName(ctx.getNameInNamespace()); if (logger.isDebugEnabled()) { logger.debug("Searching for entry in under DN '" + ctxBaseDn + "', base = '" + base + "', filter = '" + filter + "'"); } NamingEnumeration resultsEnum = ctx.search(base, filter, params, searchControls); Set results = new HashSet(); try { while (resultsEnum.hasMore()) { SearchResult searchResult = (SearchResult) resultsEnum.next(); // Work out the DN of the matched entry DistinguishedName dn = new DistinguishedName(searchResult.getName()); if (base.length() > 0) { dn.prepend(new DistinguishedName(base)); } if (logger.isDebugEnabled()) { logger.debug("Found DN: " + dn); } results.add(new DirContextAdapter(searchResult.getAttributes(), dn, ctxBaseDn)); } } catch (PartialResultException e) { logger.info("Ignoring PartialResultException"); } if (results.size() == 0) { throw new IncorrectResultSizeDataAccessException(1, 0); } if (results.size() > 1) { throw new IncorrectResultSizeDataAccessException(1, results.size()); } return results.toArray()[0]; } }); } /** * Sets the search controls which will be used for search operations by the template. * * @param searchControls the SearchControls instance which will be cached in the template. */ public void setSearchControls(SearchControls searchControls) { this.searchControls = searchControls; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/SpringSecurityContextSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/SpringSecu0000644000000000000000000000145111623517156030507 0ustar package org.springframework.security.ldap; import org.springframework.ldap.core.support.BaseLdapPathContextSource; import org.springframework.ldap.core.ContextSource; import javax.naming.directory.DirContext; /** * Extension of {@link ContextSource} which allows binding explicitly as a particular user. * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public interface SpringSecurityContextSource extends BaseLdapPathContextSource { /** * Obtains a context using the supplied distinguished name and credentials. * * @param userDn the distinguished name of the user to authenticate as * @param credentials the user's password * @return a context authenticated as the supplied user */ DirContext getReadWriteContext(String userDn, Object credentials); } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/DefaultLdapUsernameToDnMapper.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/DefaultLda0000644000000000000000000000235311623517156030434 0ustar package org.springframework.security.ldap; import org.springframework.ldap.core.DistinguishedName; /** * This implementation appends a name component to the userDnBase context using the * usernameAttributeName property. So if the uid attribute is used to store the username, and the * base DN is cn=users and we are creating a new user called "sam", then the DN will be * uid=sam,cn=users. * * @author Luke Taylor * @version $Id$ */ public class DefaultLdapUsernameToDnMapper implements LdapUsernameToDnMapper { private String userDnBase; private String usernameAttribute; /** * @param userDnBase the base name of the DN * @param usernameAttribute the attribute to append for the username component. */ public DefaultLdapUsernameToDnMapper(String userDnBase, String usernameAttribute) { this.userDnBase = userDnBase; this.usernameAttribute = usernameAttribute; } /** * Assembles the Distinguished Name that should be used the given username. */ public DistinguishedName buildDn(String username) { DistinguishedName dn = new DistinguishedName(userDnBase); dn.add(usernameAttribute, username); return dn; } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/DefaultSpringSecurityContextSource.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/DefaultSpr0000644000000000000000000000707511623517156030506 0ustar package org.springframework.security.ldap; import org.springframework.security.BadCredentialsException; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.ldap.core.support.LdapContextSource; import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.naming.Context; import javax.naming.directory.DirContext; import java.util.ArrayList; import java.util.Hashtable; import java.util.StringTokenizer; /** * SpringSecurityContextSource implementation which uses Spring LDAP's LdapContextSource as a base * class. Intended as a replacement for DefaultInitialDirContextFactory from versions of the framework prior * to 2.0. * * @author Luke Taylor * @version $Id$ * @since 2.0 */ public class DefaultSpringSecurityContextSource extends LdapContextSource implements SpringSecurityContextSource, MessageSourceAware { private static final Log logger = LogFactory.getLog(DefaultSpringSecurityContextSource.class); private String rootDn; protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); /** * Create and initialize an instance which will connect to the supplied LDAP URL. * * @param providerUrl an LDAP URL of the form ldap://localhost:389/base_dn */ public DefaultSpringSecurityContextSource(String providerUrl) { Assert.hasLength(providerUrl, "An LDAP connection URL must be supplied."); StringTokenizer st = new StringTokenizer(providerUrl); ArrayList urls = new ArrayList(); // Work out rootDn from the first URL and check that the other URLs (if any) match while (st.hasMoreTokens()) { String url = st.nextToken(); String urlRootDn = LdapUtils.parseRootDnFromUrl(url); urls.add(url.substring(0, url.lastIndexOf(urlRootDn))); logger.info(" URL '" + url + "', root DN is '" + urlRootDn + "'"); if (rootDn == null) { rootDn = urlRootDn; } else if (!rootDn.equals(urlRootDn)) { throw new IllegalArgumentException("Root DNs must be the same when using multiple URLs"); } } super.setUrls((String[]) urls.toArray(new String[urls.size()])); super.setBase(rootDn); } public DirContext getReadWriteContext(String userDn, Object credentials) { Hashtable env = new Hashtable(getAnonymousEnv()); env.put(Context.SECURITY_PRINCIPAL, userDn); env.put(Context.SECURITY_CREDENTIALS, credentials); env.remove(SUN_LDAP_POOLING_FLAG); if (logger.isDebugEnabled()) { logger.debug("Creating context with principal: '" + userDn + "'"); } try { return createContext(env); } catch (org.springframework.ldap.NamingException e) { if ((e instanceof org.springframework.ldap.AuthenticationException) || (e instanceof org.springframework.ldap.OperationNotSupportedException)) { throw new BadCredentialsException( messages.getMessage("DefaultSpringSecurityContextSource.badCredentials", "Bad credentials"), e); } throw e; } } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapAuthoritiesPopulator.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/ldap/LdapAuthor0000644000000000000000000000277411623517156030501 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.ldap; import org.springframework.security.GrantedAuthority; import org.springframework.ldap.core.DirContextOperations; /** * Obtains a list of granted authorities for an Ldap user. *

    * Used by the LdapAuthenticationProvider once a user has been * authenticated to create the final user details object. *

    * * @author Luke Taylor * @version $Id$ */ public interface LdapAuthoritiesPopulator { //~ Methods ======================================================================================================== /** * Get the list of authorities for the user. * * @param userData the context object which was returned by the LDAP authenticator. * * @return the granted authorities for the given user. * */ GrantedAuthority[] getGrantedAuthorities(DirContextOperations userData, String username); } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/runas/0000755000000000000000000000000011623517156026711 5ustar ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/runas/RunAsUserToken.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/runas/RunAsUser0000644000000000000000000000471711623517156030534 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.runas; import org.springframework.security.GrantedAuthority; import org.springframework.security.providers.AbstractAuthenticationToken; /** * An immutable {@link org.springframework.security.Authentication} implementation that supports {@link RunAsManagerImpl}. * * @author Ben Alex * @version $Id$ */ public class RunAsUserToken extends AbstractAuthenticationToken { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private Class originalAuthentication; private Object credentials; private Object principal; private int keyHash; //~ Constructors =================================================================================================== public RunAsUserToken(String key, Object principal, Object credentials, GrantedAuthority[] authorities, Class originalAuthentication) { super(authorities); this.keyHash = key.hashCode(); this.principal = principal; this.credentials = credentials; this.originalAuthentication = originalAuthentication; setAuthenticated(true); } //~ Methods ======================================================================================================== public Object getCredentials() { return this.credentials; } public int getKeyHash() { return this.keyHash; } public Class getOriginalAuthentication() { return this.originalAuthentication; } public Object getPrincipal() { return this.principal; } public String toString() { StringBuffer sb = new StringBuffer(super.toString()); sb.append("; Original Class: ").append(this.originalAuthentication.getName()); return sb.toString(); } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/runas/RunAsImplAuthenticationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/runas/RunAsImpl0000644000000000000000000000644711623517156030521 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.runas; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.BadCredentialsException; import org.springframework.security.providers.AuthenticationProvider; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.util.Assert; /** * An {@link AuthenticationProvider} implementation that can authenticate a {@link RunAsUserToken}.

    Configured in * the bean context with a key that should match the key used by adapters to generate the RunAsUserToken. * It treats as valid any RunAsUserToken instance presenting a hash code that matches the * RunAsImplAuthenticationProvider-configured key.

    *

    If the key does not match, a BadCredentialsException is thrown.

    */ public class RunAsImplAuthenticationProvider implements InitializingBean, AuthenticationProvider, MessageSourceAware { //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private String key; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(key, "A Key is required and should match that configured for the RunAsManagerImpl"); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { RunAsUserToken token = (RunAsUserToken) authentication; if (token.getKeyHash() == key.hashCode()) { return authentication; } else { throw new BadCredentialsException(messages.getMessage("RunAsImplAuthenticationProvider.incorrectKey", "The presented RunAsUserToken does not contain the expected key")); } } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } public boolean supports(Class authentication) { if (RunAsUserToken.class.isAssignableFrom(authentication)) { return true; } else { return false; } } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/runas/RunAsManagerImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/runas/RunAsMana0000644000000000000000000001302711623517156030464 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.runas; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthorityImpl; import org.springframework.security.RunAsManager; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.util.Iterator; import java.util.List; import java.util.Vector; /** * Basic concrete implementation of a {@link RunAsManager}.

    Is activated if any {@link * ConfigAttribute#getAttribute()} is prefixed with RUN_AS_. If found, it generates a new {@link * RunAsUserToken} containing the same principal, credentials and granted authorities as the original {@link * Authentication} object, along with {@link GrantedAuthorityImpl}s for each RUN_AS_ indicated. The * created GrantedAuthorityImpls will be prefixed with a special prefix indicating that it is a role * (default prefix value is ROLE_), and then the remainder of the RUN_AS_ keyword. For * example, RUN_AS_FOO will result in the creation of a granted authority of * ROLE_RUN_AS_FOO.

    *

    The role prefix may be overriden from the default, to match that used elsewhere, for example when using an * existing role database with another prefix. An empty role prefix may also be specified. Note however that there are * potential issues with using an empty role prefix since different categories of {@link * org.springframework.security.ConfigAttribute} can not be properly discerned based on the prefix, with possible consequences * when performing voting and other actions. However, this option may be of some use when using preexisting role names * without a prefix, and no ability exists to prefix them with a role prefix on reading them in, such as provided for * example in {@link org.springframework.security.userdetails.jdbc.JdbcDaoImpl}.

    * * @author Ben Alex * @author colin sampaleanu * @version $Id$ */ public class RunAsManagerImpl implements RunAsManager, InitializingBean { //~ Instance fields ================================================================================================ private String key; private String rolePrefix = "ROLE_"; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(key, "A Key is required and should match that configured for the RunAsImplAuthenticationProvider"); } public Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config) { List newAuthorities = new Vector(); Iterator iter = config.getConfigAttributes().iterator(); while (iter.hasNext()) { ConfigAttribute attribute = (ConfigAttribute) iter.next(); if (this.supports(attribute)) { GrantedAuthorityImpl extraAuthority = new GrantedAuthorityImpl(getRolePrefix() + attribute.getAttribute()); newAuthorities.add(extraAuthority); } } if (newAuthorities.size() == 0) { return null; } else { for (int i = 0; i < authentication.getAuthorities().length; i++) { newAuthorities.add(authentication.getAuthorities()[i]); } GrantedAuthority[] resultType = {new GrantedAuthorityImpl("holder")}; GrantedAuthority[] newAuthoritiesAsArray = (GrantedAuthority[]) newAuthorities.toArray(resultType); return new RunAsUserToken(this.key, authentication.getPrincipal(), authentication.getCredentials(), newAuthoritiesAsArray, authentication.getClass()); } } public String getKey() { return key; } public String getRolePrefix() { return rolePrefix; } public void setKey(String key) { this.key = key; } /** * Allows the default role prefix of ROLE_ to be overriden. May be set to an empty value, * although this is usually not desireable. * * @param rolePrefix the new prefix */ public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith("RUN_AS_")) { return true; } else { return false; } } /** * This implementation supports any type of class, because it does not query the presented secure object. * * @param clazz the secure object * * @return alwaus true */ public boolean supports(Class clazz) { return true; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/runas/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/runas/package.h0000644000000000000000000000015111623517156030452 0ustar Allows secure objects to be run under a different authentication identity. ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/runas/NullRunAsManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/runas/NullRunAs0000644000000000000000000000306311623517156030521 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.runas; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.RunAsManager; /** * Implementation of a {@link RunAsManager} that does nothing.

    This class should be used if you do not require * run-as authenticaiton replacement functionality.

    * * @author Ben Alex * @version $Id$ */ public class NullRunAsManager implements RunAsManager { //~ Methods ======================================================================================================== public Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config) { return null; } public boolean supports(ConfigAttribute attribute) { return false; } public boolean supports(Class clazz) { return true; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AccessDeniedException.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/AccessDeniedExc0000644000000000000000000000272311623517156030462 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; /** * Thrown if an {@link Authentication} object does not hold a required authority. * * @author Ben Alex * @version $Id$ */ public class AccessDeniedException extends SpringSecurityException { //~ Constructors =================================================================================================== /** * Constructs an AccessDeniedException with the specified * message. * * @param msg the detail message */ public AccessDeniedException(String msg) { super(msg); } /** * Constructs an AccessDeniedException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public AccessDeniedException(String msg, Throwable t) { super(msg, t); } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/0000755000000000000000000000000011623517156026320 5ustar ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/AclProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/AclProvider0000644000000000000000000000545011623517156030461 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl; import org.springframework.security.Authentication; /** * Indicates a class can process a given domain object instance and * authoritatively return the ACLs that apply. * *

    * Implementations are typically called from the {@link AclProviderManager}. *

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public interface AclProvider { //~ Methods ======================================================================================================== /** * Obtains the ACLs that apply to the specified domain instance.

    Will never be called unless the {@link * #supports(Object)} method returned true.

    * * @param domainInstance the instance for which ACL information is required (never null) * * @return the ACLs that apply, or null if no ACLs apply to the specified domain instance */ AclEntry[] getAcls(Object domainInstance); /** * Obtains the ACLs that apply to the specified domain instance and presented Authentication * object.

    Will never be called unless the {@link #supports(Object)} method returned true.

    * * @param domainInstance the instance for which ACL information is required (never null) * @param authentication the prncipal for which ACL information should be filtered (never null) * * @return only those ACLs applying to the domain instance that have been granted to the principal (or * null) if no such ACLs are found */ AclEntry[] getAcls(Object domainInstance, Authentication authentication); /** * Indicates whether this AclProvider can authoritatively return ACL information for the * specified domain object instance. * * @param domainInstance the instance for which ACL information is required (never null) * * @return true if this provider is authoritative for the specified domain object instance, * false otherwise */ boolean supports(Object domainInstance); } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/AclManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/AclManager.0000644000000000000000000000410411623517156030312 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl; import org.springframework.security.Authentication; /** * Obtains the AclEntry instances that apply to a particular * domain object instance. * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public interface AclManager { //~ Methods ======================================================================================================== /** * Obtains the ACLs that apply to the specified domain instance. * * @param domainInstance the instance for which ACL information is required (never null) * * @return the ACLs that apply, or null if no ACLs apply to the specified domain instance */ AclEntry[] getAcls(Object domainInstance); /** * Obtains the ACLs that apply to the specified domain instance, but only including those ACLs which have * been granted to the presented Authentication object * * @param domainInstance the instance for which ACL information is required (never null) * @param authentication the prncipal for which ACL information should be filtered (never null) * * @return only those ACLs applying to the domain instance that have been granted to the principal (or * null) if no such ACLs are found */ AclEntry[] getAcls(Object domainInstance, Authentication authentication); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/package.htm0000644000000000000000000000074211623517156030430 0ustar Enables retrieval of access control lists (ACLs) for domain object instances.

    The goal of this package is to locate the AclEntrys that apply to a given domain object instance.

    An AclManager has ultimate resposibility for obtaining the AclEntrys instances, with a provider-based implementation available via the AclProviderManager class (and its AclProvider interface.

    ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/AclEntry.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/AclEntry.ja0000644000000000000000000000171011623517156030354 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl; import java.io.Serializable; /** * Marker interface representing an access control list entry associated with a * specific domain object instance. * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public interface AclEntry extends Serializable {} ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/AclProviderManager.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/AclProvider0000644000000000000000000001104511623517156030456 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl; import org.springframework.security.Authentication; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.util.Iterator; import java.util.List; /** * Iterates through a list of {@link AclProvider}s to locate the ACLs that apply to a given domain object instance.

    If * no compatible provider is found, it is assumed that no ACLs apply for the specified domain object instance and * null is returned.

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public class AclProviderManager implements AclManager, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AclProviderManager.class); //~ Instance fields ================================================================================================ private List providers; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { checkIfValidList(this.providers); } private void checkIfValidList(List listToCheck) { Assert.notEmpty(listToCheck, "A list of AclManagers is required"); } public AclEntry[] getAcls(Object domainInstance) { Assert.notNull(domainInstance, "domainInstance is null - violating interface contract"); Iterator iter = providers.iterator(); while (iter.hasNext()) { AclProvider provider = (AclProvider) iter.next(); if (provider.supports(domainInstance)) { if (logger.isDebugEnabled()) { logger.debug("ACL lookup using " + provider.getClass().getName()); } return provider.getAcls(domainInstance); } } if (logger.isDebugEnabled()) { logger.debug("No AclProvider found for " + domainInstance.toString()); } return null; } public AclEntry[] getAcls(Object domainInstance, Authentication authentication) { Assert.notNull(domainInstance, "domainInstance is null - violating interface contract"); Assert.notNull(authentication, "authentication is null - violating interface contract"); Iterator iter = providers.iterator(); while (iter.hasNext()) { AclProvider provider = (AclProvider) iter.next(); if (provider.supports(domainInstance)) { if (logger.isDebugEnabled()) { logger.debug("ACL lookup using " + provider.getClass().getName()); } return provider.getAcls(domainInstance, authentication); } else { if (logger.isDebugEnabled()) { logger.debug("Provider " + provider.toString() + " does not support " + domainInstance); } } } if (logger.isDebugEnabled()) { logger.debug("No AclProvider found for " + domainInstance.toString()); } return null; } public List getProviders() { return this.providers; } /** * Sets the {@link AclProvider} objects to be used for ACL determinations. * * @param newList that should be used for ACL determinations * * @throws IllegalArgumentException if an invalid provider was included in the list */ public void setProviders(List newList) { checkIfValidList(newList); Iterator iter = newList.iterator(); while (iter.hasNext()) { Object currentObject = iter.next(); Assert.isInstanceOf(AclProvider.class, currentObject, "Invalid Acl Provider. "); } this.providers = newList; } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/0000755000000000000000000000000011623517156027401 5ustar ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/BasicAclEntryCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/Basic0000644000000000000000000000477211623517156030357 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic; /** * Provides a cache of {@link BasicAclEntry} objects. * *

    * Implementations should provide appropriate methods to set their cache * parameters (eg time-to-live) and/or force removal of entities before their * normal expiration. These are not part of the * BasicAclEntryCache interface contract because they vary * depending on the type of caching system used (eg in-memory vs disk vs * cluster vs hybrid). *

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public interface BasicAclEntryCache { //~ Methods ======================================================================================================== /** * Obtains an array of {@link BasicAclEntry}s from the cache. * * @param aclObjectIdentity which should be obtained from the cache * * @return any applicable BasicAclEntrys (no nulls are permitted in the returned array) * or null if the object identity could not be found or if the cache entry has expired */ BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity); /** * Places an array of {@link BasicAclEntry}s in the cache.

    No nulls are allowed in the * passed array. If any null is passed, the implementation may throw an exception.

    * * @param basicAclEntry the ACL entries to cache (the key will be extracted from the {@link * BasicAclEntry#getAclObjectIdentity()} method */ void putEntriesInCache(BasicAclEntry[] basicAclEntry); /** * Removes all ACL entries related to an {@link AclObjectIdentity} from the cache. * * @param aclObjectIdentity which should be removed from the cache */ void removeEntriesFromCache(AclObjectIdentity aclObjectIdentity); } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/GrantedAuthorityEffectiveAclsResolver.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/Grant0000644000000000000000000001365311623517156030407 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; import org.springframework.security.acl.AclEntry; import org.springframework.security.userdetails.UserDetails; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.List; import java.util.Vector; /** * Simple implementation of {@link EffectiveAclsResolver}.

    This implementation does not need to understand the * "recipient" types presented in a BasicAclEntry because it merely delegates to the detected {@link * Authentication#getPrincipal()} or {@link Authentication#getAuthorities()}. The principal object or granted * authorities object has its Object.equals(recipient) method called to make the decision as to whether * the recipient in the BasicAclEntry is the same as the principal or granted authority.

    *

    This class should prove an adequate ACLs resolver if you're using standard Spring Security classes. This is * because the typical Authentication token is UsernamePasswordAuthenticationToken, which * for its principal is usually a String. The GrantedAuthorityImpl is typically * used for granted authorities, which tests for equality based on a String. This means * BasicAclDaos simply need to return a String to represent the recipient. If you use * non-String objects, you will probably require an alternative EffectiveAclsResolver.

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public class GrantedAuthorityEffectiveAclsResolver implements EffectiveAclsResolver { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(GrantedAuthorityEffectiveAclsResolver.class); //~ Methods ======================================================================================================== public AclEntry[] resolveEffectiveAcls(AclEntry[] allAcls, Authentication filteredBy) { if ((allAcls == null) || (allAcls.length == 0)) { return null; } List list = new Vector(); if (logger.isDebugEnabled()) { logger.debug("Locating AclEntry[]s (from set of " + ((allAcls == null) ? 0 : allAcls.length) + ") that apply to Authentication: " + filteredBy); } for (int i = 0; i < allAcls.length; i++) { if (!(allAcls[i] instanceof BasicAclEntry)) { continue; } Object recipient = ((BasicAclEntry) allAcls[i]).getRecipient(); // Allow the Authentication's getPrincipal to decide whether // the presented recipient is "equal" (allows BasicAclDaos to // return Strings rather than proper objects in simple cases) if (filteredBy.getPrincipal().equals(recipient)) { if (logger.isDebugEnabled()) { logger.debug("Principal matches AclEntry recipient: " + recipient); } list.add(allAcls[i]); } else if (filteredBy.getPrincipal() instanceof UserDetails && ((UserDetails) filteredBy.getPrincipal()).getUsername().equals(recipient)) { if (logger.isDebugEnabled()) { logger.debug("Principal (from UserDetails) matches AclEntry recipient: " + recipient); } list.add(allAcls[i]); } else { // No direct match against principal; try each authority. // As with the principal, allow each of the Authentication's // granted authorities to decide whether the presented // recipient is "equal" GrantedAuthority[] authorities = filteredBy.getAuthorities(); if ((authorities == null) || (authorities.length == 0)) { if (logger.isDebugEnabled()) { logger.debug("Did not match principal and there are no granted authorities, " + "so cannot compare with recipient: " + recipient); } continue; } for (int k = 0; k < authorities.length; k++) { if (authorities[k].equals(recipient)) { if (logger.isDebugEnabled()) { logger.debug("GrantedAuthority: " + authorities[k] + " matches recipient: " + recipient); } list.add(allAcls[i]); } } } } // return null if appropriate (as per interface contract) if (list.size() > 0) { if (logger.isDebugEnabled()) { logger.debug("Returning effective AclEntry array with " + list.size() + " elements"); } return (BasicAclEntry[]) list.toArray(new BasicAclEntry[] {}); } else { if (logger.isDebugEnabled()) { logger.debug("Returning null AclEntry array as zero effective AclEntrys found"); } return null; } } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/NamedEntityObjectIdentity.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/Named0000644000000000000000000001217311623517156030354 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Simple implementation of {@link AclObjectIdentity}.

    Uses Strings to store the identity of the * domain object instance. Also offers a constructor that uses reflection to build the identity information.

    * @deprecated Use new spring-security-acl module instead */ public class NamedEntityObjectIdentity implements AclObjectIdentity { //~ Instance fields ================================================================================================ private String classname; private String id; //~ Constructors =================================================================================================== public NamedEntityObjectIdentity(String classname, String id) { Assert.hasText(classname, "classname required"); Assert.hasText(id, "id required"); this.classname = classname; this.id = id; } /** * Creates the NamedEntityObjectIdentity based on the passed * object instance. The passed object must provide a getId() * method, otherwise an exception will be thrown. * * @param object the domain object instance to create an identity for * * @throws IllegalAccessException * @throws InvocationTargetException * @throws IllegalArgumentException */ public NamedEntityObjectIdentity(Object object) throws IllegalAccessException, InvocationTargetException { Assert.notNull(object, "object cannot be null"); this.classname = (getPackageName(object.getClass().getName()) == null) ? ClassUtils.getShortName(object.getClass()) : (getPackageName(object.getClass().getName()) + "." + ClassUtils.getShortName(object.getClass())); Class clazz = object.getClass(); try { Method method = clazz.getMethod("getId", new Class[] {}); Object result = method.invoke(object, new Object[] {}); this.id = result.toString(); } catch (NoSuchMethodException nsme) { throw new IllegalArgumentException("Object of class '" + clazz + "' does not provide the required getId() method: " + object); } } //~ Methods ======================================================================================================== /** * Important so caching operates properly.

    Considers an object of the same class equal if it has the same * classname and id properties.

    * * @param arg0 object to compare * * @return true if the presented object matches this object */ public boolean equals(Object arg0) { if (arg0 == null) { return false; } if (!(arg0 instanceof NamedEntityObjectIdentity)) { return false; } NamedEntityObjectIdentity other = (NamedEntityObjectIdentity) arg0; if (this.getId().equals(other.getId()) && this.getClassname().equals(other.getClassname())) { return true; } return false; } /** * Indicates the classname portion of the object identity. * * @return the classname (never null) */ public String getClassname() { return classname; } /** * Indicates the instance identity portion of the object identity. * * @return the instance identity (never null) */ public String getId() { return id; } private String getPackageName(String className) { Assert.hasLength(className, "class name must not be empty"); int lastDotIndex = className.lastIndexOf("."); if (lastDotIndex == -1) { return null; } return className.substring(0, lastDotIndex); } /** * Important so caching operates properly. * * @return the hash of the classname and id */ public int hashCode() { StringBuffer sb = new StringBuffer(); sb.append(this.classname).append(this.id); return sb.toString().hashCode(); } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(this.getClass().getName()).append("["); sb.append("Classname: ").append(this.classname); sb.append("; Identity: ").append(this.id).append("]"); return sb.toString(); } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/EffectiveAclsResolver.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/Effec0000644000000000000000000000511311623517156030334 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic; import org.springframework.security.Authentication; import org.springframework.security.acl.AclEntry; /** * Determines the ACLs that are effective for a given * Authentication object. * *

    * Implementations will vary depending on their ability to interpret the * "recipient" object types contained in {@link BasicAclEntry} instances, and * how those recipient object types correspond to * Authentication-presented principals and granted authorities. *

    * *

    * Implementations should not filter the resulting ACL list from lower-order * permissions. So if a resulting ACL list grants a "read" permission, an * "unlimited" permission and a "zero" permission (due to the effective ACLs * for different granted authorities held by the Authentication * object), all three permissions would be returned as distinct * BasicAclEntry instances. It is the responsibility of the * relying classes (voters and business methods) to ignore or handle * lower-order permissions in a business logic dependent manner. *

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public interface EffectiveAclsResolver { //~ Methods ======================================================================================================== /** * Determines the ACLs that apply to the presented Authentication object. * * @param allAcls every ACL assigned to a domain object instance * @param filteredBy the principal (populated with GrantedAuthoritys along with any other members that * relate to role or group membership) that effective ACLs should be returned for * * @return the ACLs that apply to the presented principal, or null if there are none after filtering */ AclEntry[] resolveEffectiveAcls(AclEntry[] allAcls, Authentication filteredBy); } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/BasicAclProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/Basic0000644000000000000000000003373411623517156030357 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic; import org.springframework.security.Authentication; import org.springframework.security.acl.AclEntry; import org.springframework.security.acl.AclProvider; import org.springframework.security.acl.basic.cache.NullAclEntryCache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.lang.reflect.Constructor; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * Retrieves access control lists (ACL) entries for domain object instances from a data access object (DAO). *

    * This implementation will provide ACL lookup services for any object that it can determine the {@link * AclObjectIdentity} for by calling the {@link #obtainIdentity(Object)} method. Subclasses can override this method * if they only want the BasicAclProvider responding to particular domain object instances. *

    *

    * BasicAclProvider will walk an inheritance hierarchy if a BasicAclEntry returned by * the DAO indicates it has a parent. NB: inheritance occurs at a domain instance object level. It does not * occur at an ACL recipient level. This means allBasicAclEntrys for a given domain instance * object must have the same parent identity, or allBasicAclEntrys must have * null as their parent identity. *

    *

    * A cache should be used. This is provided by the {@link BasicAclEntryCache}. BasicAclProvider by * default is setup to use the {@link NullAclEntryCache}, which performs no caching. *

    *

    To implement the {@link #getAcls(Object, Authentication)} method, BasicAclProvider requires a * {@link EffectiveAclsResolver} to be configured against it. By default the {@link * GrantedAuthorityEffectiveAclsResolver} is used.

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public class BasicAclProvider implements AclProvider, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(BasicAclProvider.class); /** Marker added to the cache to indicate an AclObjectIdentity has no corresponding BasicAclEntry[]s */ private static final String RECIPIENT_FOR_CACHE_EMPTY = "RESERVED_RECIPIENT_NOBODY"; //~ Instance fields ================================================================================================ /** Must be set to an appropriate data access object. Defaults to null. */ private BasicAclDao basicAclDao; private BasicAclEntryCache basicAclEntryCache = new NullAclEntryCache(); private Class defaultAclObjectIdentityClass = NamedEntityObjectIdentity.class; private Class restrictSupportToClass = null; private EffectiveAclsResolver effectiveAclsResolver = new GrantedAuthorityEffectiveAclsResolver(); //~ Methods ======================================================================================================== public void afterPropertiesSet() { Assert.notNull(basicAclDao, "basicAclDao required"); Assert.notNull(basicAclEntryCache, "basicAclEntryCache required"); Assert.notNull(basicAclEntryCache, "basicAclEntryCache required"); Assert.notNull(effectiveAclsResolver, "effectiveAclsResolver required"); Assert.notNull(defaultAclObjectIdentityClass, "defaultAclObjectIdentityClass required"); Assert.isTrue(AclObjectIdentity.class.isAssignableFrom(this.defaultAclObjectIdentityClass), "defaultAclObjectIdentityClass must implement AclObjectIdentity"); try { Constructor constructor = defaultAclObjectIdentityClass.getConstructor(new Class[] {Object.class}); } catch (NoSuchMethodException nsme) { throw new IllegalArgumentException( "defaultAclObjectIdentityClass must provide a constructor that accepts the domain object instance!"); } } public AclEntry[] getAcls(Object domainInstance) { Map map = new HashMap(); AclObjectIdentity aclIdentity = obtainIdentity(domainInstance); Assert.notNull(aclIdentity, "domainInstance is not supported by this provider"); if (logger.isDebugEnabled()) { logger.debug("Looking up: " + aclIdentity.toString()); } BasicAclEntry[] instanceAclEntries = lookup(aclIdentity); // Exit if there is no ACL information or parent for this instance if (instanceAclEntries == null) { return null; } // Add the leaf objects to the Map, keyed on recipient for (int i = 0; i < instanceAclEntries.length; i++) { if (logger.isDebugEnabled()) { logger.debug("Explicit add: " + instanceAclEntries[i].toString()); } map.put(instanceAclEntries[i].getRecipient(), instanceAclEntries[i]); } AclObjectIdentity parent = instanceAclEntries[0].getAclObjectParentIdentity(); while (parent != null) { BasicAclEntry[] parentAclEntries = lookup(parent); if (logger.isDebugEnabled()) { logger.debug("Parent lookup: " + parent.toString()); } // Exit loop if parent couldn't be found (unexpected condition) if (parentAclEntries == null) { if (logger.isDebugEnabled()) { logger.debug("Parent could not be found in ACL repository"); } break; } // Now add each _NEW_ recipient to the list for (int i = 0; i < parentAclEntries.length; i++) { if (!map.containsKey(parentAclEntries[i].getRecipient())) { if (logger.isDebugEnabled()) { logger.debug("Added parent to map: " + parentAclEntries[i].toString()); } map.put(parentAclEntries[i].getRecipient(), parentAclEntries[i]); } else { if (logger.isDebugEnabled()) { logger.debug("Did NOT add parent to map: " + parentAclEntries[i].toString()); } } } // Prepare for next iteration of while loop parent = parentAclEntries[0].getAclObjectParentIdentity(); } Collection collection = map.values(); return (AclEntry[]) collection.toArray(new AclEntry[] {}); } public AclEntry[] getAcls(Object domainInstance, Authentication authentication) { AclEntry[] allAcls = (AclEntry[]) this.getAcls(domainInstance); return this.effectiveAclsResolver.resolveEffectiveAcls(allAcls, authentication); } public BasicAclDao getBasicAclDao() { return basicAclDao; } public BasicAclEntryCache getBasicAclEntryCache() { return basicAclEntryCache; } public Class getDefaultAclObjectIdentityClass() { return defaultAclObjectIdentityClass; } public EffectiveAclsResolver getEffectiveAclsResolver() { return effectiveAclsResolver; } public Class getRestrictSupportToClass() { return restrictSupportToClass; } private BasicAclEntry[] lookup(AclObjectIdentity aclObjectIdentity) { BasicAclEntry[] result = basicAclEntryCache.getEntriesFromCache(aclObjectIdentity); if (result != null) { if (result[0].getRecipient().equals(RECIPIENT_FOR_CACHE_EMPTY)) { return null; } else { return result; } } result = basicAclDao.getAcls(aclObjectIdentity); if (result == null) { SimpleAclEntry[] emptyAclEntries = { new SimpleAclEntry(RECIPIENT_FOR_CACHE_EMPTY, aclObjectIdentity, null, 0) }; basicAclEntryCache.putEntriesInCache(emptyAclEntries); return null; } basicAclEntryCache.putEntriesInCache(result); return result; } /** * This method looks up the AclObjectIdentity of a passed domain object instance.

    This * implementation attempts to obtain the AclObjectIdentity via reflection inspection of the class for * the {@link AclObjectIdentityAware} interface. If this fails, an attempt is made to construct a {@link * #getDefaultAclObjectIdentityClass()} object by passing the domain instance object into its constructor.

    * * @param domainInstance the domain object instance (never null) * * @return an ACL object identity, or null if one could not be obtained */ protected AclObjectIdentity obtainIdentity(Object domainInstance) { if (domainInstance instanceof AclObjectIdentityAware) { AclObjectIdentityAware aclObjectIdentityAware = (AclObjectIdentityAware) domainInstance; if (logger.isDebugEnabled()) { logger.debug("domainInstance: " + domainInstance + " cast to AclObjectIdentityAware"); } return aclObjectIdentityAware.getAclObjectIdentity(); } try { Constructor constructor = defaultAclObjectIdentityClass.getConstructor(new Class[] {Object.class}); if (logger.isDebugEnabled()) { logger.debug("domainInstance: " + domainInstance + " attempting to pass to constructor: " + constructor); } return (AclObjectIdentity) constructor.newInstance(new Object[] {domainInstance}); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error attempting construction of " + defaultAclObjectIdentityClass + ": " + ex.getMessage(), ex); if (ex.getCause() != null) { logger.debug("Cause: " + ex.getCause().getMessage(), ex.getCause()); } } return null; } } public void setBasicAclDao(BasicAclDao basicAclDao) { this.basicAclDao = basicAclDao; } public void setBasicAclEntryCache(BasicAclEntryCache basicAclEntryCache) { this.basicAclEntryCache = basicAclEntryCache; } /** * Allows selection of the AclObjectIdentity class that an attempt should be made to construct * if the passed object does not implement AclObjectIdentityAware.

    NB: Any * defaultAclObjectIdentityClassmust provide a public constructor that accepts an * Object. Otherwise it is not possible for the BasicAclProvider to try to create the * AclObjectIdentity instance at runtime.

    * * @param defaultAclObjectIdentityClass */ public void setDefaultAclObjectIdentityClass(Class defaultAclObjectIdentityClass) { this.defaultAclObjectIdentityClass = defaultAclObjectIdentityClass; } public void setEffectiveAclsResolver(EffectiveAclsResolver effectiveAclsResolver) { this.effectiveAclsResolver = effectiveAclsResolver; } /** * If set to a value other than null, the {@link #supports(Object)} method will only * support the indicates class. This is useful if you wish to wire multiple BasicAclProviders in a * list of AclProviderManager.providers but only have particular instances respond to particular * domain object types. * * @param restrictSupportToClass the class to restrict this BasicAclProvider to service request for, * or null (the default) if the BasicAclProvider should respond to every class * presented */ public void setRestrictSupportToClass(Class restrictSupportToClass) { this.restrictSupportToClass = restrictSupportToClass; } /** * Indicates support for the passed object.

    An object will only be supported if it (i) is allowed to be * supported as defined by the {@link #setRestrictSupportToClass(Class)} method, and (ii) if an * AclObjectIdentity is returned by {@link #obtainIdentity(Object)} for that object.

    * * @param domainInstance the instance to check * * @return true if this provider supports the passed object, false otherwise */ public boolean supports(Object domainInstance) { if (domainInstance == null) { if (logger.isDebugEnabled()) { logger.debug("domainInstance is null"); } return false; } if ((restrictSupportToClass != null) && !restrictSupportToClass.isAssignableFrom(domainInstance.getClass())) { if (logger.isDebugEnabled()) { logger.debug("domainInstance not instance of " + restrictSupportToClass); } return false; } if (obtainIdentity(domainInstance) == null) { if (logger.isDebugEnabled()) { logger.debug("obtainIdentity returned null"); } return false; } else { if (logger.isDebugEnabled()) { logger.debug("obtainIdentity returned " + obtainIdentity(domainInstance)); } return true; } } } spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/0000755000000000000000000000000011623517156030303 5ustar ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/JdbcExtendedDaoImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/0000644000000000000000000004572511623517156030322 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic.jdbc; import org.springframework.security.acl.basic.AclObjectIdentity; import org.springframework.security.acl.basic.BasicAclEntry; import org.springframework.security.acl.basic.BasicAclEntryCache; import org.springframework.security.acl.basic.BasicAclExtendedDao; import org.springframework.security.acl.basic.cache.NullAclEntryCache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContextException; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.object.MappingSqlQuery; import org.springframework.jdbc.object.SqlUpdate; import org.springframework.util.Assert; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Iterator; import java.util.List; import javax.sql.DataSource; /** *

    Extension of the base {@link JdbcDaoImpl}, which implements {@link BasicAclExtendedDao}.

    *

    A default database structure is assumed. This may be overridden by setting the default query strings to use.

    *

    If you are using a cache with BasicAclProvider, you should specify that cache via {@link * #setBasicAclEntryCache(BasicAclEntryCache)}. This will cause cache evictions (removals) to take place whenever a * DAO mutator method is called.

    *

    This implementation works with String based recipients and {@link * org.springframework.security.acl.basic.NamedEntityObjectIdentity} only. The latter can be changed by overriding {@link * #convertAclObjectIdentityToString(AclObjectIdentity)}.

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public class JdbcExtendedDaoImpl extends JdbcDaoImpl implements BasicAclExtendedDao { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(JdbcExtendedDaoImpl.class); public static final String DEF_ACL_OBJECT_IDENTITY_DELETE_STATEMENT = "DELETE FROM acl_object_identity WHERE id = ?"; public static final String DEF_ACL_OBJECT_IDENTITY_INSERT_STATEMENT = "INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES (?, ?, ?)"; public static final String DEF_ACL_PERMISSION_DELETE_STATEMENT = "DELETE FROM acl_permission WHERE acl_object_identity = ? AND recipient = ?"; public static final String DEF_ACL_PERMISSION_INSERT_STATEMENT = "INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (?, ?, ?)"; public static final String DEF_ACL_PERMISSION_UPDATE_STATEMENT = "UPDATE acl_permission SET mask = ? WHERE id = ?"; public static final String DEF_LOOKUP_PERMISSION_ID_QUERY = "SELECT id FROM acl_permission WHERE acl_object_identity = ? AND recipient = ?"; //~ Instance fields ================================================================================================ private AclObjectIdentityDelete aclObjectIdentityDelete; private AclObjectIdentityInsert aclObjectIdentityInsert; private AclPermissionDelete aclPermissionDelete; private AclPermissionInsert aclPermissionInsert; private AclPermissionUpdate aclPermissionUpdate; private BasicAclEntryCache basicAclEntryCache = new NullAclEntryCache(); private MappingSqlQuery lookupPermissionIdMapping; private String aclObjectIdentityDeleteStatement; private String aclObjectIdentityInsertStatement; private String aclPermissionDeleteStatement; private String aclPermissionInsertStatement; private String aclPermissionUpdateStatement; private String lookupPermissionIdQuery; //~ Constructors =================================================================================================== public JdbcExtendedDaoImpl() { aclObjectIdentityDeleteStatement = DEF_ACL_OBJECT_IDENTITY_DELETE_STATEMENT; aclObjectIdentityInsertStatement = DEF_ACL_OBJECT_IDENTITY_INSERT_STATEMENT; aclPermissionDeleteStatement = DEF_ACL_PERMISSION_DELETE_STATEMENT; aclPermissionInsertStatement = DEF_ACL_PERMISSION_INSERT_STATEMENT; aclPermissionUpdateStatement = DEF_ACL_PERMISSION_UPDATE_STATEMENT; lookupPermissionIdQuery = DEF_LOOKUP_PERMISSION_ID_QUERY; } //~ Methods ======================================================================================================== public void changeMask(AclObjectIdentity aclObjectIdentity, Object recipient, Integer newMask) throws DataAccessException { basicAclEntryCache.removeEntriesFromCache(aclObjectIdentity); // Retrieve acl_object_identity record details AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(aclObjectIdentity); // Retrieve applicable acl_permission.id long permissionId = lookupPermissionId(aclDetailsHolder.getForeignKeyId(), recipient.toString()); if (permissionId == -1) { throw new DataRetrievalFailureException("Could not locate existing acl_permission for aclObjectIdentity: " + aclObjectIdentity + ", recipient: " + recipient.toString()); } // Change permission aclPermissionUpdate.update(new Long(permissionId), newMask); } public void create(BasicAclEntry basicAclEntry) throws DataAccessException { // Create acl_object_identity record if required createAclObjectIdentityIfRequired(basicAclEntry); // Only continue if a recipient is specifed (null recipient indicates // just wanted to ensure the acl_object_identity was created) if (basicAclEntry.getRecipient() == null) { return; } // Retrieve acl_object_identity record details AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(basicAclEntry.getAclObjectIdentity()); // Ensure there isn't an existing record for this recipient long permissionId = lookupPermissionId(aclDetailsHolder.getForeignKeyId(), basicAclEntry.getRecipient()); if (permissionId != -1) { throw new DataIntegrityViolationException("Recipient '" + basicAclEntry.getRecipient() + "' already exists for aclObjectIdentity ID " + aclDetailsHolder.getForeignKeyId() + " (permission ID " + ")"); } // Create acl_permission aclPermissionInsert.insert(new Long(aclDetailsHolder.getForeignKeyId()), basicAclEntry.getRecipient().toString(), new Integer(basicAclEntry.getMask())); } /** * Convenience method that creates an acl_object_identity record if required. * * @param basicAclEntry containing the AclObjectIdentity to create * * @throws DataAccessException */ private void createAclObjectIdentityIfRequired(BasicAclEntry basicAclEntry) throws DataAccessException { basicAclEntryCache.removeEntriesFromCache(basicAclEntry.getAclObjectIdentity()); String aclObjectIdentityString = convertAclObjectIdentityToString(basicAclEntry.getAclObjectIdentity()); // Lookup the object's main properties from the RDBMS (guaranteed no nulls) List objects = objectProperties.execute(aclObjectIdentityString); if (objects.size() == 0) { if (basicAclEntry.getAclObjectParentIdentity() != null) { AclDetailsHolder parentDetails = lookupAclDetailsHolder(basicAclEntry.getAclObjectParentIdentity()); // Must create the acl_object_identity record aclObjectIdentityInsert.insert(aclObjectIdentityString, new Long(parentDetails.getForeignKeyId()), basicAclEntry.getClass().getName()); } else { // Must create the acl_object_identity record aclObjectIdentityInsert.insert(aclObjectIdentityString, null, basicAclEntry.getClass().getName()); } } } public void delete(AclObjectIdentity aclObjectIdentity) throws DataAccessException { basicAclEntryCache.removeEntriesFromCache(aclObjectIdentity); // Retrieve acl_object_identity record details AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(aclObjectIdentity); // Retrieve all acl_permissions applying to this acl_object_identity Iterator acls = aclsByObjectIdentity.execute(aclDetailsHolder.getForeignKeyId()).iterator(); // Delete all existing acl_permissions applying to this acl_object_identity while (acls.hasNext()) { AclDetailsHolder permission = (AclDetailsHolder) acls.next(); delete(aclObjectIdentity, permission.getRecipient()); } // Delete acl_object_identity aclObjectIdentityDelete.delete(new Long(aclDetailsHolder.getForeignKeyId())); } public void delete(AclObjectIdentity aclObjectIdentity, Object recipient) throws DataAccessException { basicAclEntryCache.removeEntriesFromCache(aclObjectIdentity); // Retrieve acl_object_identity record details AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(aclObjectIdentity); // Delete acl_permission aclPermissionDelete.delete(new Long(aclDetailsHolder.getForeignKeyId()), recipient.toString()); } public AclObjectIdentityDelete getAclObjectIdentityDelete() { return aclObjectIdentityDelete; } public String getAclObjectIdentityDeleteStatement() { return aclObjectIdentityDeleteStatement; } public AclObjectIdentityInsert getAclObjectIdentityInsert() { return aclObjectIdentityInsert; } public String getAclObjectIdentityInsertStatement() { return aclObjectIdentityInsertStatement; } public AclPermissionDelete getAclPermissionDelete() { return aclPermissionDelete; } public String getAclPermissionDeleteStatement() { return aclPermissionDeleteStatement; } public AclPermissionInsert getAclPermissionInsert() { return aclPermissionInsert; } public String getAclPermissionInsertStatement() { return aclPermissionInsertStatement; } public AclPermissionUpdate getAclPermissionUpdate() { return aclPermissionUpdate; } public String getAclPermissionUpdateStatement() { return aclPermissionUpdateStatement; } public BasicAclEntryCache getBasicAclEntryCache() { return basicAclEntryCache; } public MappingSqlQuery getLookupPermissionIdMapping() { return lookupPermissionIdMapping; } public String getLookupPermissionIdQuery() { return lookupPermissionIdQuery; } protected void initDao() throws ApplicationContextException { super.initDao(); lookupPermissionIdMapping = new LookupPermissionIdMapping(getDataSource()); aclPermissionInsert = new AclPermissionInsert(getDataSource()); aclObjectIdentityInsert = new AclObjectIdentityInsert(getDataSource()); aclPermissionDelete = new AclPermissionDelete(getDataSource()); aclObjectIdentityDelete = new AclObjectIdentityDelete(getDataSource()); aclPermissionUpdate = new AclPermissionUpdate(getDataSource()); } /** * Convenience method that obtains a given acl_object_identity record. * * @param aclObjectIdentity to lookup * * @return details of the record * * @throws DataRetrievalFailureException if record could not be found */ private AclDetailsHolder lookupAclDetailsHolder(AclObjectIdentity aclObjectIdentity) throws DataRetrievalFailureException { String aclObjectIdentityString = convertAclObjectIdentityToString(aclObjectIdentity); // Lookup the object's main properties from the RDBMS (guaranteed no nulls) List objects = objectProperties.execute(aclObjectIdentityString); if (objects.size() == 0) { throw new DataRetrievalFailureException("aclObjectIdentity not found: " + aclObjectIdentityString); } // Should only be one record return (AclDetailsHolder) objects.get(0); } /** * Convenience method to lookup the acl_permission applying to a given acl_object_identity.id and * acl_permission.recipient. * * @param aclObjectIdentityId to locate * @param recipient to locate * * @return the acl_permission.id of the record, or -1 if not found * * @throws DataAccessException DOCUMENT ME! */ private long lookupPermissionId(long aclObjectIdentityId, Object recipient) throws DataAccessException { List list = lookupPermissionIdMapping.execute(new Object[] {new Long(aclObjectIdentityId), recipient}); if (list.size() == 0) { return -1; } return ((Long) list.get(0)).longValue(); } public void setAclObjectIdentityDelete(AclObjectIdentityDelete aclObjectIdentityDelete) { this.aclObjectIdentityDelete = aclObjectIdentityDelete; } public void setAclObjectIdentityDeleteStatement(String aclObjectIdentityDeleteStatement) { this.aclObjectIdentityDeleteStatement = aclObjectIdentityDeleteStatement; } public void setAclObjectIdentityInsert(AclObjectIdentityInsert aclObjectIdentityInsert) { this.aclObjectIdentityInsert = aclObjectIdentityInsert; } public void setAclObjectIdentityInsertStatement(String aclObjectIdentityInsertStatement) { this.aclObjectIdentityInsertStatement = aclObjectIdentityInsertStatement; } public void setAclPermissionDelete(AclPermissionDelete aclPermissionDelete) { this.aclPermissionDelete = aclPermissionDelete; } public void setAclPermissionDeleteStatement(String aclPermissionDeleteStatement) { this.aclPermissionDeleteStatement = aclPermissionDeleteStatement; } public void setAclPermissionInsert(AclPermissionInsert aclPermissionInsert) { this.aclPermissionInsert = aclPermissionInsert; } public void setAclPermissionInsertStatement(String aclPermissionInsertStatement) { this.aclPermissionInsertStatement = aclPermissionInsertStatement; } public void setAclPermissionUpdate(AclPermissionUpdate aclPermissionUpdate) { this.aclPermissionUpdate = aclPermissionUpdate; } public void setAclPermissionUpdateStatement(String aclPermissionUpdateStatement) { this.aclPermissionUpdateStatement = aclPermissionUpdateStatement; } public void setBasicAclEntryCache(BasicAclEntryCache basicAclEntryCache) { Assert.notNull(basicAclEntryCache, "Cache cannot be set to null"); this.basicAclEntryCache = basicAclEntryCache; } public void setLookupPermissionIdMapping(MappingSqlQuery lookupPermissionIdMapping) { this.lookupPermissionIdMapping = lookupPermissionIdMapping; } public void setLookupPermissionIdQuery(String lookupPermissionIdQuery) { this.lookupPermissionIdQuery = lookupPermissionIdQuery; } //~ Inner Classes ================================================================================================== protected class AclObjectIdentityDelete extends SqlUpdate { protected AclObjectIdentityDelete(DataSource ds) { super(ds, aclObjectIdentityDeleteStatement); declareParameter(new SqlParameter(Types.BIGINT)); compile(); } protected void delete(Long aclObjectIdentity) throws DataAccessException { super.update(aclObjectIdentity.intValue()); } } protected class AclObjectIdentityInsert extends SqlUpdate { protected AclObjectIdentityInsert(DataSource ds) { super(ds, aclObjectIdentityInsertStatement); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected void insert(String objectIdentity, Long parentAclObjectIdentity, String aclClass) throws DataAccessException { Object[] objs = new Object[] {objectIdentity, parentAclObjectIdentity, aclClass}; super.update(objs); } } protected class AclPermissionDelete extends SqlUpdate { protected AclPermissionDelete(DataSource ds) { super(ds, aclPermissionDeleteStatement); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected void delete(Long aclObjectIdentity, String recipient) throws DataAccessException { super.update(new Object[] {aclObjectIdentity, recipient}); } } protected class AclPermissionInsert extends SqlUpdate { protected AclPermissionInsert(DataSource ds) { super(ds, aclPermissionInsertStatement); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.INTEGER)); compile(); } protected void insert(Long aclObjectIdentity, String recipient, Integer mask) throws DataAccessException { Object[] objs = new Object[] {aclObjectIdentity, recipient, mask}; super.update(objs); } } protected class AclPermissionUpdate extends SqlUpdate { protected AclPermissionUpdate(DataSource ds) { super(ds, aclPermissionUpdateStatement); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.INTEGER)); compile(); } protected void update(Long aclPermissionId, Integer newMask) throws DataAccessException { super.update(newMask.intValue(), aclPermissionId.intValue()); } } protected class LookupPermissionIdMapping extends MappingSqlQuery { protected LookupPermissionIdMapping(DataSource ds) { super(ds, lookupPermissionIdQuery); declareParameter(new SqlParameter(Types.BIGINT)); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { return new Long(rs.getLong(1)); } } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/acegi-acl-mysql.sqlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/0000644000000000000000000000431611623517156030311 0ustar CREATE TABLE acl_object_identity ( id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, object_identity VARCHAR(250) NOT NULL, parent_object INTEGER, acl_class VARCHAR(250) NOT NULL, CONSTRAINT unique_object_identity UNIQUE(object_identity), FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id) ON DELETE CASCADE ); CREATE TABLE acl_permission ( id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, acl_object_identity INTEGER NOT NULL, recipient VARCHAR(100) NOT NULL, mask INTEGER NOT NULL, CONSTRAINT unique_recipient UNIQUE(acl_object_identity, recipient), FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id) ON DELETE CASCADE ); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:1', null, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:2', 1, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:3', 1, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:4', 1, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:5', 3, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:6', 3, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (1, 'ROLE_ADMIN', 1); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'ROLE_ADMIN', 0); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'rod', 2); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (3, 'scott', 14); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (6, 'scott', 1); ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/acegi-acl-postgres.sqlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/0000644000000000000000000000462311623517156030312 0ustar CREATE SEQUENCE acl_object_identity_seq; CREATE TABLE acl_object_identity ( id INTEGER NOT NULL DEFAULT nextval('acl_object_identity_seq') CONSTRAINT acl_object_identity_PK PRIMARY KEY, object_identity VARCHAR(250) NOT NULL, parent_object INTEGER, acl_class VARCHAR(250) NOT NULL, CONSTRAINT unique_object_identity UNIQUE(object_identity), FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id) ON DELETE CASCADE ); CREATE SEQUENCE acl_permission_seq; CREATE TABLE acl_permission ( id INTEGER NOT NULL DEFAULT nextval('acl_permission_seq') CONSTRAINT acl_permission_PK PRIMARY KEY, acl_object_identity INTEGER NOT NULL, recipient VARCHAR(100) NOT NULL, mask INTEGER NOT NULL, CONSTRAINT unique_recipient UNIQUE(acl_object_identity, recipient), FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id) ON DELETE CASCADE ); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:1', null, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:2', 1, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:3', 1, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:4', 1, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:5', 3, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:6', 3, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (1, 'ROLE_ADMIN', 1); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'ROLE_ADMIN', 0); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'rod', 2); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (3, 'scott', 14); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (6, 'scott', 1); ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/0000644000000000000000000000012111623517156030277 0ustar JDBC-based data access object for ACL information. ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/JdbcDaoImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/0000644000000000000000000004154011623517156030311 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic.jdbc; import org.springframework.security.acl.basic.AclObjectIdentity; import org.springframework.security.acl.basic.BasicAclDao; import org.springframework.security.acl.basic.BasicAclEntry; import org.springframework.security.acl.basic.NamedEntityObjectIdentity; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContextException; import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.jdbc.object.MappingSqlQuery; import org.springframework.util.Assert; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.List; import java.util.Vector; import javax.sql.DataSource; /** * Retrieves ACL details from a JDBC location. *

    * A default database structure is assumed. This may be overridden by setting the default query strings to use. * If this does not provide enough flexibility, another strategy would be to subclass this class and override the * {@link MappingSqlQuery} instance used, via the {@link #initMappingSqlQueries()} extension point. *

    * @deprecated Use new spring-security-acl module instead */ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao { //~ Static fields/initializers ===================================================================================== public static final String RECIPIENT_USED_FOR_INHERITENCE_MARKER = "___INHERITENCE_MARKER_ONLY___"; public static final String DEF_ACLS_BY_OBJECT_IDENTITY_QUERY = "SELECT RECIPIENT, MASK FROM acl_permission WHERE acl_object_identity = ?"; public static final String DEF_OBJECT_PROPERTIES_QUERY = "SELECT CHILD.ID, " + "CHILD.OBJECT_IDENTITY, " + "CHILD.ACL_CLASS, " + "PARENT.OBJECT_IDENTITY as PARENT_OBJECT_IDENTITY " + "FROM acl_object_identity as CHILD " + "LEFT OUTER JOIN acl_object_identity as PARENT ON CHILD.parent_object=PARENT.id " + "WHERE CHILD.object_identity = ?"; private static final Log logger = LogFactory.getLog(JdbcDaoImpl.class); //~ Instance fields ================================================================================================ protected MappingSqlQuery aclsByObjectIdentity; protected MappingSqlQuery objectProperties; private String aclsByObjectIdentityQuery; private String objectPropertiesQuery; //~ Constructors =================================================================================================== public JdbcDaoImpl() { aclsByObjectIdentityQuery = DEF_ACLS_BY_OBJECT_IDENTITY_QUERY; objectPropertiesQuery = DEF_OBJECT_PROPERTIES_QUERY; } //~ Methods ======================================================================================================== /** * Responsible for covering a AclObjectIdentity to a String that can be located * in the RDBMS. * * @param aclObjectIdentity to locate * * @return the object identity as a String */ protected String convertAclObjectIdentityToString(AclObjectIdentity aclObjectIdentity) { // Ensure we can process this type of AclObjectIdentity Assert.isInstanceOf(NamedEntityObjectIdentity.class, aclObjectIdentity, "Only aclObjectIdentity of type NamedEntityObjectIdentity supported (was passed: " + aclObjectIdentity + ")"); NamedEntityObjectIdentity neoi = (NamedEntityObjectIdentity) aclObjectIdentity; // Compose the String we expect to find in the RDBMS return neoi.getClassname() + ":" + neoi.getId(); } /** * Constructs an individual BasicAclEntry from the passed AclDetailsHolders.

    Guarantees * to never return null (exceptions are thrown in the event of any issues).

    * * @param propertiesInformation mandatory information about which instance to create, the object identity, and the * parent object identity (null or empty Strings prohibited for * aclClass and aclObjectIdentity * @param aclInformation optional information about the individual ACL record (if null only an * "inheritence marker" instance is returned which will include a recipient of {@link * #RECIPIENT_USED_FOR_INHERITENCE_MARKER} ; if not null, it is prohibited to present * null or an empty String for recipient) * * @return a fully populated instance suitable for use by external objects * * @throws IllegalArgumentException if the indicated ACL class could not be created */ private BasicAclEntry createBasicAclEntry(AclDetailsHolder propertiesInformation, AclDetailsHolder aclInformation) { BasicAclEntry entry; try { entry = (BasicAclEntry) propertiesInformation.getAclClass().newInstance(); } catch (InstantiationException ie) { throw new IllegalArgumentException(ie.getMessage()); } catch (IllegalAccessException iae) { throw new IllegalArgumentException(iae.getMessage()); } entry.setAclObjectIdentity(propertiesInformation.getAclObjectIdentity()); entry.setAclObjectParentIdentity(propertiesInformation.getAclObjectParentIdentity()); if (aclInformation == null) { // this is an inheritence marker instance only entry.setMask(0); entry.setRecipient(RECIPIENT_USED_FOR_INHERITENCE_MARKER); } else { // this is an individual ACL entry entry.setMask(aclInformation.getMask()); entry.setRecipient(aclInformation.getRecipient()); } return entry; } /** * Returns the ACLs associated with the requested AclObjectIdentity.

    The {@link * BasicAclEntry}s returned by this method will have String-based recipients. This will not be a * problem if you are using the GrantedAuthorityEffectiveAclsResolver, which is the default * configured against BasicAclProvider.

    *

    This method will only return ACLs for requests where the AclObjectIdentity is of type * {@link NamedEntityObjectIdentity}. Of course, you can subclass or replace this class and support your own * custom AclObjectIdentity types.

    * * @param aclObjectIdentity for which ACL information is required (cannot be null and must be an * instance of NamedEntityObjectIdentity) * * @return the ACLs that apply (without any nulls inside the array), or null if not found * or if an incompatible AclObjectIdentity was requested */ public BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity) { String aclObjectIdentityString; try { aclObjectIdentityString = convertAclObjectIdentityToString(aclObjectIdentity); } catch (IllegalArgumentException unsupported) { return null; // pursuant to contract described in JavaDocs above } // Lookup the object's main properties from the RDBMS (guaranteed no nulls) List objects = objectProperties.execute(aclObjectIdentityString); if (objects.size() == 0) { // this is an unknown object identity string return null; } // Cast to an object properties holder (there should only be one record) AclDetailsHolder propertiesInformation = (AclDetailsHolder) objects.get(0); // Lookup the object's ACLs from RDBMS (guaranteed no nulls) List acls = aclsByObjectIdentity.execute(propertiesInformation.getForeignKeyId()); if (acls.size() == 0) { // return merely an inheritence marker (as we know about the object but it has no related ACLs) return new BasicAclEntry[] {createBasicAclEntry(propertiesInformation, null)}; } else { // return the individual ACL instances AclDetailsHolder[] aclHolders = (AclDetailsHolder[]) acls.toArray(new AclDetailsHolder[] {}); List toReturnAcls = new Vector(); for (int i = 0; i < aclHolders.length; i++) { toReturnAcls.add(createBasicAclEntry(propertiesInformation, aclHolders[i])); } return (BasicAclEntry[]) toReturnAcls.toArray(new BasicAclEntry[] {}); } } public MappingSqlQuery getAclsByObjectIdentity() { return aclsByObjectIdentity; } public String getAclsByObjectIdentityQuery() { return aclsByObjectIdentityQuery; } public String getObjectPropertiesQuery() { return objectPropertiesQuery; } protected void initDao() throws ApplicationContextException { initMappingSqlQueries(); } /** * Extension point to allow other MappingSqlQuery objects to be substituted in a subclass */ protected void initMappingSqlQueries() { setAclsByObjectIdentity(new AclsByObjectIdentityMapping(getDataSource())); setObjectProperties(new ObjectPropertiesMapping(getDataSource())); } public void setAclsByObjectIdentity(MappingSqlQuery aclsByObjectIdentityQuery) { this.aclsByObjectIdentity = aclsByObjectIdentityQuery; } /** * Allows the default query string used to retrieve ACLs based on object identity to be overriden, if * default table or column names need to be changed. The default query is {@link * #DEF_ACLS_BY_OBJECT_IDENTITY_QUERY}; when modifying this query, ensure that all returned columns are mapped * back to the same column names as in the default query. * * @param queryString The query string to set */ public void setAclsByObjectIdentityQuery(String queryString) { aclsByObjectIdentityQuery = queryString; } public void setObjectProperties(MappingSqlQuery objectPropertiesQuery) { this.objectProperties = objectPropertiesQuery; } public void setObjectPropertiesQuery(String queryString) { objectPropertiesQuery = queryString; } //~ Inner Classes ================================================================================================== /** * Used to hold details of a domain object instance's properties, or an individual ACL entry.

    Not all * properties will be set. The actual properties set will depend on which MappingSqlQuery creates the * object.

    *

    Does not enforce nulls or empty Strings as this is performed by the * MappingSqlQuery objects (or preferably the backend RDBMS via schema constraints).

    */ protected final class AclDetailsHolder { private AclObjectIdentity aclObjectIdentity; private AclObjectIdentity aclObjectParentIdentity; private Class aclClass; private Object recipient; private int mask; private long foreignKeyId; /** * Record details of an individual ACL entry (usually from the * ACL_PERMISSION table) * * @param recipient the recipient * @param mask the integer to be masked */ public AclDetailsHolder(Object recipient, int mask) { this.recipient = recipient; this.mask = mask; } /** * Record details of a domain object instance's properties (usually * from the ACL_OBJECT_IDENTITY table) * * @param foreignKeyId used by the * AclsByObjectIdentityMapping to locate the * individual ACL entries * @param aclObjectIdentity the object identity of the domain object * instance * @param aclObjectParentIdentity the object identity of the domain * object instance's parent * @param aclClass the class of which a new instance which should be * created for each individual ACL entry (or an inheritence * "holder" class if there are no ACL entries) */ public AclDetailsHolder(long foreignKeyId, AclObjectIdentity aclObjectIdentity, AclObjectIdentity aclObjectParentIdentity, Class aclClass) { this.foreignKeyId = foreignKeyId; this.aclObjectIdentity = aclObjectIdentity; this.aclObjectParentIdentity = aclObjectParentIdentity; this.aclClass = aclClass; } public Class getAclClass() { return aclClass; } public AclObjectIdentity getAclObjectIdentity() { return aclObjectIdentity; } public AclObjectIdentity getAclObjectParentIdentity() { return aclObjectParentIdentity; } public long getForeignKeyId() { return foreignKeyId; } public int getMask() { return mask; } public Object getRecipient() { return recipient; } } /** * Query object to look up individual ACL entries.

    Returns the generic AclDetailsHolder * object.

    *

    Guarantees to never return null (exceptions are thrown in the event of any issues).

    *

    The executed SQL requires the following information be made available from the indicated * placeholders: 1. RECIPIENT, 2. MASK.

    */ protected class AclsByObjectIdentityMapping extends MappingSqlQuery { protected AclsByObjectIdentityMapping(DataSource ds) { super(ds, aclsByObjectIdentityQuery); declareParameter(new SqlParameter(Types.BIGINT)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { String recipient = rs.getString(1); int mask = rs.getInt(2); Assert.hasText(recipient, "recipient required"); return new AclDetailsHolder(recipient, mask); } } /** * Query object to look up properties for an object identity.

    Returns the generic * AclDetailsHolder object.

    *

    Guarantees to never return null (exceptions are thrown in the event of any issues).

    *

    The executed SQL requires the following information be made available from the indicated * placeholders: 1. ID, 2. OBJECT_IDENTITY, 3. ACL_CLASS and 4. PARENT_OBJECT_IDENTITY.

    */ protected class ObjectPropertiesMapping extends MappingSqlQuery { protected ObjectPropertiesMapping(DataSource ds) { super(ds, objectPropertiesQuery); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } private AclObjectIdentity buildIdentity(String identity) { if (identity == null) { // Must be an empty parent, so return null return null; } int delim = identity.lastIndexOf(":"); String classname = identity.substring(0, delim); String id = identity.substring(delim + 1); return new NamedEntityObjectIdentity(classname, id); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { long id = rs.getLong(1); // required String objectIdentity = rs.getString(2); // required String aclClass = rs.getString(3); // required String parentObjectIdentity = rs.getString(4); // optional Assert.hasText(objectIdentity, "required DEF_OBJECT_PROPERTIES_QUERY value (objectIdentity) returned null or empty"); Assert.hasText(aclClass, "required DEF_OBJECT_PROPERTIES_QUERY value (aclClass) returned null or empty"); Class aclClazz; try { aclClazz = this.getClass().getClassLoader().loadClass(aclClass); } catch (ClassNotFoundException cnf) { throw new IllegalArgumentException(cnf.getMessage()); } return new AclDetailsHolder(id, buildIdentity(objectIdentity), buildIdentity(parentObjectIdentity), aclClazz); } } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/acegi-acl-hsql.sqlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/0000644000000000000000000000431011623517156030303 0ustar CREATE TABLE acl_object_identity ( id INTEGER GENERATED BY DEFAULT AS IDENTITY, object_identity VARCHAR(250) NOT NULL, parent_object INTEGER, acl_class VARCHAR(250) NOT NULL, CONSTRAINT unique_object_identity UNIQUE(object_identity), FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id) ON DELETE CASCADE ); CREATE TABLE acl_permission ( id INTEGER GENERATED BY DEFAULT AS IDENTITY, acl_object_identity INTEGER NOT NULL, recipient VARCHAR(100) NOT NULL, mask INTEGER NOT NULL, CONSTRAINT unique_recipient UNIQUE(acl_object_identity, recipient), FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id) ON DELETE CASCADE ); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:1', null, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:2', 1, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:3', 1, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:4', 1, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:5', 3, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:6', 3, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (1, 'ROLE_ADMIN', 1); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'ROLE_ADMIN', 0); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'rod', 2); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (3, 'scott', 14); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (6, 'scott', 1); ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/acegi-acl-derby.sqlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/jdbc/0000644000000000000000000000447611623517156030320 0ustar CREATE SCHEMA sa; CREATE TABLE acl_object_identity ( id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY CONSTRAINT acl_object_identity_PK PRIMARY KEY, object_identity VARCHAR(250) NOT NULL, parent_object INTEGER, acl_class VARCHAR(250) NOT NULL, CONSTRAINT unique_object_identity UNIQUE(object_identity), FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id) ON DELETE CASCADE ); CREATE TABLE acl_permission ( id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY CONSTRAINT acl_permission_PK PRIMARY KEY, acl_object_identity INTEGER NOT NULL, recipient VARCHAR(100) NOT NULL, mask INTEGER NOT NULL, CONSTRAINT unique_recipient UNIQUE(acl_object_identity, recipient), FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id) ON DELETE CASCADE ); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:1', null, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:2', 1, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:3', 1, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:4', 1, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:5', 3, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_object_identity (object_identity, parent_object, acl_class) VALUES ('org.mydomain.MyClass:6', 3, 'org.springframework.security.acl.basic.SimpleAclEntry'); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (1, 'ROLE_ADMIN', 1); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'ROLE_ADMIN', 0); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (2, 'rod', 2); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (3, 'scott', 14); --INSERT INTO acl_permission (acl_object_identity, recipient, mask) VALUES (6, 'scott', 1); ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/packa0000644000000000000000000000013511623517156030402 0ustar Access control list implementation based on integer bit masks. ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/BasicAclDao.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/Basic0000644000000000000000000000431211623517156030345 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic; /** * Represents a data access object that can return the {@link BasicAclEntry}s * applying to a given ACL object identity. * *

    * BasicAclDao implementations are responsible for interpreting a * given {@link AclObjectIdentity} and being able to lookup and return the * corresponding {@link BasicAclEntry}[]s. *

    * *

    * BasicAclDaos many, but are not required to, allow the backend * ACL repository to specify the class of BasicAclEntry * implementations that should be returned. *

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public interface BasicAclDao { //~ Methods ======================================================================================================== /** * Obtains the ACLs that apply to the specified domain instance.

    Does not perform caching, include * ACLs from any inheritance hierarchy or filter returned objects based on effective permissions. Implementations * are solely responsible for returning ACLs found in the ACL repository for the specified object identity.

    * * @param aclObjectIdentity the domain object instance that ACL information is being requested for (never * null) * * @return the ACLs that apply (no nulls are permitted in the array), or null if no ACLs * could be found for the specified ACL object identity */ BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity); } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/SimpleAclEntry.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/Simpl0000644000000000000000000001256411623517156030420 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Stores some privileges typical of a domain object. * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public class SimpleAclEntry extends AbstractBasicAclEntry { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(SimpleAclEntry.class); // Base permissions we permit public static final int NOTHING = 0; public static final int ADMINISTRATION = (int) Math.pow(2, 0); public static final int READ = (int) Math.pow(2, 1); public static final int WRITE = (int) Math.pow(2, 2); public static final int CREATE = (int) Math.pow(2, 3); public static final int DELETE = (int) Math.pow(2, 4); // Combinations of base permissions we permit public static final int READ_WRITE_CREATE_DELETE = READ | WRITE | CREATE | DELETE; public static final int READ_WRITE_CREATE = READ | WRITE | CREATE; public static final int READ_WRITE = READ | WRITE; public static final int READ_WRITE_DELETE = READ | WRITE | DELETE; // Array required by the abstract superclass via getValidPermissions() private static final int[] VALID_PERMISSIONS = { NOTHING, ADMINISTRATION, READ, WRITE, CREATE, DELETE, READ_WRITE_CREATE_DELETE, READ_WRITE_CREATE, READ_WRITE, READ_WRITE_DELETE }; private static final String[] VALID_PERMISSIONS_AS_STRING = { "NOTHING", "ADMINISTRATION", "READ", "WRITE", "CREATE", "DELETE", "READ_WRITE_CREATE_DELETE", "READ_WRITE_CREATE", "READ_WRITE", "READ_WRITE_DELETE" }; //~ Constructors =================================================================================================== /** * Allows {@link BasicAclDao} implementations to construct this object * using newInstance(). * *

    * Normal classes should not use this default constructor. *

    */ public SimpleAclEntry() { super(); } public SimpleAclEntry(Object recipient, AclObjectIdentity aclObjectIdentity, AclObjectIdentity aclObjectParentIdentity, int mask) { super(recipient, aclObjectIdentity, aclObjectParentIdentity, mask); } //~ Methods ======================================================================================================== /** * @return a copy of the permissions array, changes to the values won't affect this class. */ public int[] getValidPermissions() { return (int[]) VALID_PERMISSIONS.clone(); } public String printPermissionsBlock(int i) { StringBuffer sb = new StringBuffer(); if (isPermitted(i, ADMINISTRATION)) { sb.append('A'); } else { sb.append('-'); } if (isPermitted(i, READ)) { sb.append('R'); } else { sb.append('-'); } if (isPermitted(i, WRITE)) { sb.append('W'); } else { sb.append('-'); } if (isPermitted(i, CREATE)) { sb.append('C'); } else { sb.append('-'); } if (isPermitted(i, DELETE)) { sb.append('D'); } else { sb.append('-'); } return sb.toString(); } /** * Parse a permission {@link String} literal and return associated value. * * @param permission one of the field names that represent a permission: ADMINISTRATION, * READ, WRITE,... * @return the value associated to that permission * @throws IllegalArgumentException if argument is not a valid permission */ public static int parsePermission(String permission) { for (int i = 0; i < VALID_PERMISSIONS_AS_STRING.length; i++) { if (VALID_PERMISSIONS_AS_STRING[i].equalsIgnoreCase(permission)) { return VALID_PERMISSIONS[i]; } } throw new IllegalArgumentException("Permission provided does not exist: " + permission); } /** * Parse a list of permission {@link String} literals and return associated values. * * @param permissions array with permissions as {@link String} * @see #parsePermission(String) for valid values */ public static int[] parsePermissions(String[] permissions) { int[] requirepermissionAsIntArray = new int[permissions.length]; for (int i = 0; i < requirepermissionAsIntArray.length; i++) { requirepermissionAsIntArray[i] = parsePermission(permissions[i]); } return requirepermissionAsIntArray; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/BasicAclExtendedDao.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/Basic0000644000000000000000000000515311623517156030351 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic; import org.springframework.dao.DataAccessException; /** * Represents a more extensive data access object * for {@link BasicAclEntry}s. * *

    * BasicAclExtendedDao implementations are responsible for interpreting a * a given {@link AclObjectIdentity}. *

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public interface BasicAclExtendedDao extends BasicAclDao { //~ Methods ======================================================================================================== /** * Changes the permission mask assigned to the BasicAclEntry associated with the specified * AclObjectIdentity and recipient Object. * * @param aclObjectIdentity to locate the relevant BasicAclEntry * @param recipient to locate the relevant BasicAclEntry * @param newMask indicating the new permission * * @throws DataAccessException DOCUMENT ME! */ void changeMask(AclObjectIdentity aclObjectIdentity, Object recipient, Integer newMask) throws DataAccessException; void create(BasicAclEntry basicAclEntry) throws DataAccessException; /** * Deletes all entries associated with the specified AclObjectIdentity. * * @param aclObjectIdentity to delete, including any BasicAclEntrys * * @throws DataAccessException DOCUMENT ME! */ void delete(AclObjectIdentity aclObjectIdentity) throws DataAccessException; /** * Deletes the BasicAclEntry associated with the specified AclObjectIdentity and * recipient Object. * * @param aclObjectIdentity to delete * @param recipient to delete * * @throws DataAccessException DOCUMENT ME! */ void delete(AclObjectIdentity aclObjectIdentity, Object recipient) throws DataAccessException; } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/BasicAclEntry.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/Basic0000644000000000000000000001211711623517156030347 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic; import org.springframework.security.acl.AclEntry; /** * Represents an entry in an access control list. * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public interface BasicAclEntry extends AclEntry { //~ Methods ======================================================================================================== /** * Indicates the domain object instance that is subject of this BasicAclEntry. This * information may be of interest to relying classes (voters and business methods) that wish to know the actual * origination of the ACL entry (so as to distinguish individual ACL entries from others contributed by the * inheritance hierarchy). * * @return the ACL object identity that is subject of this ACL entry (never null) */ AclObjectIdentity getAclObjectIdentity(); /** * Indicates any ACL parent of the domain object instance. This is used by BasicAclProvider to * walk the inheritance hierarchy. An domain object instance need not have a parent. * * @return the ACL object identity that is the parent of this ACL entry (may be null if no parent * should be consulted) */ AclObjectIdentity getAclObjectParentIdentity(); /** * Access control lists in this package are based on bit masking. The integer value of the bit mask can be * obtained from this method. * * @return the bit mask applicable to this ACL entry (zero indicates a bit mask where no permissions have been * granted) */ int getMask(); /** * A domain object instance will usually have multiple BasicAclEntrys. Each separate * BasicAclEntry applies to a particular "recipient". Typical examples of recipients include (but do * not necessarily have to include) usernames, role names, complex granted authorities etc.

    It is * essential that only one BasicAclEntry exists for a given recipient. Otherwise conflicts as to * the mask that should apply to a given recipient will occur.

    *

    This method indicates which recipient this BasicAclEntry applies to. The returned * object type will vary depending on the type of recipient. For instance, it might be a String * containing a username, or a GrantedAuthorityImpl containing a complex granted authority that is * being granted the permissions contained in this access control entry. The {@link EffectiveAclsResolver} and * {@link BasicAclProvider#getAcls(Object,org.springframework.security.Authentication)} can process the different recipient * types and return only those that apply to a specified Authentication object.

    * * @return the recipient of this access control list entry (never null) */ Object getRecipient(); /** * Determine if the mask of this entry includes this permission or not * * @param permissionToCheck * * @return if the entry's mask includes this permission */ boolean isPermitted(int permissionToCheck); /** * This setter should only be used by DAO implementations. * * @param aclObjectIdentity an object which can be used to uniquely identify the domain object instance subject of * this ACL entry */ void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity); /** * This setter should only be used by DAO implementations. * * @param aclObjectParentIdentity an object which represents the parent of the domain object instance subject of * this ACL entry, or null if either the domain object instance has no parent or its parent * should be not used to compute an inheritance hierarchy */ void setAclObjectParentIdentity(AclObjectIdentity aclObjectParentIdentity); /** * This setter should only be used by DAO implementations. * * @param mask the integer representing the permissions bit mask */ void setMask(int mask); /** * This setter should only be used by DAO implementations. * * @param recipient a representation of the recipient of this ACL entry that makes sense to an * EffectiveAclsResolver implementation */ void setRecipient(Object recipient); } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/AclObjectIdentity.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/AclOb0000644000000000000000000000456711623517156030320 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic; import java.io.Serializable; /** * Interface representing the identity of an individual domain object instance. * *

    * It should be noted that AclObjectIdentity instances are created * in various locations throughout the package. As * AclObjectIdentitys are used as the key for caching, it is * essential that implementations provide methods so that object-equality * rather than reference-equality can be relied upon by caches. In other * words, a cache can consider two AclObjectIdentitys equal if * identity1.equals(identity2), rather than reference-equality of * identity1==identity2. *

    * *

    * In practical terms this means you must implement the standard * java.lang.Object methods shown below. Depending on your * cache's internal structure, you may also need to implement special * interfaces such as java.util.Comparator or * java.lang.Comparable. *

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public interface AclObjectIdentity extends Serializable { //~ Methods ======================================================================================================== /** * Refer to the java.lang.Object documentation for the interface contract. * * @param obj to be compared * * @return true if the objects are equal, false otherwise */ boolean equals(Object obj); /** * Refer to the java.lang.Object documentation for the interface contract. * * @return a hash code representation of this object */ int hashCode(); } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/AbstractBasicAclEntry.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/Abstr0000644000000000000000000002265411623517156030410 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import java.util.Arrays; /** * Abstract implementation of {@link BasicAclEntry}.

    Provides core bit mask handling methods.

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public abstract class AbstractBasicAclEntry implements BasicAclEntry { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AbstractBasicAclEntry.class); //~ Instance fields ================================================================================================ private AclObjectIdentity aclObjectIdentity; private AclObjectIdentity aclObjectParentIdentity; private Object recipient; private int[] validPermissions; private int mask = 0; // default means no permissions //~ Constructors =================================================================================================== public AbstractBasicAclEntry(Object recipient, AclObjectIdentity aclObjectIdentity, AclObjectIdentity aclObjectParentIdentity, int mask) { Assert.notNull(recipient, "recipient cannot be null"); Assert.notNull(aclObjectIdentity, "aclObjectIdentity cannot be null"); validPermissions = getValidPermissions(); Arrays.sort(validPermissions); for (int i = 0; i < validPermissions.length; i++) { if (logger.isDebugEnabled()) { logger.debug("Valid permission: " + printPermissionsBlock(validPermissions[i]) + " " + printBinary(validPermissions[i]) + " (" + validPermissions[i] + ")"); } } this.recipient = recipient; this.aclObjectIdentity = aclObjectIdentity; this.aclObjectParentIdentity = aclObjectParentIdentity; this.mask = mask; } /** * A protected constructor for use by Hibernate. */ protected AbstractBasicAclEntry() { validPermissions = getValidPermissions(); Arrays.sort(validPermissions); } //~ Methods ======================================================================================================== public int addPermission(int permissionToAdd) { return addPermissions(new int[] {permissionToAdd}); } public int addPermissions(int[] permissionsToAdd) { if (logger.isDebugEnabled()) { logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask + ")"); } for (int i = 0; i < permissionsToAdd.length; i++) { if (logger.isDebugEnabled()) { logger.debug("Add permission: " + printPermissionsBlock(permissionsToAdd[i]) + " " + printBinary(permissionsToAdd[i]) + " (" + permissionsToAdd[i] + ")"); } this.mask |= permissionsToAdd[i]; } if (Arrays.binarySearch(validPermissions, this.mask) < 0) { throw new IllegalArgumentException("Resulting permission set will be invalid."); } else { if (logger.isDebugEnabled()) { logger.debug("AFTER Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask + ")"); } return this.mask; } } public int deletePermission(int permissionToDelete) { return deletePermissions(new int[] {permissionToDelete}); } public int deletePermissions(int[] permissionsToDelete) { if (logger.isDebugEnabled()) { logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask + ")"); } for (int i = 0; i < permissionsToDelete.length; i++) { if (logger.isDebugEnabled()) { logger.debug("Delete permission: " + printPermissionsBlock(permissionsToDelete[i]) + " " + printBinary(permissionsToDelete[i]) + " (" + permissionsToDelete[i] + ")"); } this.mask &= ~permissionsToDelete[i]; } if (Arrays.binarySearch(validPermissions, this.mask) < 0) { throw new IllegalArgumentException("Resulting permission set will be invalid."); } else { if (logger.isDebugEnabled()) { logger.debug("AFTER Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask + ")"); } return this.mask; } } public AclObjectIdentity getAclObjectIdentity() { return this.aclObjectIdentity; } public AclObjectIdentity getAclObjectParentIdentity() { return this.aclObjectParentIdentity; } public int getMask() { return this.mask; } public Object getRecipient() { return this.recipient; } /** * Subclasses must indicate the permissions they support. Each base permission should be an integer with a * base 2. ie: the first permission is 2^^0 (1), the second permission is 2^^1 (2), the third permission is 2^^2 * (4) etc. Each base permission should be exposed by the subclass as a public static final int. It * is further recommended that valid combinations of permissions are also exposed as public static final * ints.

    This method returns all permission integers that are allowed to be used together. This * must include any combinations of valid permissions. So if the permissions indicated by 2^^2 (4) and 2^^1 * (2) can be used together, one of the integers returned by this method must be 6 (4 + 2). Otherwise attempts to * set the permission will be rejected, as the final resulting mask will be rejected.

    *

    Whilst it may seem unduly time onerous to return every valid permission combination, doing so * delivers maximum flexibility in ensuring ACLs only reflect logical combinations. For example, it would be * inappropriate to grant a "read" and "write" permission along with an "unrestricted" permission, as the latter * implies the former permissions.

    * * @return every valid combination of permissions */ public abstract int[] getValidPermissions(); public boolean isPermitted(int permissionToCheck) { return isPermitted(this.mask, permissionToCheck); } protected boolean isPermitted(int maskToCheck, int permissionToCheck) { return ((maskToCheck & permissionToCheck) == permissionToCheck); } private String printBinary(int i) { String s = Integer.toString(i, 2); String pattern = "................................"; String temp1 = pattern.substring(0, pattern.length() - s.length()); String temp2 = temp1 + s; return temp2.replace('0', '.'); } /** * Outputs the permissions in a human-friendly format. For example, this method may return "CR-D" to * indicate the passed integer permits create, permits read, does not permit update, and permits delete. * * @param i the integer containing the mask which should be printed * * @return the human-friend formatted block */ public abstract String printPermissionsBlock(int i); /** * Outputs the permissions in human-friendly format for the current AbstractBasicAclEntry's * mask. * * @return the human-friendly formatted block for this instance */ public String printPermissionsBlock() { return printPermissionsBlock(this.mask); } public void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity) { this.aclObjectIdentity = aclObjectIdentity; } public void setAclObjectParentIdentity(AclObjectIdentity aclObjectParentIdentity) { this.aclObjectParentIdentity = aclObjectParentIdentity; } public void setMask(int mask) { this.mask = mask; } public void setRecipient(Object recipient) { this.recipient = recipient; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(getClass().getName()); sb.append("[").append(aclObjectIdentity).append(",").append(recipient); sb.append("=").append(printPermissionsBlock(mask)).append(" "); sb.append(printBinary(mask)).append(" ("); sb.append(mask).append(")").append("]"); return sb.toString(); } public int togglePermission(int permissionToToggle) { this.mask ^= permissionToToggle; if (Arrays.binarySearch(validPermissions, this.mask) < 0) { throw new IllegalArgumentException("Resulting permission set will be invalid."); } else { return this.mask; } } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/AclObjectIdentityAware.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/AclOb0000644000000000000000000000277511623517156030317 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic; /** * Indicates a domain object instance is able to provide {@link * AclObjectIdentity} information. * *

    * Domain objects must implement this interface if they wish to provide an * AclObjectIdentity rather than it being determined by relying * classes. Specifically, the {@link BasicAclProvider} detects and uses this * interface. *

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public interface AclObjectIdentityAware { //~ Methods ======================================================================================================== /** * Retrieves the AclObjectIdentity for this instance. * * @return the ACL object identity for this instance (can never be null) */ AclObjectIdentity getAclObjectIdentity(); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/cache/spring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/cache0000755000000000000000000000000011623517156030365 5ustar ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/cache/BasicAclEntryHolder.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/cache0000644000000000000000000000514311623517156030372 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic.cache; import org.springframework.security.acl.basic.BasicAclEntry; import org.springframework.util.Assert; import java.io.Serializable; /** * Used by {@link EhCacheBasedAclEntryCache} to store the array of BasicAclEntrys in the cache.

    This * is necessary because caches store a single object per key, not an array.

    *

    This class uses value object semantics. ie: construction-based initialisation without any setters for the * properties.

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public class BasicAclEntryHolder implements Serializable { //~ Instance fields ================================================================================================ private BasicAclEntry[] basicAclEntries; //~ Constructors =================================================================================================== /** * Constructs the BasicAclEntryHolder. * * @param aclEntries to cache (any nulls will cause an * exception, which should not be a problem as the contract for * BasicAclEntryCache allows exceptions if * nulls are presented) * * @throws IllegalArgumentException if a null exists anywhere * in the aclEntries or if a null is * passed to the constructor */ public BasicAclEntryHolder(BasicAclEntry[] aclEntries) { Assert.notNull(aclEntries, "aclEntries cannot be null"); for (int i = 0; i < aclEntries.length; i++) { Assert.notNull(aclEntries[i], "aclEntries cannot be null"); } this.basicAclEntries = aclEntries; } //~ Methods ======================================================================================================== public BasicAclEntry[] getBasicAclEntries() { return basicAclEntries; } } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/cache/EhCacheBasedAclEntryCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/cache0000644000000000000000000000711511623517156030373 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic.cache; import net.sf.ehcache.CacheException; import net.sf.ehcache.Element; import net.sf.ehcache.Ehcache; import org.springframework.security.acl.basic.AclObjectIdentity; import org.springframework.security.acl.basic.BasicAclEntry; import org.springframework.security.acl.basic.BasicAclEntryCache; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.util.Assert; /** * Caches BasicAclEntrys using a Spring IoC defined EHCACHE. * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public class EhCacheBasedAclEntryCache implements BasicAclEntryCache, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(EhCacheBasedAclEntryCache.class); //~ Instance fields ================================================================================================ private Ehcache cache; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "cache mandatory"); } public BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity) { Element element = null; try { element = cache.get(aclObjectIdentity); } catch (CacheException cacheException) { throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage()); } // Return null if cache element has expired or not found if (element == null) { if (logger.isDebugEnabled()) { logger.debug("Cache miss: " + aclObjectIdentity); } return null; } if (logger.isDebugEnabled()) { logger.debug("Cache hit: " + (element != null) + "; object: " + aclObjectIdentity); } BasicAclEntryHolder holder = (BasicAclEntryHolder) element.getValue(); return holder.getBasicAclEntries(); } public void putEntriesInCache(BasicAclEntry[] basicAclEntry) { BasicAclEntryHolder holder = new BasicAclEntryHolder(basicAclEntry); Element element = new Element(basicAclEntry[0].getAclObjectIdentity(), holder); if (logger.isDebugEnabled()) { logger.debug("Cache put: " + element.getKey()); } cache.put(element); } public void removeEntriesFromCache(AclObjectIdentity aclObjectIdentity) { cache.remove(aclObjectIdentity); } public Ehcache getCache() { return cache; } public void setCache(Ehcache cache) { this.cache = cache; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/cache/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/cache0000644000000000000000000000013411623517156030365 0ustar Caches ACL information for the BasicAclProvider. ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/cache/NullAclEntryCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/acl/basic/cache0000644000000000000000000000370611623517156030375 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acl.basic.cache; import org.springframework.security.acl.basic.AclObjectIdentity; import org.springframework.security.acl.basic.BasicAclEntry; import org.springframework.security.acl.basic.BasicAclEntryCache; /** * Does not perform any caching.

    Do not use in production settings, as ACL queries are likely to be * extensive.

    * * @author Ben Alex * @version $Id$ * @deprecated Use new spring-security-acl module instead */ public class NullAclEntryCache implements BasicAclEntryCache { //~ Methods ======================================================================================================== /** * As nothing ever stored in the cache, will always return null. * * @param aclObjectIdentity ignored * * @return always null */ public BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity) { return null; } /** * Meets method signature but doesn't store in any cache. * * @param basicAclEntry ignored */ public void putEntriesInCache(BasicAclEntry[] basicAclEntry) {} /** * Meets method signature but doesn't remove from cache. * * @param aclObjectIdentity ignored */ public void removeEntriesFromCache(AclObjectIdentity aclObjectIdentity) {} } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/GrantedAuthorityImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-core/org/springframework/security/GrantedAuthorit0000644000000000000000000000512011623517156030606 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security; import java.io.Serializable; import org.springframework.util.Assert; /** * Basic concrete implementation of a {@link GrantedAuthority}. * *

    * Stores a String representation of an authority granted to the {@link Authentication} object. *

    * If compared to a custom authority which returns null from {@link #getAuthority}, the compareTo * method will return -1, so the custom authority will take precedence. * * @author Ben Alex * @version $Id$ */ public class GrantedAuthorityImpl implements GrantedAuthority, Serializable { //~ Instance fields ================================================================================================ private static final long serialVersionUID = 1L; private String role; //~ Constructors =================================================================================================== public GrantedAuthorityImpl(String role) { Assert.hasText(role, "A granted authority textual representation is required"); this.role = role; } //~ Methods ======================================================================================================== public boolean equals(Object obj) { if (obj instanceof String) { return obj.equals(this.role); } if (obj instanceof GrantedAuthority) { GrantedAuthority attr = (GrantedAuthority) obj; return this.role.equals(attr.getAuthority()); } return false; } public String getAuthority() { return this.role; } public int hashCode() { return this.role.hashCode(); } public String toString() { return this.role; } public int compareTo(Object o) { if (o != null && o instanceof GrantedAuthority) { String rhsRole = ((GrantedAuthority) o).getAuthority(); if (rhsRole == null) { return -1; } return role.compareTo(rhsRole); } return -1; } } spring-security-2.0.7.RELEASE/dist/spring-security-acl/0000755000000000000000000000000011766764113017517 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-acl/META-INF/0000755000000000000000000000000011623522002020634 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-acl/META-INF/MANIFEST.MF0000644000000000000000000000014311623522000022262 0ustar Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: 20.1-b02-384 (Apple Inc.) spring-security-2.0.7.RELEASE/dist/spring-security-acl/org/0000755000000000000000000000000011623517156020301 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/0000755000000000000000000000000011623517156023521 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/0000755000000000000000000000000011623517156025370 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/vote/0000755000000000000000000000000011623517156026345 5ustar ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/vote/AclEntryVoter.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/vote/AclEntryVot0000644000000000000000000002731511623517156030512 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.vote; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Iterator; import org.springframework.security.Authentication; import org.springframework.security.AuthorizationServiceException; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.acls.Acl; import org.springframework.security.acls.AclService; import org.springframework.security.acls.NotFoundException; import org.springframework.security.acls.Permission; import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategy; import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategyImpl; import org.springframework.security.acls.sid.Sid; import org.springframework.security.acls.sid.SidRetrievalStrategy; import org.springframework.security.acls.sid.SidRetrievalStrategyImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** *

    * Given a domain object instance passed as a method argument, ensures the principal has appropriate permission * as indicated by the {@link AclService}. *

    * The AclService is used to retrieve the access control list (ACL) permissions associated with a * domain object instance for the current Authentication object. *

    * The voter will vote if any {@link ConfigAttribute#getAttribute()} matches the {@link #processConfigAttribute}. * The provider will then locate the first method argument of type {@link #processDomainObjectClass}. Assuming that * method argument is non-null, the provider will then lookup the ACLs from the AclManager and ensure the * principal is {@link Acl#isGranted(org.springframework.security.acls.Permission[], * org.springframework.security.acls.sid.Sid[], boolean)} when presenting the {@link #requirePermission} array to that * method. *

    * If the method argument is null, the voter will abstain from voting. If the method argument * could not be found, an {@link org.springframework.security.AuthorizationServiceException} will be thrown. *

    * In practical terms users will typically setup a number of AclEntryVoters. Each will have a * different {@link #processDomainObjectClass}, {@link #processConfigAttribute} and {@link #requirePermission} * combination. For example, a small application might employ the following instances of AclEntryVoter: *

      *
    • Process domain object class BankAccount, configuration attribute * VOTE_ACL_BANK_ACCONT_READ, require permission BasePermission.READ
    • *
    • Process domain object class BankAccount, configuration attribute * VOTE_ACL_BANK_ACCOUNT_WRITE, require permission list BasePermission.WRITE and * BasePermission.CREATE (allowing the principal to have either of these two permissions)
    • *
    • Process domain object class Customer, configuration attribute * VOTE_ACL_CUSTOMER_READ, require permission BasePermission.READ
    • *
    • Process domain object class Customer, configuration attribute * VOTE_ACL_CUSTOMER_WRITE, require permission list BasePermission.WRITE and * BasePermission.CREATE
    • *
    * Alternatively, you could have used a common superclass or interface for the {@link #processDomainObjectClass} * if both BankAccount and Customer had common parents.

    *

    If the principal does not have sufficient permissions, the voter will vote to deny access.

    *

    All comparisons and prefixes are case sensitive.

    * * @author Ben Alex * @version $Id$ */ public class AclEntryVoter extends AbstractAclVoter { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(AclEntryVoter.class); //~ Instance fields ================================================================================================ private AclService aclService; private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); private String internalMethod; private String processConfigAttribute; private Permission[] requirePermission; //~ Constructors =================================================================================================== public AclEntryVoter(AclService aclService, String processConfigAttribute, Permission[] requirePermission) { Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.notNull(aclService, "An AclService is mandatory"); if ((requirePermission == null) || (requirePermission.length == 0)) { throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); } this.aclService = aclService; this.processConfigAttribute = processConfigAttribute; this.requirePermission = requirePermission; } //~ Methods ======================================================================================================== /** * Optionally specifies a method of the domain object that will be used to obtain a contained domain * object. That contained domain object will be used for the ACL evaluation. This is useful if a domain object * contains a parent that an ACL evaluation should be targeted for, instead of the child domain object (which * perhaps is being created and as such does not yet have any ACL permissions) * * @return null to use the domain object, or the name of a method (that requires no arguments) that * should be invoked to obtain an Object which will be the domain object used for ACL * evaluation */ protected String getInternalMethod() { return internalMethod; } public void setInternalMethod(String internalMethod) { this.internalMethod = internalMethod; } protected String getProcessConfigAttribute() { return processConfigAttribute; } public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required"); this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; } public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); this.sidRetrievalStrategy = sidRetrievalStrategy; } public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) { return true; } else { return false; } } public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { Iterator iter = config.getConfigAttributes().iterator(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (!this.supports(attr)) { continue; } // Need to make an access decision on this invocation // Attempt to locate the domain object instance to process Object domainObject = getDomainObjectInstance(object); // If domain object is null, vote to abstain if (domainObject == null) { if (logger.isDebugEnabled()) { logger.debug("Voting to abstain - domainObject is null"); } return AccessDecisionVoter.ACCESS_ABSTAIN; } // Evaluate if we are required to use an inner domain object if (StringUtils.hasText(internalMethod)) { try { Class clazz = domainObject.getClass(); Method method = clazz.getMethod(internalMethod, new Class[0]); domainObject = method.invoke(domainObject, new Object[0]); } catch (NoSuchMethodException nsme) { throw new AuthorizationServiceException("Object of class '" + domainObject.getClass() + "' does not provide the requested internalMethod: " + internalMethod); } catch (IllegalAccessException iae) { logger.debug("IllegalAccessException", iae); throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod + " for object: " + domainObject); } catch (InvocationTargetException ite) { logger.debug("InvocationTargetException", ite); throw new AuthorizationServiceException("Problem invoking internalMethod: " + internalMethod + " for object: " + domainObject); } } // Obtain the OID applicable to the domain object ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject); // Obtain the SIDs applicable to the principal Sid[] sids = sidRetrievalStrategy.getSids(authentication); Acl acl; try { // Lookup only ACLs for SIDs we're interested in acl = aclService.readAclById(objectIdentity, sids); } catch (NotFoundException nfe) { if (logger.isDebugEnabled()) { logger.debug("Voting to deny access - no ACLs apply for this principal"); } return AccessDecisionVoter.ACCESS_DENIED; } try { if (acl.isGranted(requirePermission, sids, false)) { if (logger.isDebugEnabled()) { logger.debug("Voting to grant access"); } return AccessDecisionVoter.ACCESS_GRANTED; } else { if (logger.isDebugEnabled()) { logger.debug( "Voting to deny access - ACLs returned, but insufficient permissions for this principal"); } return AccessDecisionVoter.ACCESS_DENIED; } } catch (NotFoundException nfe) { if (logger.isDebugEnabled()) { logger.debug("Voting to deny access - no ACLs apply for this principal"); } return AccessDecisionVoter.ACCESS_DENIED; } } // No configuration attribute matched, so abstain return AccessDecisionVoter.ACCESS_ABSTAIN; } } spring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/afterinvocation/0000755000000000000000000000000011623517156030563 5ustar ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/afterinvocation/AbstractAclProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/afterinvocation/0000644000000000000000000001246511623517156030575 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.afterinvocation; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttribute; import org.springframework.security.acls.Acl; import org.springframework.security.acls.AclService; import org.springframework.security.acls.NotFoundException; import org.springframework.security.acls.Permission; import org.springframework.security.acls.domain.BasePermission; import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategy; import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategyImpl; import org.springframework.security.acls.sid.Sid; import org.springframework.security.acls.sid.SidRetrievalStrategy; import org.springframework.security.acls.sid.SidRetrievalStrategyImpl; import org.springframework.util.Assert; /** * Abstract {@link AfterInvocationProvider} which provides commonly-used ACL-related services. * * @author Ben Alex * @version $Id$ */ public abstract class AbstractAclProvider implements AfterInvocationProvider { //~ Instance fields ================================================================================================ protected AclService aclService; protected Class processDomainObjectClass = Object.class; protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); protected String processConfigAttribute; protected Permission[] requirePermission = {BasePermission.READ}; //~ Constructors =================================================================================================== public AbstractAclProvider(AclService aclService, String processConfigAttribute, Permission[] requirePermission) { Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.notNull(aclService, "An AclService is mandatory"); if ((requirePermission == null) || (requirePermission.length == 0)) { throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); } this.aclService = aclService; this.processConfigAttribute = processConfigAttribute; this.requirePermission = requirePermission; } //~ Methods ======================================================================================================== protected Class getProcessDomainObjectClass() { return processDomainObjectClass; } protected boolean hasPermission(Authentication authentication, Object domainObject) { // Obtain the OID applicable to the domain object ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject); // Obtain the SIDs applicable to the principal Sid[] sids = sidRetrievalStrategy.getSids(authentication); Acl acl = null; try { // Lookup only ACLs for SIDs we're interested in acl = aclService.readAclById(objectIdentity, sids); return acl.isGranted(requirePermission, sids, false); } catch (NotFoundException ignore) { return false; } } public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required"); this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; } protected void setProcessConfigAttribute(String processConfigAttribute) { Assert.hasText(processConfigAttribute, "A processConfigAttribute is mandatory"); this.processConfigAttribute = processConfigAttribute; } public void setProcessDomainObjectClass(Class processDomainObjectClass) { Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null"); this.processDomainObjectClass = processDomainObjectClass; } public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); this.sidRetrievalStrategy = sidRetrievalStrategy; } public boolean supports(ConfigAttribute attribute) { return processConfigAttribute.equals(attribute.getAttribute()); } /** * This implementation supports any type of class, because it does not query the presented secure object. * * @param clazz the secure object * * @return always true */ public boolean supports(Class clazz) { return true; } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/afterinvocation/AclEntryAfterInvocationProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/afterinvocation/0000644000000000000000000001263411623517156030573 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.afterinvocation; import org.springframework.security.AccessDeniedException; import org.springframework.security.SpringSecurityMessageSource; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.acls.AclService; import org.springframework.security.acls.Permission; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import java.util.Iterator; /** * Given a domain object instance returned from a secure object invocation, ensures the principal has * appropriate permission as defined by the {@link AclService}. *

    * The AclService is used to retrieve the access control list (ACL) permissions associated with a * domain object instance for the current Authentication object. *

    * This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link * #processConfigAttribute}. The provider will then lookup the ACLs from the AclService and ensure the * principal is {@link org.springframework.security.acls.Acl#isGranted(org.springframework.security.acls.Permission[], org.springframework.security.acls.sid.Sid[], boolean) Acl.isGranted(Permission[], Sid[], boolean)} * when presenting the {@link #requirePermission} array to that method. *

    * Often users will setup an AclEntryAfterInvocationProvider with a {@link * #processConfigAttribute} of AFTER_ACL_READ and a {@link #requirePermission} of * BasePermission.READ. These are also the defaults. *

    * If the principal does not have sufficient permissions, an AccessDeniedException will be thrown. *

    * If the provided returnedObject is null, permission will always be granted and * null will be returned. *

    * All comparisons and prefixes are case sensitive. */ public class AclEntryAfterInvocationProvider extends AbstractAclProvider implements MessageSourceAware { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationProvider.class); //~ Instance fields ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); //~ Constructors =================================================================================================== public AclEntryAfterInvocationProvider(AclService aclService, Permission[] requirePermission) { super(aclService, "AFTER_ACL_READ", requirePermission); } //~ Methods ======================================================================================================== public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { Iterator iter = config.getConfigAttributes().iterator(); if (returnedObject == null) { // AclManager interface contract prohibits nulls // As they have permission to null/nothing, grant access if (logger.isDebugEnabled()) { logger.debug("Return object is null, skipping"); } return null; } if (!getProcessDomainObjectClass().isAssignableFrom(returnedObject.getClass())) { if (logger.isDebugEnabled()) { logger.debug("Return object is not applicable for this provider, skipping"); } return returnedObject; } while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (!this.supports(attr)) { continue; } // Need to make an access decision on this invocation if (hasPermission(authentication, returnedObject)) { return returnedObject; } logger.debug("Denying access"); throw new AccessDeniedException(messages.getMessage("BasicAclEntryAfterInvocationProvider.noPermission", new Object[] {authentication.getName(), returnedObject}, "Authentication {0} has NO permissions to the domain object {1}")); } return returnedObject; } public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } } ././@LongLink0000000000000000000000000000023400000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/afterinvocation/0000644000000000000000000001352111623517156030567 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.afterinvocation; import org.springframework.security.AccessDeniedException; import org.springframework.security.Authentication; import org.springframework.security.AuthorizationServiceException; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.acls.AclService; import org.springframework.security.acls.Permission; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Collection; import java.util.Iterator; /** *

    * Given a Collection of domain object instances returned from a secure object invocation, remove * any Collection elements the principal does not have appropriate permission to access as defined by the * {@link AclService}. *

    * The AclService is used to retrieve the access control list (ACL) permissions associated with * each Collection domain object instance element for the current Authentication object. *

    * This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link * #processConfigAttribute}. The provider will then lookup the ACLs from the AclService and ensure the * principal is {@link org.springframework.security.acls.Acl#isGranted(org.springframework.security.acls.Permission[], * org.springframework.security.acls.sid.Sid[], boolean) Acl.isGranted(Permission[], Sid[], boolean)} * when presenting the {@link #requirePermission} array to that method. *

    * If the principal does not have permission, that element will not be included in the returned * Collection. *

    * Often users will setup a BasicAclEntryAfterInvocationProvider with a {@link * #processConfigAttribute} of AFTER_ACL_COLLECTION_READ and a {@link #requirePermission} of * BasePermission.READ. These are also the defaults. *

    * If the provided returnObject is null, a nullCollection * will be returned. If the provided returnObject is not a Collection, an {@link * AuthorizationServiceException} will be thrown. *

    * All comparisons and prefixes are case sensitive. * * @author Ben Alex * @author Paulo Neves * @version $Id$ */ public class AclEntryAfterInvocationCollectionFilteringProvider extends AbstractAclProvider { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationCollectionFilteringProvider.class); //~ Constructors =================================================================================================== public AclEntryAfterInvocationCollectionFilteringProvider(AclService aclService, Permission[] requirePermission) { super(aclService, "AFTER_ACL_COLLECTION_READ", requirePermission); } //~ Methods ======================================================================================================== public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject) throws AccessDeniedException { if (returnedObject == null) { if (logger.isDebugEnabled()) { logger.debug("Return object is null, skipping"); } return null; } Iterator iter = config.getConfigAttributes().iterator(); while (iter.hasNext()) { ConfigAttribute attr = (ConfigAttribute) iter.next(); if (!this.supports(attr)) { continue; } // Need to process the Collection for this invocation Filterer filterer; if (returnedObject instanceof Collection) { filterer = new CollectionFilterer((Collection) returnedObject); } else if (returnedObject.getClass().isArray()) { filterer = new ArrayFilterer((Object[]) returnedObject); } else { throw new AuthorizationServiceException("A Collection or an array (or null) was required as the " + "returnedObject, but the returnedObject was: " + returnedObject); } // Locate unauthorised Collection elements Iterator collectionIter = filterer.iterator(); while (collectionIter.hasNext()) { Object domainObject = collectionIter.next(); // Ignore nulls or entries which aren't instances of the configured domain object class if (domainObject == null || !getProcessDomainObjectClass().isAssignableFrom(domainObject.getClass())) { continue; } if(!hasPermission(authentication, domainObject)) { filterer.remove(domainObject); if (logger.isDebugEnabled()) { logger.debug("Principal is NOT authorised for element: " + domainObject); } } } return filterer.getFilteredObject(); } return returnedObject; } } spring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/0000755000000000000000000000000011623517156026312 5ustar ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/objectidentity/spring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/objectident0000755000000000000000000000000011623517156030525 5ustar ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/objectidentity/ObjectIdentityImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/objectident0000644000000000000000000001267111623517156030536 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.objectidentity; import org.springframework.security.acls.IdentityUnavailableException; import org.springframework.security.acls.jdbc.LookupStrategy; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import java.io.Serializable; import java.lang.reflect.Method; /** * Simple implementation of {@link ObjectIdentity}. *

    * Uses Strings to store the identity of the domain object instance. Also offers a constructor that uses * reflection to build the identity information. * * @author Ben Alex * @version $Id$ */ public class ObjectIdentityImpl implements ObjectIdentity { //~ Instance fields ================================================================================================ private Class javaType; private Serializable identifier; //~ Constructors =================================================================================================== public ObjectIdentityImpl(String javaType, Serializable identifier) { Assert.hasText(javaType, "Java Type required"); Assert.notNull(identifier, "identifier required"); try { this.javaType = Class.forName(javaType); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } this.identifier = identifier; } public ObjectIdentityImpl(Class javaType, Serializable identifier) { Assert.notNull(javaType, "Java Type required"); Assert.notNull(identifier, "identifier required"); this.javaType = javaType; this.identifier = identifier; } /** * Creates the ObjectIdentityImpl based on the passed * object instance. The passed object must provide a getId() * method, otherwise an exception will be thrown. The object passed will * be considered the {@link #javaType}, so if more control is required, * an alternate constructor should be used instead. * * @param object the domain object instance to create an identity for * * @throws IdentityUnavailableException if identity could not be extracted */ public ObjectIdentityImpl(Object object) throws IdentityUnavailableException { Assert.notNull(object, "object cannot be null"); this.javaType = ClassUtils.getUserClass(object.getClass()); Object result; try { Method method = this.javaType.getMethod("getId", new Class[] {}); result = method.invoke(object, new Object[] {}); } catch (Exception e) { throw new IdentityUnavailableException("Could not extract identity from object " + object, e); } Assert.notNull(result, "getId() is required to return a non-null value"); Assert.isInstanceOf(Serializable.class, result, "Getter must provide a return value of type Serializable"); this.identifier = (Serializable) result; } //~ Methods ======================================================================================================== /** * Important so caching operates properly.

    Considers an object of the same class equal if it has the same * classname and id properties.

    * *

    * Note that this class uses string equality for the identifier field, which ensures it better supports * differences between {@link LookupStrategy} requirements and the domain object represented by this * ObjectIdentityImpl. *

    * * @param arg0 object to compare * * @return true if the presented object matches this object */ public boolean equals(Object arg0) { if (arg0 == null) { return false; } if (!(arg0 instanceof ObjectIdentityImpl)) { return false; } ObjectIdentityImpl other = (ObjectIdentityImpl) arg0; if (this.getIdentifier().toString().equals(other.getIdentifier().toString()) && this.getJavaType().equals(other.getJavaType())) { return true; } return false; } public Serializable getIdentifier() { return identifier; } public Class getJavaType() { return javaType; } /** * Important so caching operates properly. * * @return the hash */ public int hashCode() { int code = 31; code ^= this.javaType.hashCode(); code ^= this.identifier.hashCode(); return code; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(this.getClass().getName()).append("["); sb.append("Java Type: ").append(this.javaType.getName()); sb.append("; Identifier: ").append(this.identifier).append("]"); return sb.toString(); } } ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/objectidentity/ObjectIdentityRetrievalStrategy.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/objectident0000644000000000000000000000212311623517156030525 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.objectidentity; /** * Strategy interface that provides the ability to determine which {@link ObjectIdentity} * will be returned for a particular domain object * * @author Ben Alex * @version $Id$ * */ public interface ObjectIdentityRetrievalStrategy { //~ Methods ======================================================================================================== ObjectIdentity getObjectIdentity(Object domainObject); } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/objectidentity/ObjectIdentity.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/objectident0000644000000000000000000000531311623517156030531 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.objectidentity; import java.io.Serializable; /** * Represents the identity of an individual domain object instance. * *

    * As implementations of ObjectIdentity are used as the key to represent * domain objects in the ACL subsystem, it is essential that implementations provide * methods so that object-equality rather than reference-equality can be relied upon * reliably. In other words, the ACL subsystem can consider two * ObjectIdentitys equal if identity1.equals(identity2), rather than * reference-equality of identity1==identity2. *

    * * @author Ben Alex * @version $Id$ */ public interface ObjectIdentity extends Serializable { //~ Methods ======================================================================================================== /** * @param obj to be compared * * @return true if the objects are equal, false otherwise * @see Object#equals(Object) */ boolean equals(Object obj); /** * Obtains the actual identifier. This identifier must not be reused to represent other domain objects with * the same javaType. * *

    Because ACLs are largely immutable, it is strongly recommended to use * a synthetic identifier (such as a database sequence number for the primary key). Do not use an identifier with * business meaning, as that business meaning may change in the future such change will cascade to the ACL * subsystem data.

    * * @return the identifier (unique within this javaType; never null) */ Serializable getIdentifier(); /** * Obtains the Java type represented by the domain object. The Java type can be an interface or a class, but is * most often the domain object implementation class. * * @return the Java type of the domain object (never null) */ Class getJavaType(); /** * @return a hash code representation of the ObjectIdentity * @see Object#hashCode() */ int hashCode(); } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/objectidentity/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/objectident0000644000000000000000000000014111623517156030523 0ustar Provides indirection between ACL packages and domain objects. ././@LongLink0000000000000000000000000000022100000000000011560 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/objectidentity/ObjectIdentityRetrievalStrategyImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/objectident0000644000000000000000000000232511623517156030531 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.objectidentity; /** * Basic implementation of {@link ObjectIdentityRetrievalStrategy} that uses the constructor of {@link * ObjectIdentityImpl} to create the {@link ObjectIdentity}. * * @author Ben Alex * @version $Id$ */ public class ObjectIdentityRetrievalStrategyImpl implements ObjectIdentityRetrievalStrategy { //~ Methods ======================================================================================================== public ObjectIdentity getObjectIdentity(Object domainObject) { return new ObjectIdentityImpl(domainObject); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/OwnershipAcl.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/OwnershipAc0000644000000000000000000000220111623517156030452 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import org.springframework.security.acls.sid.Sid; /** * A mutable ACL that provides ownership capabilities. * *

    * Generally the owner of an ACL is able to call any ACL mutator method, as * well as assign a new owner. *

    * * @author Ben Alex * @version $Id$ */ public interface OwnershipAcl extends MutableAcl { //~ Methods ======================================================================================================== void setOwner(Sid newOwner); } spring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/0000755000000000000000000000000011623517156027071 5ustar ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/PrincipalSid.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/Princip0000644000000000000000000000543711623517156030431 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.sid; import org.springframework.security.Authentication; import org.springframework.security.userdetails.UserDetails; import org.springframework.util.Assert; /** * Represents an Authentication.getPrincipal() as a Sid.

    This is a basic implementation * that simply uses the String-based principal for Sid comparison. More complex principal * objects may wish to provide an alternative Sid implementation that uses some other identifier.

    * * @author Ben Alex * @version $Id$ */ public class PrincipalSid implements Sid { //~ Instance fields ================================================================================================ private String principal; //~ Constructors =================================================================================================== public PrincipalSid(String principal) { Assert.hasText(principal, "Principal required"); this.principal = principal; } public PrincipalSid(Authentication authentication) { Assert.notNull(authentication, "Authentication required"); Assert.notNull(authentication.getPrincipal(), "Principal required"); if (authentication.getPrincipal() instanceof UserDetails) { this.principal = ((UserDetails) authentication.getPrincipal()).getUsername(); } else { this.principal = authentication.getPrincipal().toString(); } } //~ Methods ======================================================================================================== public boolean equals(Object object) { if ((object == null) || !(object instanceof PrincipalSid)) { return false; } // Delegate to getPrincipal() to perform actual comparison (both should be identical) return ((PrincipalSid) object).getPrincipal().equals(this.getPrincipal()); } public int hashCode() { return this.getPrincipal().hashCode(); } public String getPrincipal() { return principal; } public String toString() { return "PrincipalSid[" + this.principal + "]"; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/package0000644000000000000000000000022111623517156030402 0ustar Provides indirection between ACL packages and security identities, such as principals and GrantedAuthority[]s. ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/Sid.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/Sid.jav0000644000000000000000000000353611623517156030321 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.sid; import java.io.Serializable; /** * A security identity recognised by the ACL system. * *

    * This interface provides indirection between actual security objects (eg * principals, roles, groups etc) and what is stored inside an * Acl. This is because an Acl will not store an * entire security object, but only an abstraction of it. This interface * therefore provides a simple way to compare these abstracted security * identities with other security identities and actual security objects. *

    * * @author Ben Alex * @version $Id$ */ public interface Sid extends Serializable { //~ Methods ======================================================================================================== /** * Refer to the java.lang.Object documentation for the interface contract. * * @param obj to be compared * * @return true if the objects are equal, false otherwise */ boolean equals(Object obj); /** * Refer to the java.lang.Object documentation for the interface contract. * * @return a hash code representation of this object */ int hashCode(); } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/SidRetrievalStrategy.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/SidRetr0000644000000000000000000000213511623517156030371 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.sid; import org.springframework.security.Authentication; /** * Strategy interface that provides an ability to determine the {@link Sid} instances applicable * for an {@link Authentication}. * * @author Ben Alex * @version $Id$ */ public interface SidRetrievalStrategy { //~ Methods ======================================================================================================== Sid[] getSids(Authentication authentication); } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/GrantedAuthoritySid.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/Granted0000644000000000000000000000536711623517156030413 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.sid; import org.springframework.security.GrantedAuthority; import org.springframework.util.Assert; /** * Represents a GrantedAuthority as a Sid.

    This is a basic implementation that simply * uses the String-based principal for Sid comparison. More complex principal objects may * wish to provide an alternative Sid implementation that uses some other identifier.

    * * @author Ben Alex * @version $Id$ */ public class GrantedAuthoritySid implements Sid { //~ Instance fields ================================================================================================ private String grantedAuthority; //~ Constructors =================================================================================================== public GrantedAuthoritySid(String grantedAuthority) { Assert.hasText(grantedAuthority, "GrantedAuthority required"); this.grantedAuthority = grantedAuthority; } public GrantedAuthoritySid(GrantedAuthority grantedAuthority) { Assert.notNull(grantedAuthority, "GrantedAuthority required"); Assert.notNull(grantedAuthority.getAuthority(), "This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()"); this.grantedAuthority = grantedAuthority.getAuthority(); } //~ Methods ======================================================================================================== public boolean equals(Object object) { if ((object == null) || !(object instanceof GrantedAuthoritySid)) { return false; } // Delegate to getGrantedAuthority() to perform actual comparison (both should be identical) return ((GrantedAuthoritySid) object).getGrantedAuthority().equals(this.getGrantedAuthority()); } public int hashCode() { return this.getGrantedAuthority().hashCode(); } public String getGrantedAuthority() { return grantedAuthority; } public String toString() { return "GrantedAuthoritySid[" + this.grantedAuthority + "]"; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/SidRetrievalStrategyImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/sid/SidRetr0000644000000000000000000000325211623517156030372 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.sid; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; /** * Basic implementation of {@link SidRetrievalStrategy} that creates a {@link Sid} for the principal, as well as * every granted authority the principal holds. *

    * The returned array will always contain the {@link PrincipalSid} before any {@link GrantedAuthoritySid} elements. * * @author Ben Alex * @version $Id$ */ public class SidRetrievalStrategyImpl implements SidRetrievalStrategy { //~ Methods ======================================================================================================== public Sid[] getSids(Authentication authentication) { GrantedAuthority[] authorities = authentication.getAuthorities(); Sid[] sids = new Sid[authorities.length + 1]; sids[0] = new PrincipalSid(authentication); for (int i = 1; i <= authorities.length; i++) { sids[i] = new GrantedAuthoritySid(authorities[i - 1]); } return sids; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/AclService.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/AclService.0000644000000000000000000001103011623517156030326 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.sid.Sid; import java.util.Map; /** * Provides retrieval of {@link Acl} instances. * * @author Ben Alex * @version $Id$ */ public interface AclService { //~ Methods ======================================================================================================== /** * Locates all object identities that use the specified parent. This is useful for administration tools. * * @param parentIdentity to locate children of * * @return the children (or null if none were found) */ ObjectIdentity[] findChildren(ObjectIdentity parentIdentity); /** * Same as {@link #readAclsById(ObjectIdentity[])} except it returns only a single Acl.

    This method * should not be called as it does not leverage the underlaying implementation's potential ability to filter * Acl entries based on a {@link Sid} parameter.

    * * @param object to locate an {@link Acl} for * * @return the {@link Acl} for the requested {@link ObjectIdentity} (never null) * * @throws NotFoundException if an {@link Acl} was not found for the requested {@link ObjectIdentity} */ Acl readAclById(ObjectIdentity object) throws NotFoundException; /** * Same as {@link #readAclsById(ObjectIdentity[], Sid[])} except it returns only a single Acl. * * @param object to locate an {@link Acl} for * @param sids the security identities for which {@link Acl} information is required * (may be null to denote all entries) * * @return the {@link Acl} for the requested {@link ObjectIdentity} (never null) * * @throws NotFoundException if an {@link Acl} was not found for the requested {@link ObjectIdentity} */ Acl readAclById(ObjectIdentity object, Sid[] sids) throws NotFoundException; /** * Obtains all the Acls that apply for the passed Objects.

    The returned map is * keyed on the passed objects, with the values being the Acl instances. Any unknown objects will not * have a map key.

    * * @param objects the objects to find {@link Acl} information for * * @return a map with exactly one element for each {@link ObjectIdentity} passed as an argument (never null) * * @throws NotFoundException if an {@link Acl} was not found for each requested {@link ObjectIdentity} */ Map readAclsById(ObjectIdentity[] objects) throws NotFoundException; /** * Obtains all the Acls that apply for the passed Objects, but only for the * security identifies passed.

    Implementations MAY provide a subset of the ACLs via this method * although this is NOT a requirement. This is intended to allow performance optimisations within implementations. * Callers should therefore use this method in preference to the alternative overloaded version which does not * have performance optimisation opportunities.

    *

    The returned map is keyed on the passed objects, with the values being the Acl * instances. Any unknown objects (or objects for which the interested Sids do not have entries) will * not have a map key.

    * * @param objects the objects to find {@link Acl} information for * @param sids the security identities for which {@link Acl} information is required * (may be null to denote all entries) * * @return a map with exactly one element for each {@link ObjectIdentity} passed as an argument (never null) * * @throws NotFoundException if an {@link Acl} was not found for each requested {@link ObjectIdentity} */ Map readAclsById(ObjectIdentity[] objects, Sid[] sids) throws NotFoundException; } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/ChildrenExistException.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/ChildrenExi0000644000000000000000000000303111623517156030430 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import org.springframework.security.SpringSecurityException; /** * Thrown if an {@link Acl} cannot be deleted because children Acls exist. * * @author Ben Alex * @version $Id$ */ public class ChildrenExistException extends SpringSecurityException { //~ Constructors =================================================================================================== /** * Constructs an ChildrenExistException with the specified * message. * * @param msg the detail message */ public ChildrenExistException(String msg) { super(msg); } /** * Constructs an ChildrenExistException with the specified * message and root cause. * * @param msg the detail message * @param t root cause */ public ChildrenExistException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/AccessControlEntry.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/AccessContr0000644000000000000000000000321011623517156030440 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import org.springframework.security.acls.sid.Sid; import java.io.Serializable; /** * Represents an individual permission assignment within an {@link Acl}. * *

    * Instances MUST be immutable, as they are returned by Acl * and should not allow client modification. *

    * * @author Ben Alex * @version $Id$ * */ public interface AccessControlEntry extends Serializable { //~ Methods ======================================================================================================== Acl getAcl(); /** * Obtains an identifier that represents this ACE. * * @return the identifier, or null if unsaved */ Serializable getId(); Permission getPermission(); Sid getSid(); /** * Indicates the a Permission is being granted to the relevant Sid. If false, indicates the permission is * being revoked/blocked. * * @return true if being granted, false otherwise */ boolean isGranting(); } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/AlreadyExistsException.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/AlreadyExis0000644000000000000000000000300011623517156030440 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import org.springframework.security.SpringSecurityException; /** * Thrown if an Acl entry already exists for the object. * * @author Ben Alex * @version $Id$ */ public class AlreadyExistsException extends SpringSecurityException { //~ Constructors =================================================================================================== /** * Constructs an AlreadyExistsException with the specified message. * * @param msg the detail message */ public AlreadyExistsException(String msg) { super(msg); } /** * Constructs an AlreadyExistsException with the specified message * and root cause. * * @param msg the detail message * @param t root cause */ public AlreadyExistsException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/UnloadedSidException.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/UnloadedSid0000644000000000000000000000314111623517156030427 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import org.springframework.security.SpringSecurityException; /** * Thrown if an {@link Acl} cannot perform an operation because it only loaded a subset of Sids and * the caller has requested details for an unloaded Sid. * * @author Ben Alex * @version $Id$ */ public class UnloadedSidException extends SpringSecurityException { //~ Constructors =================================================================================================== /** * Constructs an NotFoundException with the specified message. * * @param msg the detail message */ public UnloadedSidException(String msg) { super(msg); } /** * Constructs an NotFoundException with the specified message * and root cause. * * @param msg the detail message * @param t root cause */ public UnloadedSidException(String msg, Throwable t) { super(msg, t); } } spring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/0000755000000000000000000000000011623517156027214 5ustar ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/select.sqlspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/select0000644000000000000000000000207711623517156030424 0ustar -- Not required. Just shows the sort of queries being sent to DB. select ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY, ACL_ENTRY.ACE_ORDER, ACL_OBJECT_IDENTITY.ID as ACL_ID, ACL_OBJECT_IDENTITY.PARENT_OBJECT, ACL_OBJECT_IDENTITY,ENTRIES_INHERITING, ACL_ENTRY.ID as ACE_ID, ACL_ENTRY.MASK, ACL_ENTRY.GRANTING, ACL_ENTRY.AUDIT_SUCCESS, ACL_ENTRY.AUDIT_FAILURE, ACL_SID.PRINCIPAL as ACE_PRINCIPAL, ACL_SID.SID as ACE_SID, ACLI_SID.PRINCIPAL as ACL_PRINCIPAL, ACLI_SID.SID as ACL_SID, ACL_CLASS.CLASS from ACL_OBJECT_IDENTITY, ACL_SID ACLI_SID, ACL_CLASS LEFT JOIN ACL_ENTRY ON ACL_OBJECT_IDENTITY.ID = ACL_ENTRY.ACL_OBJECT_IDENTITY LEFT JOIN ACL_SID ON ACL_ENTRY.SID = ACL_SID.ID where ACLI_SID.ID = ACL_OBJECT_IDENTITY.OWNER_SID and ACL_CLASS.ID = ACL_OBJECT_IDENTITY.OBJECT_ID_CLASS and ( (ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY = 1 and ACL_CLASS.CLASS = 'sample.contact.Contact') or (ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY = 2000 and ACL_CLASS.CLASS = 'sample.contact.Contact') ) order by ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY asc, ACL_ENTRY.ACE_ORDER asc ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/LookupStrategy.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/Lookup0000644000000000000000000000360111623517156030410 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.jdbc; import org.springframework.security.acls.NotFoundException; import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.sid.Sid; import java.util.Map; /** * Performs lookups for {@link org.springframework.security.acls.AclService}. * * @author Ben Alex * @version $Id$ */ public interface LookupStrategy { //~ Methods ======================================================================================================== /** * Perform database-specific optimized lookup. * * @param objects the identities to lookup (required) * @param sids the SIDs for which identities are required (may be null - implementations may elect not * to provide SID optimisations) * * @return a Map where keys represent the {@link ObjectIdentity} of the located {@link Acl} and values * are the located {@link Acl} (never null although some entries may be missing; this method * should not throw {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used * to automatically create entries if required) */ Map readAclsById(ObjectIdentity[] objects, Sid[] sids); } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/AclCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/AclCac0000644000000000000000000000245211623517156030250 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.jdbc; import org.springframework.security.acls.MutableAcl; import org.springframework.security.acls.objectidentity.ObjectIdentity; import java.io.Serializable; /** * A caching layer for {@link JdbcAclService}. * * @author Ben Alex * @version $Id$ * */ public interface AclCache { //~ Methods ======================================================================================================== void evictFromCache(Serializable pk); void evictFromCache(ObjectIdentity objectIdentity); MutableAcl getFromCache(ObjectIdentity objectIdentity); MutableAcl getFromCache(Serializable pk); void putInCache(MutableAcl acl); } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/JdbcAclService.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/JdbcAc0000644000000000000000000001220511623517156030245 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.jdbc; import org.springframework.security.acls.Acl; import org.springframework.security.acls.AclService; import org.springframework.security.acls.NotFoundException; import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.objectidentity.ObjectIdentityImpl; import org.springframework.security.acls.sid.Sid; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Map; import javax.sql.DataSource; /** * Simple JDBC-based implementation of AclService. *

    * Requires the "dirty" flags in {@link org.springframework.security.acls.domain.AclImpl} and * {@link org.springframework.security.acls.domain.AccessControlEntryImpl} to be set, so that the implementation can * detect changed parameters easily. * * @author Ben Alex * @version $Id$ */ public class JdbcAclService implements AclService { //~ Static fields/initializers ===================================================================================== protected static final Log log = LogFactory.getLog(JdbcAclService.class); private static final String selectAclObjectWithParent = "select obj.object_id_identity as obj_id, class.class as class " + "from acl_object_identity obj, acl_object_identity parent, acl_class class " + "where obj.parent_object = parent.id and obj.object_id_class = class.id " + "and parent.object_id_identity = ? and parent.object_id_class = (" + "select id FROM acl_class where acl_class.class = ?)"; //~ Instance fields ================================================================================================ protected JdbcTemplate jdbcTemplate; private LookupStrategy lookupStrategy; //~ Constructors =================================================================================================== public JdbcAclService(DataSource dataSource, LookupStrategy lookupStrategy) { Assert.notNull(dataSource, "DataSource required"); Assert.notNull(lookupStrategy, "LookupStrategy required"); this.jdbcTemplate = new JdbcTemplate(dataSource); this.lookupStrategy = lookupStrategy; } //~ Methods ======================================================================================================== public ObjectIdentity[] findChildren(ObjectIdentity parentIdentity) { Object[] args = {parentIdentity.getIdentifier(), parentIdentity.getJavaType().getName()}; List objects = jdbcTemplate.query(selectAclObjectWithParent, args, new RowMapper() { public Object mapRow(ResultSet rs, int rowNum) throws SQLException { String javaType = rs.getString("class"); Long identifier = new Long(rs.getLong("obj_id")); return new ObjectIdentityImpl(javaType, identifier); } }); if (objects.size() == 0) { return null; } return (ObjectIdentityImpl[]) objects.toArray(new ObjectIdentityImpl[objects.size()]); } public Acl readAclById(ObjectIdentity object, Sid[] sids) throws NotFoundException { Map map = readAclsById(new ObjectIdentity[] {object}, sids); Assert.isTrue(map.containsKey(object), "There should have been an Acl entry for ObjectIdentity " + object); return (Acl) map.get(object); } public Acl readAclById(ObjectIdentity object) throws NotFoundException { return readAclById(object, null); } public Map readAclsById(ObjectIdentity[] objects) throws NotFoundException { return readAclsById(objects, null); } public Map readAclsById(ObjectIdentity[] objects, Sid[] sids) throws NotFoundException { Map result = lookupStrategy.readAclsById(objects, sids); // Check every requested object identity was found (throw NotFoundException if needed) for (int i = 0; i < objects.length; i++) { if (!result.containsKey(objects[i])) { throw new NotFoundException("Unable to find ACL information for object identity '" + objects[i].toString() + "'"); } } return result; } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/BasicLookupStrategy.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/BasicL0000644000000000000000000005730711623517156030310 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.jdbc; import java.lang.reflect.Field; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import javax.sql.DataSource; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementSetter; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.security.acls.AccessControlEntry; import org.springframework.security.acls.Acl; import org.springframework.security.acls.MutableAcl; import org.springframework.security.acls.NotFoundException; import org.springframework.security.acls.Permission; import org.springframework.security.acls.UnloadedSidException; import org.springframework.security.acls.domain.AccessControlEntryImpl; import org.springframework.security.acls.domain.AclAuthorizationStrategy; import org.springframework.security.acls.domain.AclImpl; import org.springframework.security.acls.domain.AuditLogger; import org.springframework.security.acls.domain.BasePermission; import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.objectidentity.ObjectIdentityImpl; import org.springframework.security.acls.sid.GrantedAuthoritySid; import org.springframework.security.acls.sid.PrincipalSid; import org.springframework.security.acls.sid.Sid; import org.springframework.security.util.FieldUtils; import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** * Performs lookups in a manner that is compatible with ANSI SQL.

    NB: This implementation does attempt to provide * reasonably optimised lookups - within the constraints of a normalised database and standard ANSI SQL features. If * you are willing to sacrifice either of these constraints (eg use a particular database feature such as hierarchical * queries or materalized views, or reduce normalisation) you are likely to achieve better performance. In such * situations you will need to provide your own custom LookupStrategy. This class does not support * subclassing, as it is likely to change in future releases and therefore subclassing is unsupported.

    * * @author Ben Alex * @version $Id$ */ public final class BasicLookupStrategy implements LookupStrategy { //~ Instance fields ================================================================================================ private AclAuthorizationStrategy aclAuthorizationStrategy; private AclCache aclCache; private AuditLogger auditLogger; private JdbcTemplate jdbcTemplate; private int batchSize = 50; //~ Constructors =================================================================================================== /** * Constructor accepting mandatory arguments * * @param dataSource to access the database * @param aclCache the cache where fully-loaded elements can be stored * @param aclAuthorizationStrategy authorization strategy (required) */ public BasicLookupStrategy(DataSource dataSource, AclCache aclCache, AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) { Assert.notNull(dataSource, "DataSource required"); Assert.notNull(aclCache, "AclCache required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); Assert.notNull(auditLogger, "AuditLogger required"); this.jdbcTemplate = new JdbcTemplate(dataSource); this.aclCache = aclCache; this.aclAuthorizationStrategy = aclAuthorizationStrategy; this.auditLogger = auditLogger; } //~ Methods ======================================================================================================== private static String computeRepeatingSql(String repeatingSql, int requiredRepetitions) { Assert.isTrue(requiredRepetitions >= 1, "Must be => 1"); String startSql = "select acl_object_identity.object_id_identity, " + "acl_entry.ace_order, " + "acl_object_identity.id as acl_id, " + "acl_object_identity.parent_object, " + "acl_object_identity.entries_inheriting, " + "acl_entry.id as ace_id, " + "acl_entry.mask, " + "acl_entry.granting, " + "acl_entry.audit_success, " + "acl_entry.audit_failure, " + "acl_sid.principal as ace_principal, " + "acl_sid.sid as ace_sid, " + "acli_sid.principal as acl_principal, " + "acli_sid.sid as acl_sid, " + "acl_class.class " + "from acl_object_identity " + "left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid " + "left join acl_class on acl_class.id = acl_object_identity.object_id_class " + "left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity " + "left join acl_sid on acl_entry.sid = acl_sid.id " + "where ( "; String endSql = ") order by acl_object_identity.object_id_identity" + " asc, acl_entry.ace_order asc"; StringBuffer sqlStringBuffer = new StringBuffer(); sqlStringBuffer.append(startSql); for (int i = 1; i <= requiredRepetitions; i++) { sqlStringBuffer.append(repeatingSql); if (i != requiredRepetitions) { sqlStringBuffer.append(" or "); } } sqlStringBuffer.append(endSql); return sqlStringBuffer.toString(); } /** * The final phase of converting the Map of AclImpl instances which contain * StubAclParents into proper, valid AclImpls with correct ACL parents. * * @param inputMap the unconverted AclImpls * @param currentIdentity the currentAcl that we wish to convert (this may be * * @return * * @throws IllegalStateException DOCUMENT ME! */ private AclImpl convert(Map inputMap, Long currentIdentity) { Assert.notEmpty(inputMap, "InputMap required"); Assert.notNull(currentIdentity, "CurrentIdentity required"); // Retrieve this Acl from the InputMap Acl uncastAcl = (Acl) inputMap.get(currentIdentity); Assert.isInstanceOf(AclImpl.class, uncastAcl, "The inputMap contained a non-AclImpl"); AclImpl inputAcl = (AclImpl) uncastAcl; Acl parent = inputAcl.getParentAcl(); if ((parent != null) && parent instanceof StubAclParent) { // Lookup the parent StubAclParent stubAclParent = (StubAclParent) parent; parent = convert(inputMap, stubAclParent.getId()); } // Now we have the parent (if there is one), create the true AclImpl AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), (Long) inputAcl.getId(), aclAuthorizationStrategy, auditLogger, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner()); // Copy the "aces" from the input to the destination Field fieldAces = FieldUtils.getField(AclImpl.class, "aces"); Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class, "acl"); try { fieldAces.setAccessible(true); fieldAcl.setAccessible(true); // Obtain the "aces" from the input ACL Iterator i = ((List) fieldAces.get(inputAcl)).iterator(); // Create a list in which to store the "aces" for the "result" AclImpl instance List acesNew = new ArrayList(); // Iterate over the "aces" input and replace each nested AccessControlEntryImpl.getAcl() with the new "result" AclImpl instance // This ensures StubAclParent instances are removed, as per SEC-951 while(i.hasNext()) { AccessControlEntryImpl ace = (AccessControlEntryImpl) i.next(); fieldAcl.set(ace, result); acesNew.add(ace); } // Finally, now that the "aces" have been converted to have the "result" AclImpl instance, modify the "result" AclImpl instance fieldAces.set(result, acesNew); } catch (IllegalAccessException ex) { throw new IllegalStateException("Could not obtain or set AclImpl or AccessControlEntryImpl fields"); } return result; } /** * Accepts the current ResultSet row, and converts it into an AclImpl that * contains a StubAclParent * * @param acls the Map we should add the converted Acl to * @param rs the ResultSet focused on a current row * * @throws SQLException if something goes wrong converting values * @throws IllegalStateException DOCUMENT ME! */ private void convertCurrentResultIntoObject(Map acls, ResultSet rs) throws SQLException { Long id = new Long(rs.getLong("acl_id")); // If we already have an ACL for this ID, just create the ACE AclImpl acl = (AclImpl) acls.get(id); if (acl == null) { // Make an AclImpl and pop it into the Map ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("class"), new Long(rs.getLong("object_id_identity"))); Acl parentAcl = null; long parentAclId = rs.getLong("parent_object"); if (parentAclId != 0) { parentAcl = new StubAclParent(new Long(parentAclId)); } boolean entriesInheriting = rs.getBoolean("entries_inheriting"); Sid owner; if (rs.getBoolean("acl_principal")) { owner = new PrincipalSid(rs.getString("acl_sid")); } else { owner = new GrantedAuthoritySid(rs.getString("acl_sid")); } acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, auditLogger, parentAcl, null, entriesInheriting, owner); acls.put(id, acl); } // Add an extra ACE to the ACL (ORDER BY maintains the ACE list order) // It is permissable to have no ACEs in an ACL (which is detected by a null ACE_SID) if (rs.getString("ace_sid") != null) { Long aceId = new Long(rs.getLong("ace_id")); Sid recipient; if (rs.getBoolean("ace_principal")) { recipient = new PrincipalSid(rs.getString("ace_sid")); } else { recipient = new GrantedAuthoritySid(rs.getString("ace_sid")); } int mask = rs.getInt("mask"); Permission permission = convertMaskIntoPermission(mask); boolean granting = rs.getBoolean("granting"); boolean auditSuccess = rs.getBoolean("audit_success"); boolean auditFailure = rs.getBoolean("audit_failure"); AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, recipient, permission, granting, auditSuccess, auditFailure); Field acesField = FieldUtils.getField(AclImpl.class, "aces"); List aces; try { acesField.setAccessible(true); aces = (List) acesField.get(acl); } catch (IllegalAccessException ex) { throw new IllegalStateException("Could not obtain AclImpl.ace field: cause[" + ex.getMessage() + "]"); } // Add the ACE if it doesn't already exist in the ACL.aces field if (!aces.contains(ace)) { aces.add(ace); } } } protected Permission convertMaskIntoPermission(int mask) { return BasePermission.buildFromMask(mask); } /** * Looks up a batch of ObjectIdentitys directly from the database.

    The caller is responsible * for optimization issues, such as selecting the identities to lookup, ensuring the cache doesn't contain them * already, and adding the returned elements to the cache etc.

    *

    This subclass is required to return fully valid Acls, including properly-configured * parent ACLs.

    * * @param objectIdentities DOCUMENT ME! * @param sids DOCUMENT ME! * * @return DOCUMENT ME! */ private Map lookupObjectIdentities(final ObjectIdentity[] objectIdentities, Sid[] sids) { Assert.notEmpty(objectIdentities, "Must provide identities to lookup"); final Map acls = new HashMap(); // contains Acls with StubAclParents // Make the "acls" map contain all requested objectIdentities // (including markers to each parent in the hierarchy) String sql = computeRepeatingSql("(acl_object_identity.object_id_identity = ? and acl_class.class = ?)", objectIdentities.length); Set parentsToLookup = (Set) jdbcTemplate.query(sql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { for (int i = 0; i < objectIdentities.length; i++) { // Determine prepared statement values for this iteration String javaType = objectIdentities[i].getJavaType().getName(); // No need to check for nulls, as guaranteed non-null by ObjectIdentity.getIdentifier() interface contract String identifier = objectIdentities[i].getIdentifier().toString(); long id = (Long.valueOf(identifier)).longValue(); // Inject values ps.setLong((2 * i) + 1, id); ps.setString((2 * i) + 2, javaType); } } }, new ProcessResultSet(acls, sids)); // Lookup the parents, now that our JdbcTemplate has released the database connection (SEC-547) if (parentsToLookup.size() > 0) { lookupPrimaryKeys(acls, parentsToLookup, sids); } // Finally, convert our "acls" containing StubAclParents into true Acls Map resultMap = new HashMap(); Iterator iter = acls.values().iterator(); while (iter.hasNext()) { Acl inputAcl = (Acl) iter.next(); Assert.isInstanceOf(AclImpl.class, inputAcl, "Map should have contained an AclImpl"); Assert.isInstanceOf(Long.class, ((AclImpl) inputAcl).getId(), "Acl.getId() must be Long"); Acl result = convert(acls, (Long) ((AclImpl) inputAcl).getId()); resultMap.put(result.getObjectIdentity(), result); } return resultMap; } /** * Locates the primary key IDs specified in "findNow", adding AclImpl instances with StubAclParents to the * "acls" Map. * * @param acls the AclImpls (with StubAclParents) * @param findNow Long-based primary keys to retrieve * @param sids DOCUMENT ME! */ private void lookupPrimaryKeys(final Map acls, final Set findNow, final Sid[] sids) { Assert.notNull(acls, "ACLs are required"); Assert.notEmpty(findNow, "Items to find now required"); String sql = computeRepeatingSql("(acl_object_identity.id = ?)", findNow.size()); Set parentsToLookup = (Set) jdbcTemplate.query(sql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { Iterator iter = findNow.iterator(); int i = 0; while (iter.hasNext()) { i++; ps.setLong(i, ((Long) iter.next()).longValue()); } } }, new ProcessResultSet(acls, sids)); // Lookup the parents, now that our JdbcTemplate has released the database connection (SEC-547) if (parentsToLookup.size() > 0) { lookupPrimaryKeys(acls, parentsToLookup, sids); } } /** * The main method.

    WARNING: This implementation completely disregards the "sids" argument! Every item * in the cache is expected to contain all SIDs. If you have serious performance needs (eg a very large number of * SIDs per object identity), you'll probably want to develop a custom {@link LookupStrategy} implementation * instead.

    *

    The implementation works in batch sizes specfied by {@link #batchSize}.

    * * @param objects the identities to lookup (required) * @param sids the SIDs for which identities are required (ignored by this implementation) * * @return a Map where keys represent the {@link ObjectIdentity} of the located {@link Acl} and values * are the located {@link Acl} (never null although some entries may be missing; this method * should not throw {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used * to automatically create entries if required) */ public Map readAclsById(ObjectIdentity[] objects, Sid[] sids) { Assert.isTrue(batchSize >= 1, "BatchSize must be >= 1"); Assert.notEmpty(objects, "Objects to lookup required"); // Map Map result = new HashMap(); // contains FULLY loaded Acl objects Set currentBatchToLoad = new HashSet(); // contains ObjectIdentitys for (int i = 0; i < objects.length; i++) { boolean aclFound = false; // Check we don't already have this ACL in the results if (result.containsKey(objects[i])) { aclFound = true; } // Check cache for the present ACL entry if (!aclFound) { Acl acl = aclCache.getFromCache(objects[i]); // Ensure any cached element supports all the requested SIDs // (they should always, as our base impl doesn't filter on SID) if (acl != null) { if (acl.isSidLoaded(sids)) { result.put(acl.getObjectIdentity(), acl); aclFound = true; } else { throw new IllegalStateException( "Error: SID-filtered element detected when implementation does not perform SID filtering " + "- have you added something to the cache manually?"); } } } // Load the ACL from the database if (!aclFound) { currentBatchToLoad.add(objects[i]); } // Is it time to load from JDBC the currentBatchToLoad? if ((currentBatchToLoad.size() == this.batchSize) || ((i + 1) == objects.length)) { if (currentBatchToLoad.size() > 0) { Map loadedBatch = lookupObjectIdentities((ObjectIdentity[]) currentBatchToLoad.toArray(new ObjectIdentity[] {}), sids); // Add loaded batch (all elements 100% initialized) to results result.putAll(loadedBatch); // Add the loaded batch to the cache Iterator loadedAclIterator = loadedBatch.values().iterator(); while (loadedAclIterator.hasNext()) { aclCache.putInCache((AclImpl) loadedAclIterator.next()); } currentBatchToLoad.clear(); } } } return result; } public void setBatchSize(int batchSize) { this.batchSize = batchSize; } //~ Inner Classes ================================================================================================== private class ProcessResultSet implements ResultSetExtractor { private Map acls; private Sid[] sids; public ProcessResultSet(Map acls, Sid[] sids) { Assert.notNull(acls, "ACLs cannot be null"); this.acls = acls; this.sids = sids; // can be null } /** * Implementation of {@link ResultSetExtractor#extractData(ResultSet)}. * Creates an {@link Acl} for each row in the {@link ResultSet} and * ensures it is in member field acls. Any {@link Acl} with * a parent will have the parents id returned in a set. The returned * set of ids may requires further processing. * @param rs The {@link ResultSet} to be processed * @return a list of parent IDs remaining to be looked up (may be empty, but never null) * @throws SQLException * @throws DataAccessException */ public Object extractData(ResultSet rs) throws SQLException, DataAccessException { Set parentIdsToLookup = new HashSet(); // Set of parent_id Longs while (rs.next()) { // Convert current row into an Acl (albeit with a StubAclParent) convertCurrentResultIntoObject(acls, rs); // Figure out if this row means we need to lookup another parent long parentId = rs.getLong("parent_object"); if (parentId != 0) { // See if it's already in the "acls" if (acls.containsKey(new Long(parentId))) { continue; // skip this while iteration } // Now try to find it in the cache MutableAcl cached = aclCache.getFromCache(new Long(parentId)); if ((cached == null) || !cached.isSidLoaded(sids)) { parentIdsToLookup.add(new Long(parentId)); } else { // Pop into the acls map, so our convert method doesn't // need to deal with an unsynchronized AclCache acls.put(cached.getId(), cached); } } } // Return the parents left to lookup to the calller return parentIdsToLookup; } } private class StubAclParent implements Acl { private Long id; public StubAclParent(Long id) { this.id = id; } public AccessControlEntry[] getEntries() { throw new UnsupportedOperationException("Stub only"); } public Long getId() { return id; } public ObjectIdentity getObjectIdentity() { throw new UnsupportedOperationException("Stub only"); } public Sid getOwner() { throw new UnsupportedOperationException("Stub only"); } public Acl getParentAcl() { throw new UnsupportedOperationException("Stub only"); } public boolean isEntriesInheriting() { throw new UnsupportedOperationException("Stub only"); } public boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode) throws NotFoundException, UnloadedSidException { throw new UnsupportedOperationException("Stub only"); } public boolean isSidLoaded(Sid[] sids) { throw new UnsupportedOperationException("Stub only"); } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/packag0000644000000000000000000000011611623517156030363 0ustar JDBC-based persistence of ACL information. ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/EhCacheBasedAclCache.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/EhCach0000644000000000000000000001141611623517156030255 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.jdbc; import java.io.Serializable; import net.sf.ehcache.CacheException; import net.sf.ehcache.Ehcache; import net.sf.ehcache.Element; import org.springframework.security.acls.MutableAcl; import org.springframework.security.acls.domain.AclAuthorizationStrategy; import org.springframework.security.acls.domain.AclImpl; import org.springframework.security.acls.domain.AuditLogger; import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.util.FieldUtils; import org.springframework.util.Assert; /** * Simple implementation of {@link AclCache} that delegates to EH-CACHE. * *

    * Designed to handle the transient fields in {@link AclImpl}. Note that this implementation assumes all * {@link AclImpl} instances share the same {@link AuditLogger} and {@link AclAuthorizationStrategy} instance. *

    * * @author Ben Alex * @version $Id$ */ public class EhCacheBasedAclCache implements AclCache { //~ Instance fields ================================================================================================ private Ehcache cache; private AuditLogger auditLogger; private AclAuthorizationStrategy aclAuthorizationStrategy; //~ Constructors =================================================================================================== public EhCacheBasedAclCache(Ehcache cache) { Assert.notNull(cache, "Cache required"); this.cache = cache; } //~ Methods ======================================================================================================== public void evictFromCache(Serializable pk) { Assert.notNull(pk, "Primary key (identifier) required"); MutableAcl acl = getFromCache(pk); if (acl != null) { cache.remove(acl.getId()); cache.remove(acl.getObjectIdentity()); } } public void evictFromCache(ObjectIdentity objectIdentity) { Assert.notNull(objectIdentity, "ObjectIdentity required"); MutableAcl acl = getFromCache(objectIdentity); if (acl != null) { cache.remove(acl.getId()); cache.remove(acl.getObjectIdentity()); } } public MutableAcl getFromCache(ObjectIdentity objectIdentity) { Assert.notNull(objectIdentity, "ObjectIdentity required"); Element element = null; try { element = cache.get(objectIdentity); } catch (CacheException ignored) {} if (element == null) { return null; } return initializeTransientFields((MutableAcl)element.getValue()); } public MutableAcl getFromCache(Serializable pk) { Assert.notNull(pk, "Primary key (identifier) required"); Element element = null; try { element = cache.get(pk); } catch (CacheException ignored) {} if (element == null) { return null; } return initializeTransientFields((MutableAcl) element.getValue()); } public void putInCache(MutableAcl acl) { Assert.notNull(acl, "Acl required"); Assert.notNull(acl.getObjectIdentity(), "ObjectIdentity required"); Assert.notNull(acl.getId(), "ID required"); if (this.aclAuthorizationStrategy == null) { if (acl instanceof AclImpl) { this.aclAuthorizationStrategy = (AclAuthorizationStrategy) FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy", acl); this.auditLogger = (AuditLogger) FieldUtils.getProtectedFieldValue("auditLogger", acl); } } if ((acl.getParentAcl() != null) && (acl.getParentAcl() instanceof MutableAcl)) { putInCache((MutableAcl) acl.getParentAcl()); } cache.put(new Element(acl.getObjectIdentity(), acl)); cache.put(new Element(acl.getId(), acl)); } private MutableAcl initializeTransientFields(MutableAcl value) { if (value instanceof AclImpl) { FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, this.aclAuthorizationStrategy); FieldUtils.setProtectedFieldValue("auditLogger", value, this.auditLogger); } return value; } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/applicationContext-test.xmlspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/applic0000644000000000000000000000471011623517156030411 0ustar ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/JdbcMutableAclService.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/JdbcMu0000644000000000000000000004157311623517156030315 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.jdbc; import org.springframework.security.Authentication; import org.springframework.security.acls.AccessControlEntry; import org.springframework.security.acls.Acl; import org.springframework.security.acls.AlreadyExistsException; import org.springframework.security.acls.ChildrenExistException; import org.springframework.security.acls.MutableAcl; import org.springframework.security.acls.MutableAclService; import org.springframework.security.acls.NotFoundException; import org.springframework.security.acls.domain.AccessControlEntryImpl; import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.objectidentity.ObjectIdentityImpl; import org.springframework.security.acls.sid.GrantedAuthoritySid; import org.springframework.security.acls.sid.PrincipalSid; import org.springframework.security.acls.sid.Sid; import org.springframework.security.context.SecurityContextHolder; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; import java.lang.reflect.Array; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; import javax.sql.DataSource; /** * Provides a base implementation of {@link MutableAclService}. * * @author Ben Alex * @author Johannes Zlattinger * @version $Id$ */ public class JdbcMutableAclService extends JdbcAclService implements MutableAclService { //~ Instance fields ================================================================================================ private boolean foreignKeysInDatabase = true; private AclCache aclCache; private String deleteEntryByObjectIdentityForeignKey = "delete from acl_entry where acl_object_identity=?"; private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?"; private String classIdentityQuery = "call identity()"; // should be overridden for postgres : select currval('acl_class_seq') private String sidIdentityQuery = "call identity()"; // should be overridden for postgres : select currval('acl_siq_seq') private String insertClass = "insert into acl_class (class) values (?)"; private String insertEntry = "insert into acl_entry " + "(acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)" + "values (?, ?, ?, ?, ?, ?, ?)"; private String insertObjectIdentity = "insert into acl_object_identity " + "(object_id_class, object_id_identity, owner_sid, entries_inheriting) " + "values (?, ?, ?, ?)"; private String insertSid = "insert into acl_sid (principal, sid) values (?, ?)"; private String selectClassPrimaryKey = "select id from acl_class where class=?"; private String selectObjectIdentityPrimaryKey = "select acl_object_identity.id from acl_object_identity, acl_class " + "where acl_object_identity.object_id_class = acl_class.id and acl_class.class=? " + "and acl_object_identity.object_id_identity = ?"; private String selectSidPrimaryKey = "select id from acl_sid where principal=? and sid=?"; private String updateObjectIdentity = "update acl_object_identity set " + "parent_object = ?, owner_sid = ?, entries_inheriting = ?" + " where id = ?"; //~ Constructors =================================================================================================== public JdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) { super(dataSource, lookupStrategy); Assert.notNull(aclCache, "AclCache required"); this.aclCache = aclCache; } //~ Methods ======================================================================================================== public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException { Assert.notNull(objectIdentity, "Object Identity required"); // Check this object identity hasn't already been persisted if (retrieveObjectIdentityPrimaryKey(objectIdentity) != null) { throw new AlreadyExistsException("Object identity '" + objectIdentity + "' already exists"); } // Need to retrieve the current principal, in order to know who "owns" this ACL (can be changed later on) Authentication auth = SecurityContextHolder.getContext().getAuthentication(); PrincipalSid sid = new PrincipalSid(auth); // Create the acl_object_identity row createObjectIdentity(objectIdentity, sid); // Retrieve the ACL via superclass (ensures cache registration, proper retrieval etc) Acl acl = readAclById(objectIdentity); Assert.isInstanceOf(MutableAcl.class, acl, "MutableAcl should be been returned"); return (MutableAcl) acl; } /** * Creates a new row in acl_entry for every ACE defined in the passed MutableAcl object. * * @param acl containing the ACEs to insert */ protected void createEntries(final MutableAcl acl) { jdbcTemplate.batchUpdate(insertEntry, new BatchPreparedStatementSetter() { public int getBatchSize() { return acl.getEntries().length; } public void setValues(PreparedStatement stmt, int i) throws SQLException { AccessControlEntry entry_ = (AccessControlEntry) Array.get(acl.getEntries(), i); Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class"); AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_; stmt.setLong(1, ((Long) acl.getId()).longValue()); stmt.setInt(2, i); stmt.setLong(3, createOrRetrieveSidPrimaryKey(entry.getSid(), true).longValue()); stmt.setInt(4, entry.getPermission().getMask()); stmt.setBoolean(5, entry.isGranting()); stmt.setBoolean(6, entry.isAuditSuccess()); stmt.setBoolean(7, entry.isAuditFailure()); } }); } /** * Creates an entry in the acl_object_identity table for the passed ObjectIdentity. The Sid is also * necessary, as acl_object_identity has defined the sid column as non-null. * * @param object to represent an acl_object_identity for * @param owner for the SID column (will be created if there is no acl_sid entry for this particular Sid already) */ protected void createObjectIdentity(ObjectIdentity object, Sid owner) { Long sidId = createOrRetrieveSidPrimaryKey(owner, true); Long classId = createOrRetrieveClassPrimaryKey(object.getJavaType(), true); jdbcTemplate.update(insertObjectIdentity, new Object[] {classId, object.getIdentifier().toString(), sidId, new Boolean(true)}); } /** * Retrieves the primary key from acl_class, creating a new row if needed and the allowCreate property is * true. * * @param clazz to find or create an entry for (this implementation uses the fully-qualified class name String) * @param allowCreate true if creation is permitted if not found * * @return the primary key or null if not found */ protected Long createOrRetrieveClassPrimaryKey(Class clazz, boolean allowCreate) { List classIds = jdbcTemplate.queryForList(selectClassPrimaryKey, new Object[] {clazz.getName()}, Long.class); Long classId = null; if (classIds.isEmpty()) { if (allowCreate) { classId = null; jdbcTemplate.update(insertClass, new Object[] {clazz.getName()}); Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running"); classId = new Long(jdbcTemplate.queryForLong(classIdentityQuery)); } } else { classId = (Long) classIds.iterator().next(); } return classId; } /** * Retrieves the primary key from acl_sid, creating a new row if needed and the allowCreate property is * true. * * @param sid to find or create * @param allowCreate true if creation is permitted if not found * * @return the primary key or null if not found * * @throws IllegalArgumentException DOCUMENT ME! */ protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) { Assert.notNull(sid, "Sid required"); String sidName = null; boolean principal = true; if (sid instanceof PrincipalSid) { sidName = ((PrincipalSid) sid).getPrincipal(); } else if (sid instanceof GrantedAuthoritySid) { sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority(); principal = false; } else { throw new IllegalArgumentException("Unsupported implementation of Sid"); } List sidIds = jdbcTemplate.queryForList(selectSidPrimaryKey, new Object[] {new Boolean(principal), sidName}, Long.class); Long sidId = null; if (sidIds.isEmpty()) { if (allowCreate) { sidId = null; jdbcTemplate.update(insertSid, new Object[] {new Boolean(principal), sidName}); Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running"); sidId = new Long(jdbcTemplate.queryForLong(sidIdentityQuery)); } } else { sidId = (Long) sidIds.iterator().next(); } return sidId; } public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException { Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(objectIdentity.getIdentifier(), "Object Identity doesn't provide an identifier"); if (deleteChildren) { ObjectIdentity[] children = findChildren(objectIdentity); if (children != null) { for (int i = 0; i < children.length; i++) { deleteAcl(children[i], true); } } } else { if (!foreignKeysInDatabase) { // We need to perform a manual verification for what a FK would normally do // We generally don't do this, in the interests of deadlock management ObjectIdentity[] children = findChildren(objectIdentity); if (children != null) { throw new ChildrenExistException("Cannot delete '" + objectIdentity + "' (has " + children.length + " children)"); } } } Long oidPrimaryKey = retrieveObjectIdentityPrimaryKey(objectIdentity); // Delete this ACL's ACEs in the acl_entry table deleteEntries(oidPrimaryKey); // Delete this ACL's acl_object_identity row deleteObjectIdentity(oidPrimaryKey); // Clear the cache aclCache.evictFromCache(objectIdentity); } /** * Deletes all ACEs defined in the acl_entry table belonging to the presented ObjectIdentity primary key. * * @param oidPrimaryKey the rows in acl_entry to delete */ protected void deleteEntries(Long oidPrimaryKey) { jdbcTemplate.update(deleteEntryByObjectIdentityForeignKey, new Object[] {oidPrimaryKey}); } /** * Deletes a single row from acl_object_identity that is associated with the presented ObjectIdentity primary key. * *

    * We do not delete any entries from acl_class, even if no classes are using that class any longer. This is a * deadlock avoidance approach. *

    * * @param oidPrimaryKey to delete the acl_object_identity */ protected void deleteObjectIdentity(Long oidPrimaryKey) { // Delete the acl_object_identity row jdbcTemplate.update(deleteObjectIdentityByPrimaryKey, new Object[] {oidPrimaryKey}); } /** * Retrieves the primary key from the acl_object_identity table for the passed ObjectIdentity. Unlike some * other methods in this implementation, this method will NOT create a row (use {@link * #createObjectIdentity(ObjectIdentity, Sid)} instead). * * @param oid to find * * @return the object identity or null if not found */ protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) { try { return new Long(jdbcTemplate.queryForLong(selectObjectIdentityPrimaryKey, new Object[] {oid.getJavaType().getName(), oid.getIdentifier()})); } catch (DataAccessException notFound) { return null; } } /** * This implementation will simply delete all ACEs in the database and recreate them on each invocation of * this method. A more comprehensive implementation might use dirty state checking, or more likely use ORM * capabilities for create, update and delete operations of {@link MutableAcl}. * * @param acl DOCUMENT ME! * * @return DOCUMENT ME! * * @throws NotFoundException DOCUMENT ME! */ public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException { Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier"); // Delete this ACL's ACEs in the acl_entry table deleteEntries(retrieveObjectIdentityPrimaryKey(acl.getObjectIdentity())); // Create this ACL's ACEs in the acl_entry table createEntries(acl); // Change the mutable columns in acl_object_identity updateObjectIdentity(acl); // Clear the cache, including children clearCacheIncludingChildren(acl.getObjectIdentity()); // Retrieve the ACL via superclass (ensures cache registration, proper retrieval etc) return (MutableAcl) super.readAclById(acl.getObjectIdentity()); } private void clearCacheIncludingChildren(ObjectIdentity objectIdentity) { Assert.notNull(objectIdentity, "ObjectIdentity required"); ObjectIdentity[] children = findChildren(objectIdentity); if (children != null) { for (int i = 0; i < children.length; i++) { clearCacheIncludingChildren(children[i]); } } aclCache.evictFromCache(objectIdentity); } /** * Updates an existing acl_object_identity row, with new information presented in the passed MutableAcl * object. Also will create an acl_sid entry if needed for the Sid that owns the MutableAcl. * * @param acl to modify (a row must already exist in acl_object_identity) * * @throws NotFoundException DOCUMENT ME! */ protected void updateObjectIdentity(MutableAcl acl) { Long parentId = null; if (acl.getParentAcl() != null) { Assert.isInstanceOf(ObjectIdentityImpl.class, acl.getParentAcl().getObjectIdentity(), "Implementation only supports ObjectIdentityImpl"); ObjectIdentityImpl oii = (ObjectIdentityImpl) acl.getParentAcl().getObjectIdentity(); parentId = retrieveObjectIdentityPrimaryKey(oii); } Assert.notNull(acl.getOwner(), "Owner is required in this implementation"); Long ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true); int count = jdbcTemplate.update(updateObjectIdentity, new Object[] {parentId, ownerSid, new Boolean(acl.isEntriesInheriting()), acl.getId()}); if (count != 1) { throw new NotFoundException("Unable to locate ACL to update"); } } public void setClassIdentityQuery(String identityQuery) { Assert.hasText(identityQuery, "New identity query is required"); this.classIdentityQuery = identityQuery; } public void setSidIdentityQuery(String identityQuery) { Assert.hasText(identityQuery, "New identity query is required"); this.sidIdentityQuery = identityQuery; } /** * @param foreignKeysInDatabase if false this class will perform additional FK constrain checking, which may * cause deadlocks (the default is true, so deadlocks are avoided but the database is expected to enforce FKs) */ public void setForeignKeysInDatabase(boolean foreignKeysInDatabase) { this.foreignKeysInDatabase = foreignKeysInDatabase; } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/testData.sqlspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/jdbc/testDa0000644000000000000000000000341511623517156030366 0ustar -- Injected into DatabaseSeeder via applicationContext-test.xml (see test case JdbcAclServiceTests) -- DROP TABLE ACL_ENTRY; -- DROP TABLE ACL_OBJECT_IDENTITY; -- DROP TABLE ACL_CLASS; -- DROP TABLE ACL_SID; CREATE TABLE ACL_SID( ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, PRINCIPAL BOOLEAN NOT NULL, SID VARCHAR_IGNORECASE(100) NOT NULL, CONSTRAINT UNIQUE_UK_1 UNIQUE(SID,PRINCIPAL)); CREATE TABLE ACL_CLASS( ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, CLASS VARCHAR_IGNORECASE(100) NOT NULL, CONSTRAINT UNIQUE_UK_2 UNIQUE(CLASS)); INSERT INTO ACL_CLASS VALUES (1, 'sample.contact.Contact'); CREATE TABLE ACL_OBJECT_IDENTITY( ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, OBJECT_ID_CLASS BIGINT NOT NULL, OBJECT_ID_IDENTITY BIGINT NOT NULL, PARENT_OBJECT BIGINT, OWNER_SID BIGINT, ENTRIES_INHERITING BOOLEAN NOT NULL, CONSTRAINT UNIQUE_UK_3 UNIQUE(OBJECT_ID_CLASS,OBJECT_ID_IDENTITY), CONSTRAINT FOREIGN_FK_1 FOREIGN KEY(PARENT_OBJECT)REFERENCES ACL_OBJECT_IDENTITY(ID), CONSTRAINT FOREIGN_FK_2 FOREIGN KEY(OBJECT_ID_CLASS)REFERENCES ACL_CLASS(ID), CONSTRAINT FOREIGN_FK_3 FOREIGN KEY(OWNER_SID)REFERENCES ACL_SID(ID)); CREATE TABLE ACL_ENTRY( ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, ACL_OBJECT_IDENTITY BIGINT NOT NULL, ACE_ORDER INT NOT NULL, SID BIGINT NOT NULL, MASK INTEGER NOT NULL, GRANTING BOOLEAN NOT NULL, AUDIT_SUCCESS BOOLEAN NOT NULL, AUDIT_FAILURE BOOLEAN NOT NULL, CONSTRAINT UNIQUE_UK_4 UNIQUE(ACL_OBJECT_IDENTITY,ACE_ORDER), CONSTRAINT FOREIGN_FK_4 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID), CONSTRAINT FOREIGN_FK_5 FOREIGN KEY(SID) REFERENCES ACL_SID(ID)); ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/IdentityUnavailableException.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/IdentityUna0000644000000000000000000000303411623517156030472 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import org.springframework.security.SpringSecurityException; /** * Thrown if an ACL identity could not be extracted from an object. * * @author Ben Alex * @version $Id$ */ public class IdentityUnavailableException extends SpringSecurityException { //~ Constructors =================================================================================================== /** * Constructs an IdentityUnavailableException with the specified message. * * @param msg the detail message */ public IdentityUnavailableException(String msg) { super(msg); } /** * Constructs an IdentityUnavailableException with the specified message * and root cause. * * @param msg the detail message * @param t root cause */ public IdentityUnavailableException(String msg, Throwable t) { super(msg, t); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/package.htm0000644000000000000000000000020411623517156030413 0ustar Interfaces and shared classes to manage access control lists (ACLs) for domain object instances. ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/AclFormattingUtils.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/AclFormatti0000644000000000000000000001001711623517156030441 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import org.springframework.util.Assert; /** * Utility methods for displaying ACL information. * * @author Ben Alex * @version $Id$ */ public abstract class AclFormattingUtils { public static String demergePatterns(String original, String removeBits) { Assert.notNull(original, "Original string required"); Assert.notNull(removeBits, "Bits To Remove string required"); Assert.isTrue(original.length() == removeBits.length(), "Original and Bits To Remove strings must be identical length"); char[] replacement = new char[original.length()]; for (int i = 0; i < original.length(); i++) { if (removeBits.charAt(i) == Permission.RESERVED_OFF) { replacement[i] = original.charAt(i); } else { replacement[i] = Permission.RESERVED_OFF; } } return new String(replacement); } public static String mergePatterns(String original, String extraBits) { Assert.notNull(original, "Original string required"); Assert.notNull(extraBits, "Extra Bits string required"); Assert.isTrue(original.length() == extraBits.length(), "Original and Extra Bits strings must be identical length"); char[] replacement = new char[extraBits.length()]; for (int i = 0; i < extraBits.length(); i++) { if (extraBits.charAt(i) == Permission.RESERVED_OFF) { replacement[i] = original.charAt(i); } else { replacement[i] = extraBits.charAt(i); } } return new String(replacement); } private static String printBinary(int i, char on, char off) { String s = Integer.toString(i, 2); String pattern = Permission.THIRTY_TWO_RESERVED_OFF; String temp2 = pattern.substring(0, pattern.length() - s.length()) + s; return temp2.replace('0', off).replace('1', on); } /** * Returns a representation of the active bits in the presented mask, with each active bit being denoted by * character "".

    Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}.

    * * @param i the integer bit mask to print the active bits for * * @return a 32-character representation of the bit mask */ public static String printBinary(int i) { return printBinary(i, '*', Permission.RESERVED_OFF); } /** * Returns a representation of the active bits in the presented mask, with each active bit being denoted by * the passed character. *

    * Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. * * @param mask the integer bit mask to print the active bits for * @param code the character to print when an active bit is detected * * @return a 32-character representation of the bit mask */ public static String printBinary(int mask, char code) { Assert.doesNotContain(Character.toString(code), Character.toString(Permission.RESERVED_ON), Permission.RESERVED_ON + " is a reserved character code"); Assert.doesNotContain(Character.toString(code), Character.toString(Permission.RESERVED_OFF), Permission.RESERVED_OFF + " is a reserved character code"); return printBinary(mask, Permission.RESERVED_ON, Permission.RESERVED_OFF).replace(Permission.RESERVED_ON, code); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/AuditableAcl.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/AuditableAc0000644000000000000000000000200311623517156030366 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; /** * A mutable ACL that provides audit capabilities. * * @author Ben Alex * @version $Id$ * */ public interface AuditableAcl extends MutableAcl { //~ Methods ======================================================================================================== void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure); } spring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/0000755000000000000000000000000011623517156027561 5ustar ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/AuditLogger.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/Audi0000644000000000000000000000204111623517156030363 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.domain; import org.springframework.security.acls.AccessControlEntry; /** * Used by AclImpl to log audit events. * * @author Ben Alex * @version $Id$ * */ public interface AuditLogger { //~ Methods ======================================================================================================== void logIfNeeded(boolean granted, AccessControlEntry ace); } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/BasePermission.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/Base0000644000000000000000000000475611623517156030372 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.domain; import org.springframework.security.acls.Permission; /** * A set of standard permissions. * *

    * You may subclass this class to add additional permissions, or use this class as a guide * for creating your own permission classes. *

    * * @author Ben Alex * @version $Id$ */ public class BasePermission extends AbstractPermission { public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1 public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2 public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4 public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8 public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16 protected static DefaultPermissionFactory defaultPermissionFactory = new DefaultPermissionFactory(); /** * Registers the public static permissions defined on this class. This is mandatory so * that the static methods will operate correctly. */ static { registerPermissionsFor(BasePermission.class); } protected BasePermission(int mask, char code) { super(mask, code); } protected final static void registerPermissionsFor(Class subClass) { defaultPermissionFactory.registerPublicPermissions(subClass); } public final static Permission buildFromMask(int mask) { return defaultPermissionFactory.buildFromMask(mask); } public final static Permission[] buildFromMask(int[] masks) { return defaultPermissionFactory.buildFromMask(masks); } public final static Permission buildFromName(String name) { return defaultPermissionFactory.buildFromName(name); } public final static Permission[] buildFromName(String[] names) { return defaultPermissionFactory.buildFromName(names); } }././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/AclAuthorizationStrategy.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/AclA0000644000000000000000000000247411623517156030313 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.domain; import org.springframework.security.acls.Acl; /** * Strategy used by {@link AclImpl} to determine whether a principal is permitted to call * adminstrative methods on the AclImpl. * * @author Ben Alex * @version $Id$ */ public interface AclAuthorizationStrategy { //~ Static fields/initializers ===================================================================================== int CHANGE_OWNERSHIP = 0; int CHANGE_AUDITING = 1; int CHANGE_GENERAL = 2; //~ Methods ======================================================================================================== void securityCheck(Acl acl, int changeType); } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/DefaultPermissionFactory.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/Defa0000644000000000000000000001113011623517156030337 0ustar package org.springframework.security.acls.domain; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import org.springframework.security.acls.Permission; import org.springframework.security.acls.jdbc.LookupStrategy; import org.springframework.util.Assert; /** * Default implementation of {@link PermissionFactory}. * *

    * Generally this class will be used by a {@link Permission} instance, as opposed to being dependency * injected into a {@link LookupStrategy} or similar. Nevertheless, the latter mode of operation is * fully supported (in which case your {@link Permission} implementations probably should extend * {@link AbstractPermission} instead of {@link AbstractRegisteredPermission}). *

    * * @author Ben Alex * @since 2.0.3 * */ public class DefaultPermissionFactory implements PermissionFactory { private Map registeredPermissionsByInteger = new HashMap(); private Map registeredPermissionsByName = new HashMap(); /** * Permit registration of a {@link DefaultPermissionFactory} class. The class must provide * public static fields of type {@link Permission} to represent the possible permissions. * * @param clazz a {@link Permission} class with public static fields to register */ public void registerPublicPermissions(Class clazz) { Assert.notNull(clazz, "Class required"); Assert.isAssignable(Permission.class, clazz); Field[] fields = clazz.getFields(); for (int i = 0; i < fields.length; i++) { try { Object fieldValue = fields[i].get(null); if (Permission.class.isAssignableFrom(fieldValue.getClass())) { // Found a Permission static field Permission perm = (Permission) fieldValue; String permissionName = fields[i].getName(); registerPermission(perm, permissionName); } } catch (Exception ignore) {} } } public void registerPermission(Permission perm, String permissionName) { Assert.notNull(perm, "Permission required"); Assert.hasText(permissionName, "Permission name required"); Integer mask = new Integer(perm.getMask()); // Ensure no existing Permission uses this integer or code Assert.isTrue(!registeredPermissionsByInteger.containsKey(mask), "An existing Permission already provides mask " + mask); Assert.isTrue(!registeredPermissionsByName.containsKey(permissionName), "An existing Permission already provides name '" + permissionName + "'"); // Register the new Permission registeredPermissionsByInteger.put(mask, perm); registeredPermissionsByName.put(permissionName, perm); } public Permission buildFromMask(int mask) { if (registeredPermissionsByInteger.containsKey(new Integer(mask))) { // The requested mask has an exactly match against a statically-defined Permission, so return it return (Permission) registeredPermissionsByInteger.get(new Integer(mask)); } // To get this far, we have to use a CumulativePermission CumulativePermission permission = new CumulativePermission(); for (int i = 0; i < 32; i++) { int permissionToCheck = 1 << i; if ((mask & permissionToCheck) == permissionToCheck) { Permission p = (Permission) registeredPermissionsByInteger.get(new Integer(permissionToCheck)); Assert.state(p != null, "Mask " + permissionToCheck + " does not have a corresponding static Permission"); permission.set(p); } } return permission; } public Permission[] buildFromMask(int[] masks) { if ((masks == null) || (masks.length == 0)) { return new Permission[0]; } Permission[] permissions = new Permission[masks.length]; for (int i = 0; i < masks.length; i++) { permissions[i] = buildFromMask(masks[i]); } return permissions; } public Permission buildFromName(String name) { Assert.isTrue(registeredPermissionsByName.containsKey(name), "Unknown permission '" + name + "'"); return (Permission) registeredPermissionsByName.get(name); } public Permission[] buildFromName(String[] names) { if ((names == null) || (names.length == 0)) { return new Permission[0]; } Permission[] permissions = new Permission[names.length]; for (int i = 0; i < names.length; i++) { permissions[i] = buildFromName(names[i]); } return permissions; } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/PermissionFactory.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/Perm0000644000000000000000000000111411623517156030404 0ustar package org.springframework.security.acls.domain; import org.springframework.security.acls.Permission; /** * Provides a simple mechanism to retrieve {@link Permission} instances from integer masks. * * @author Ben Alex * @since 2.0.3 * */ public interface PermissionFactory { /** * Dynamically creates a CumulativePermission or BasePermission representing the * active bits in the passed mask. * * @param mask to build * * @return a Permission representing the requested object */ public abstract Permission buildFromMask(int mask); }././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/pack0000644000000000000000000000014311623517156030420 0ustar Basic implementation of access control lists (ACLs) interfaces. ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/AclA0000644000000000000000000001271611623517156030313 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.domain; import org.springframework.security.AccessDeniedException; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; import org.springframework.security.acls.Acl; import org.springframework.security.acls.Permission; import org.springframework.security.acls.sid.PrincipalSid; import org.springframework.security.acls.sid.Sid; import org.springframework.security.acls.sid.SidRetrievalStrategy; import org.springframework.security.acls.sid.SidRetrievalStrategyImpl; import org.springframework.security.context.SecurityContextHolder; import org.springframework.util.Assert; /** * Default implementation of {@link AclAuthorizationStrategy}.

    Permission will be granted provided the current * principal is either the owner (as defined by the ACL), has {@link BasePermission#ADMINISTRATION} (as defined by the * ACL and via a {@link Sid} retrieved for the current principal via {@link #sidRetrievalStrategy}), or if the current * principal holds the relevant system-wide {@link GrantedAuthority} and injected into the constructor.

    * * @author Ben Alex * @version $Id$ */ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy { //~ Instance fields ================================================================================================ private GrantedAuthority gaGeneralChanges; private GrantedAuthority gaModifyAuditing; private GrantedAuthority gaTakeOwnership; private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); //~ Constructors =================================================================================================== /** * Constructor. The only mandatory parameter relates to the system-wide {@link GrantedAuthority} instances that * can be held to always permit ACL changes. * * @param auths an array of GrantedAuthoritys that have * special permissions (index 0 is the authority needed to change * ownership, index 1 is the authority needed to modify auditing details, * index 2 is the authority needed to change other ACL and ACE details) (required) */ public AclAuthorizationStrategyImpl(GrantedAuthority[] auths) { Assert.notEmpty(auths, "GrantedAuthority[] with three elements required"); Assert.isTrue(auths.length == 3, "GrantedAuthority[] with three elements required"); this.gaTakeOwnership = auths[0]; this.gaModifyAuditing = auths[1]; this.gaGeneralChanges = auths[2]; } //~ Methods ======================================================================================================== public void securityCheck(Acl acl, int changeType) { if ((SecurityContextHolder.getContext() == null) || (SecurityContextHolder.getContext().getAuthentication() == null) || !SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) { throw new AccessDeniedException("Authenticated principal required to operate with ACLs"); } Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // Check if authorized by virtue of ACL ownership Sid currentUser = new PrincipalSid(authentication); if (currentUser.equals(acl.getOwner()) && ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) { return; } // Not authorized by ACL ownership; try via adminstrative permissions GrantedAuthority requiredAuthority = null; if (changeType == CHANGE_AUDITING) { requiredAuthority = this.gaModifyAuditing; } else if (changeType == CHANGE_GENERAL) { requiredAuthority = this.gaGeneralChanges; } else if (changeType == CHANGE_OWNERSHIP) { requiredAuthority = this.gaTakeOwnership; } else { throw new IllegalArgumentException("Unknown change type"); } // Iterate this principal's authorities to determine right GrantedAuthority[] auths = authentication.getAuthorities(); for (int i = 0; i < auths.length; i++) { if (requiredAuthority.equals(auths[i])) { return; } } // Try to get permission via ACEs within the ACL Sid[] sids = sidRetrievalStrategy.getSids(authentication); if (acl.isGranted(new Permission[] {BasePermission.ADMINISTRATION}, sids, false)) { return; } throw new AccessDeniedException( "Principal does not have required ACL permissions to perform requested operation"); } public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); this.sidRetrievalStrategy = sidRetrievalStrategy; } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/AclImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/AclI0000644000000000000000000004216211623517156030321 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.domain; import java.io.Serializable; import java.util.Iterator; import java.util.List; import java.util.Vector; import org.springframework.security.acls.AccessControlEntry; import org.springframework.security.acls.Acl; import org.springframework.security.acls.AuditableAcl; import org.springframework.security.acls.MutableAcl; import org.springframework.security.acls.NotFoundException; import org.springframework.security.acls.OwnershipAcl; import org.springframework.security.acls.Permission; import org.springframework.security.acls.UnloadedSidException; import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.sid.Sid; import org.springframework.util.Assert; /** * Base implementation of Acl. * * @author Ben Alex * @version $Id */ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { //~ Instance fields ================================================================================================ private Acl parentAcl; private transient AclAuthorizationStrategy aclAuthorizationStrategy; private transient AuditLogger auditLogger; private List aces = new Vector(); private ObjectIdentity objectIdentity; private Serializable id; private Sid owner; // OwnershipAcl private Sid[] loadedSids = null; // includes all SIDs the WHERE clause covered, even if there was no ACE for a SID private boolean entriesInheriting = true; //~ Constructors =================================================================================================== /** * Minimal constructor, which should be used {@link * org.springframework.security.acls.MutableAclService#createAcl(ObjectIdentity)}. * * @param objectIdentity the object identity this ACL relates to (required) * @param id the primary key assigned to this ACL (required) * @param aclAuthorizationStrategy authorization strategy (required) * @param auditLogger audit logger (required) */ public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) { Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(id, "Id required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); Assert.notNull(auditLogger, "AuditLogger required"); this.objectIdentity = objectIdentity; this.id = id; this.aclAuthorizationStrategy = aclAuthorizationStrategy; this.auditLogger = auditLogger; } /** * Full constructor, which should be used by persistence tools that do not * provide field-level access features. * * @param objectIdentity the object identity this ACL relates to (required) * @param id the primary key assigned to this ACL (required) * @param aclAuthorizationStrategy authorization strategy (required) * @param auditLogger audit logger (required) * @param parentAcl the parent (may be null) * @param loadedSids the loaded SIDs if only a subset were loaded (may be * null) * @param entriesInheriting if ACEs from the parent should inherit into * this ACL * @param owner the owner (required) */ public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger, Acl parentAcl, Sid[] loadedSids, boolean entriesInheriting, Sid owner) { Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(id, "Id required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); Assert.notNull(owner, "Owner required"); Assert.notNull(auditLogger, "AuditLogger required"); this.objectIdentity = objectIdentity; this.id = id; this.aclAuthorizationStrategy = aclAuthorizationStrategy; this.auditLogger = auditLogger; this.parentAcl = parentAcl; // may be null this.loadedSids = loadedSids; // may be null this.entriesInheriting = entriesInheriting; this.owner = owner; } /** * Private no-argument constructor for use by reflection-based persistence * tools along with field-level access. */ private AclImpl() {} //~ Methods ======================================================================================================== private void verifyAceIndexExists(int aceIndex) { if (aceIndex < 0) { throw new NotFoundException("aceIndex must be greater than or equal to zero"); } if (aceIndex > this.aces.size()) { throw new NotFoundException("aceIndex must correctly refer to an index of the AccessControlEntry collection"); } } public void deleteAce(int aceIndex) throws NotFoundException { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); verifyAceIndexExists(aceIndex); synchronized (aces) { this.aces.remove(aceIndex); } } public AccessControlEntry[] getEntries() { // Can safely return AccessControlEntry directly, as they're immutable outside the ACL package return (AccessControlEntry[]) aces.toArray(new AccessControlEntry[] {}); } public Serializable getId() { return this.id; } public ObjectIdentity getObjectIdentity() { return objectIdentity; } public Sid getOwner() { return this.owner; } public Acl getParentAcl() { return parentAcl; } public void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) throws NotFoundException { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); Assert.notNull(permission, "Permission required"); Assert.notNull(sid, "Sid required"); if (atIndexLocation < 0) { throw new NotFoundException("atIndexLocation must be greater than or equal to zero"); } if (atIndexLocation > this.aces.size()) { throw new NotFoundException("atIndexLocation must be less than or equal to the size of the AccessControlEntry collection"); } AccessControlEntryImpl ace = new AccessControlEntryImpl(null, this, sid, permission, granting, false, false); synchronized (aces) { this.aces.add(atIndexLocation, ace); } } public boolean isEntriesInheriting() { return entriesInheriting; } /** * Determines authorization. The order of the permission and sid arguments is * extremely important! The method will iterate through each of the permissions in the order * specified. For each iteration, all of the sids will be considered, again in the order they are * presented. A search will then be performed for the first {@link AccessControlEntry} object that directly * matches that permission:sid combination. When the first full match is found (ie an ACE * that has the SID currently being searched for and the exact permission bit mask being search for), the grant or * deny flag for that ACE will prevail. If the ACE specifies to grant access, the method will return * true. If the ACE specifies to deny access, the loop will stop and the next permission * iteration will be performed. If each permission indicates to deny access, the first deny ACE found will be * considered the reason for the failure (as it was the first match found, and is therefore the one most logically * requiring changes - although not always). If absolutely no matching ACE was found at all for any permission, * the parent ACL will be tried (provided that there is a parent and {@link #isEntriesInheriting()} is * true. The parent ACL will also scan its parent and so on. If ultimately no matching ACE is found, * a NotFoundException will be thrown and the caller will need to decide how to handle the permission * check. Similarly, if any of the SID arguments presented to the method were not loaded by the ACL, * UnloadedSidException will be thrown. * * @param permission the exact permissions to scan for (order is important) * @param sids the exact SIDs to scan for (order is important) * @param administrativeMode if true denotes the query is for administrative purposes and no auditing * will be undertaken * * @return true if one of the permissions has been granted, false if one of the * permissions has been specifically revoked * * @throws NotFoundException if an exact ACE for one of the permission bit masks and SID combination could not be * found * @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the ACL was only loaded for a * subset of SIDs */ public boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode) throws NotFoundException, UnloadedSidException { Assert.notEmpty(permission, "Permissions required"); Assert.notEmpty(sids, "SIDs required"); if (!this.isSidLoaded(sids)) { throw new UnloadedSidException("ACL was not loaded for one or more SID"); } AccessControlEntry firstRejection = null; for (int i = 0; i < permission.length; i++) { for (int x = 0; x < sids.length; x++) { // Attempt to find exact match for this permission mask and SID Iterator acesIterator = aces.iterator(); boolean scanNextSid = true; while (acesIterator.hasNext()) { AccessControlEntry ace = (AccessControlEntry) acesIterator.next(); if ((ace.getPermission().getMask() == permission[i].getMask()) && ace.getSid().equals(sids[x])) { // Found a matching ACE, so its authorization decision will prevail if (ace.isGranting()) { // Success if (!administrativeMode) { auditLogger.logIfNeeded(true, ace); } return true; } else { // Failure for this permission, so stop search // We will see if they have a different permission // (this permission is 100% rejected for this SID) if (firstRejection == null) { // Store first rejection for auditing reasons firstRejection = ace; } scanNextSid = false; // helps break the loop break; // exit "aceIterator" while loop } } } if (!scanNextSid) { break; // exit SID for loop (now try next permission) } } } if (firstRejection != null) { // We found an ACE to reject the request at this point, as no // other ACEs were found that granted a different permission if (!administrativeMode) { auditLogger.logIfNeeded(false, firstRejection); } return false; } // No matches have been found so far if (isEntriesInheriting() && (parentAcl != null)) { // We have a parent, so let them try to find a matching ACE return parentAcl.isGranted(permission, sids, false); } else { // We either have no parent, or we're the uppermost parent throw new NotFoundException("Unable to locate a matching ACE for passed permissions and SIDs"); } } public boolean isSidLoaded(Sid[] sids) { // If loadedSides is null, this indicates all SIDs were loaded // Also return true if the caller didn't specify a SID to find if ((this.loadedSids == null) || (sids == null) || (sids.length == 0)) { return true; } // This ACL applies to a SID subset only. Iterate to check it applies. for (int i = 0; i < sids.length; i++) { boolean found = false; for (int y = 0; y < this.loadedSids.length; y++) { if (sids[i].equals(this.loadedSids[y])) { // this SID is OK found = true; break; // out of loadedSids for loop } } if (!found) { return false; } } return true; } public void setEntriesInheriting(boolean entriesInheriting) { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); this.entriesInheriting = entriesInheriting; } public void setOwner(Sid newOwner) { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_OWNERSHIP); Assert.notNull(newOwner, "Owner required"); this.owner = newOwner; } public void setParent(Acl newParent) { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); Assert.isTrue(newParent == null || !newParent.equals(this), "Cannot be the parent of yourself"); this.parentAcl = newParent; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("AclImpl["); sb.append("id: ").append(this.id).append("; "); sb.append("objectIdentity: ").append(this.objectIdentity).append("; "); sb.append("owner: ").append(this.owner).append("; "); Iterator iterator = this.aces.iterator(); int count = 0; while (iterator.hasNext()) { count++; if (count == 1) { sb.append("\r\n"); } sb.append(iterator.next().toString()).append("\r\n"); } if (count == 0) { sb.append("no ACEs; "); } sb.append("inheriting: ").append(this.entriesInheriting).append("; "); sb.append("parent: ").append((this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity().toString()); sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy).append("; "); sb.append("auditLogger: ").append(this.auditLogger); sb.append("]"); return sb.toString(); } public void updateAce(int aceIndex, Permission permission) throws NotFoundException { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); verifyAceIndexExists(aceIndex); synchronized (aces) { AccessControlEntryImpl ace = (AccessControlEntryImpl) aces.get(aceIndex); ace.setPermission(permission); } } public void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure) { aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_AUDITING); verifyAceIndexExists(aceIndex); synchronized (aces) { AccessControlEntryImpl ace = (AccessControlEntryImpl) aces.get(aceIndex); ace.setAuditSuccess(auditSuccess); ace.setAuditFailure(auditFailure); } } public boolean equals(Object obj) { if (obj instanceof AclImpl) { AclImpl rhs = (AclImpl) obj; if (this.aces.equals(rhs.aces)) { if ((this.parentAcl == null && rhs.parentAcl == null) || (this.parentAcl.equals(rhs.parentAcl))) { if ((this.objectIdentity == null && rhs.objectIdentity == null) || (this.objectIdentity.equals(rhs.objectIdentity))) { if ((this.id == null && rhs.id == null) || (this.id.equals(rhs.id))) { if ((this.owner == null && rhs.owner == null) || this.owner.equals(rhs.owner)) { if (this.entriesInheriting == rhs.entriesInheriting) { if ((this.loadedSids == null && rhs.loadedSids == null)) { return true; } if (this.loadedSids.length == rhs.loadedSids.length) { for (int i = 0; i < this.loadedSids.length; i++) { if (!this.loadedSids[i].equals(rhs.loadedSids[i])) { return false; } } return true; } } } } } } } } return false; } } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/AccessControlEntryImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/Acce0000644000000000000000000001265511623517156030350 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.domain; import org.springframework.security.acls.AccessControlEntry; import org.springframework.security.acls.Acl; import org.springframework.security.acls.AuditableAccessControlEntry; import org.springframework.security.acls.Permission; import org.springframework.security.acls.sid.Sid; import org.springframework.util.Assert; import java.io.Serializable; /** * An immutable default implementation of AccessControlEntry. * * @author Ben Alex * @version $Id$ */ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAccessControlEntry { //~ Instance fields ================================================================================================ private Acl acl; private Permission permission; private Serializable id; private Sid sid; private boolean auditFailure = false; private boolean auditSuccess = false; private boolean granting; //~ Constructors =================================================================================================== public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, Permission permission, boolean granting, boolean auditSuccess, boolean auditFailure) { Assert.notNull(acl, "Acl required"); Assert.notNull(sid, "Sid required"); Assert.notNull(permission, "Permission required"); this.id = id; this.acl = acl; // can be null this.sid = sid; this.permission = permission; this.granting = granting; this.auditSuccess = auditSuccess; this.auditFailure = auditFailure; } //~ Methods ======================================================================================================== public boolean equals(Object arg0) { if (!(arg0 instanceof AccessControlEntryImpl)) { return false; } AccessControlEntryImpl rhs = (AccessControlEntryImpl) arg0; if (this.acl == null) { if (rhs.getAcl() != null) { return false; } // Both this.acl and rhs.acl are null and thus equal } else { // this.acl is non-null if (rhs.getAcl() == null) { return false; } // Both this.acl and rhs.acl are non-null, so do a comparison if (this.acl.getObjectIdentity() == null) { if (rhs.acl.getObjectIdentity() != null) { return false; } // Both this.acl and rhs.acl are null and thus equal } else { // Both this.acl.objectIdentity and rhs.acl.objectIdentity are non-null if (!this.acl.getObjectIdentity().equals(rhs.getAcl().getObjectIdentity())) { return false; } } } if (this.id == null) { if (rhs.id != null) { return false; } // Both this.id and rhs.id are null and thus equal } else { // this.id is non-null if (rhs.id == null) { return false; } // Both this.id and rhs.id are non-null if (!this.id.equals(rhs.id)) { return false; } } if ((this.auditFailure != rhs.isAuditFailure()) || (this.auditSuccess != rhs.isAuditSuccess()) || (this.granting != rhs.isGranting()) || !this.permission.equals(rhs.getPermission()) || !this.sid.equals(rhs.getSid())) { return false; } return true; } public Acl getAcl() { return acl; } public Serializable getId() { return id; } public Permission getPermission() { return permission; } public Sid getSid() { return sid; } public boolean isAuditFailure() { return auditFailure; } public boolean isAuditSuccess() { return auditSuccess; } public boolean isGranting() { return granting; } void setAuditFailure(boolean auditFailure) { this.auditFailure = auditFailure; } void setAuditSuccess(boolean auditSuccess) { this.auditSuccess = auditSuccess; } void setPermission(Permission permission) { Assert.notNull(permission, "Permission required"); this.permission = permission; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("AccessControlEntryImpl["); sb.append("id: ").append(this.id).append("; "); sb.append("granting: ").append(this.granting).append("; "); sb.append("sid: ").append(this.sid).append("; "); sb.append("permission: ").append(this.permission).append("; "); sb.append("auditSuccess: ").append(this.auditSuccess).append("; "); sb.append("auditFailure: ").append(this.auditFailure); sb.append("]"); return sb.toString(); } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/CumulativePermission.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/Cumu0000644000000000000000000000354111623517156030420 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.domain; import org.springframework.security.acls.AclFormattingUtils; import org.springframework.security.acls.Permission; /** * Represents a Permission that is constructed at runtime from other permissions. * *

    Methods return this, in order to facilitate method chaining.

    * * @author Ben Alex * @version $Id$ */ public class CumulativePermission extends AbstractPermission { private String pattern = THIRTY_TWO_RESERVED_OFF; public CumulativePermission() { super(0, ' '); } public CumulativePermission clear(Permission permission) { this.mask &= ~permission.getMask(); this.pattern = AclFormattingUtils.demergePatterns(this.pattern, permission.getPattern()); return this; } public CumulativePermission clear() { this.mask = 0; this.pattern = THIRTY_TWO_RESERVED_OFF; return this; } public CumulativePermission set(Permission permission) { this.mask |= permission.getMask(); this.pattern = AclFormattingUtils.mergePatterns(this.pattern, permission.getPattern()); return this; } public String getPattern() { return this.pattern; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/ConsoleAuditLogger.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/Cons0000644000000000000000000000323711623517156030413 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls.domain; import org.springframework.security.acls.AccessControlEntry; import org.springframework.security.acls.AuditableAccessControlEntry; import org.springframework.util.Assert; /** * A bsaic implementation of {@link AuditLogger}. * * @author Ben Alex * @version $Id$ */ public class ConsoleAuditLogger implements AuditLogger { //~ Methods ======================================================================================================== public void logIfNeeded(boolean granted, AccessControlEntry ace) { Assert.notNull(ace, "AccessControlEntry required"); if (ace instanceof AuditableAccessControlEntry) { AuditableAccessControlEntry auditableAce = (AuditableAccessControlEntry) ace; if (granted && auditableAce.isAuditSuccess()) { System.out.println("GRANTED due to ACE: " + ace); } else if (!granted && auditableAce.isAuditFailure()) { System.out.println("DENIED due to ACE: " + ace); } } } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/AbstractPermission.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/domain/Abst0000644000000000000000000000303611623517156030377 0ustar package org.springframework.security.acls.domain; import org.springframework.security.acls.AclFormattingUtils; import org.springframework.security.acls.Permission; /** * Provides an abstract superclass for {@link Permission} implementations. * * @author Ben Alex * @since 2.0.3 * @see AbstractRegisteredPermission * */ public abstract class AbstractPermission implements Permission { //~ Instance fields ================================================================================================ protected char code; protected int mask; //~ Constructors =================================================================================================== protected AbstractPermission(int mask, char code) { this.mask = mask; this.code = code; } //~ Methods ======================================================================================================== public final boolean equals(Object arg0) { if (arg0 == null) { return false; } if (!(arg0 instanceof Permission)) { return false; } Permission rhs = (Permission) arg0; return (this.mask == rhs.getMask()); } public final int getMask() { return mask; } public String getPattern() { return AclFormattingUtils.printBinary(mask, code); } public final String toString() { return this.getClass().getSimpleName() + "[" + getPattern() + "=" + mask + "]"; } public final int hashCode() { return this.mask; } } spring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/Acl.java0000644000000000000000000002125311623517156027657 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.sid.Sid; import java.io.Serializable; /** * Represents an access control list (ACL) for a domain object. * *

    * An Acl represents all ACL entries for a given domain object. In * order to avoid needing references to the domain object itself, this * interface handles indirection between a domain object and an ACL object * identity via the {@link * org.springframework.security.acls.objectidentity.ObjectIdentity} interface. *

    * *

    * Implementing classes may elect to return instances that represent * {@link org.springframework.security.acls.Permission} information for either * some OR all {@link org.springframework.security.acls.sid.Sid} * instances. Therefore, an instance may NOT necessarily contain ALL Sids * for a given domain object. *

    * * @author Ben Alex * @version $Id$ */ public interface Acl extends Serializable { /** * Returns all of the entries represented by the present Acl. Entries associated with * the Acl parents are not returned. * *

    This method is typically used for administrative purposes.

    * *

    The order that entries appear in the array is important for methods declared in the * {@link MutableAcl} interface. Furthermore, some implementations MAY use ordering as * part of advanced permission checking.

    * *

    Do NOT use this method for making authorization decisions. Instead use {@link * #isGranted(Permission[], Sid[], boolean)}.

    * *

    This method must operate correctly even if the Acl only represents a subset of * Sids. The caller is responsible for correctly handling the result if only a subset of * Sids is represented.

    * * @return the list of entries represented by the Acl, or null if there are * no entries presently associated with this Acl. */ AccessControlEntry[] getEntries(); /** * Obtains the domain object this Acl provides entries for. This is immutable once an * Acl is created. * * @return the object identity (never null) */ ObjectIdentity getObjectIdentity(); /** * Determines the owner of the Acl. The meaning of ownership varies by implementation and is * unspecified. * * @return the owner (may be null if the implementation does not use ownership concepts) */ Sid getOwner(); /** * A domain object may have a parent for the purpose of ACL inheritance. If there is a parent, its ACL can * be accessed via this method. In turn, the parent's parent (grandparent) can be accessed and so on. * *

    This method solely represents the presence of a navigation hierarchy between the parent Acl and this * Acl. For actual inheritance to take place, the {@link #isEntriesInheriting()} must also be * true.

    * *

    This method must operate correctly even if the Acl only represents a subset of * Sids. The caller is responsible for correctly handling the result if only a subset of * Sids is represented.

    * * @return the parent Acl (may be null if this Acl does not have a parent) */ Acl getParentAcl(); /** * Indicates whether the ACL entries from the {@link #getParentAcl()} should flow down into the current * Acl.

    The mere link between an Acl and a parent Acl on its own * is insufficient to cause ACL entries to inherit down. This is because a domain object may wish to have entirely * independent entries, but maintain the link with the parent for navigation purposes. Thus, this method denotes * whether or not the navigation relationship also extends to the actual inheritance of entries.

    * * @return true if parent ACL entries inherit into the current Acl */ boolean isEntriesInheriting(); /** * This is the actual authorization logic method, and must be used whenever ACL authorization decisions are * required. * *

    An array of Sids are presented, representing security identifies of the current * principal. In addition, an array of Permissions is presented which will have one or more bits set * in order to indicate the permissions needed for an affirmative authorization decision. An array is presented * because holding any of the Permissions inside the array will be sufficient for an * affirmative authorization.

    * *

    The actual approach used to make authorization decisions is left to the implementation and is not * specified by this interface. For example, an implementation MAY search the current ACL in the order * the ACL entries have been stored. If a single entry is found that has the same active bits as are shown in a * passed Permission, that entry's grant or deny state may determine the authorization decision. If * the case of a deny state, the deny decision will only be relevant if all other Permissions passed * in the array have also been unsuccessfully searched. If no entry is found that match the bits in the current * ACL, provided that {@link #isEntriesInheriting()} is true, the authorization decision may be * passed to the parent ACL. If there is no matching entry, the implementation MAY throw an exception, or make a * predefined authorization decision.

    * *

    This method must operate correctly even if the Acl only represents a subset of Sids, * although the implementation is permitted to throw one of the signature-defined exceptions if the method * is called requesting an authorization decision for a {@link Sid} that was never loaded in this Acl. *

    * * @param permission the permission or permissions required (at least one entry required) * @param sids the security identities held by the principal (at least one entry required) * @param administrativeMode if true denotes the query is for administrative purposes and no logging * or auditing (if supported by the implementation) should be undertaken * * @return true if authorization is granted * * @throws NotFoundException MUST be thrown if an implementation cannot make an authoritative authorization * decision, usually because there is no ACL information for this particular permission and/or SID * @throws UnloadedSidException thrown if the Acl does not have details for one or more of the * Sids passed as arguments */ boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode) throws NotFoundException, UnloadedSidException; /** * For efficiency reasons an Acl may be loaded and not contain entries for every * Sid in the system. If an Acl has been loaded and does not represent every * Sid, all methods of the Acl can only be used within the limited scope of the * Sid instances it actually represents. *

    * It is normal to load an Acl for only particular Sids if read-only authorization * decisions are being made. However, if user interface reporting or modification of Acls are * desired, an Acl should be loaded with all Sids. This method denotes whether or * not the specified Sids have been loaded or not. *

    * * @param sids one or more security identities the caller is interest in knowing whether this Sid * supports * * @return true if every passed Sid is represented by this Acl instance */ boolean isSidLoaded(Sid[] sids); } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/MutableAcl.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/MutableAcl.0000644000000000000000000000405511623517156030330 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import java.io.Serializable; import org.springframework.security.acls.sid.Sid; /** * A mutable Acl. * *

    * A mutable ACL must ensure that appropriate security checks are performed * before allowing access to its methods. *

    * * @author Ben Alex * @version $Id$ */ public interface MutableAcl extends Acl { //~ Methods ======================================================================================================== void deleteAce(int aceIndex) throws NotFoundException; /** * Obtains an identifier that represents this MutableAcl. * * @return the identifier, or null if unsaved */ Serializable getId(); void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) throws NotFoundException; /** * Changes the present owner to a different owner. * * @param newOwner the new owner (mandatory; cannot be null) */ void setOwner(Sid newOwner); /** * Change the value returned by {@link Acl#isEntriesInheriting()}. * * @param entriesInheriting the new value */ void setEntriesInheriting(boolean entriesInheriting); /** * Changes the parent of this ACL. * * @param newParent the new parent */ void setParent(Acl newParent); void updateAce(int aceIndex, Permission permission) throws NotFoundException; } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/MutableAclService.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/MutableAclS0000644000000000000000000000457011623517156030377 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import org.springframework.security.acls.objectidentity.ObjectIdentity; /** * Provides support for creating and storing Acl instances. * * @author Ben Alex * @version $Id$ */ public interface MutableAclService extends AclService { //~ Methods ======================================================================================================== /** * Creates an empty Acl object in the database. It will have no entries. The returned object * will then be used to add entries. * * @param objectIdentity the object identity to create * * @return an ACL object with its ID set * * @throws AlreadyExistsException if the passed object identity already has a record */ MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException; /** * Removes the specified entry from the database. * * @param objectIdentity the object identity to remove * @param deleteChildren whether to cascade the delete to children * * @throws ChildrenExistException if the deleteChildren argument was false but children exist */ void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException; /** * Changes an existing Acl in the database. * * @param acl to modify * * @return DOCUMENT ME! * * @throws NotFoundException if the relevant record could not be found (did you remember to use {@link * #createAcl(ObjectIdentity)} to create the object, rather than creating it with the new * keyword?) */ MutableAcl updateAcl(MutableAcl acl) throws NotFoundException; } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/AuditableAccessControlEntry.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/AuditableAc0000644000000000000000000000201011623517156030364 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; /** * Represents an ACE that provides auditing information. * * @author Ben Alex * @version $Id$ * */ public interface AuditableAccessControlEntry extends AccessControlEntry { //~ Methods ======================================================================================================== boolean isAuditFailure(); boolean isAuditSuccess(); } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/Permission.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/Permission.0000644000000000000000000000457511623517156030456 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import java.io.Serializable; /** * Represents a permission granted to a {@link org.springframework.security.acls.sid.Sid Sid} for a given domain object. * * @author Ben Alex * @version $Id$ */ public interface Permission extends Serializable { //~ Static fields/initializers ===================================================================================== char RESERVED_ON = '~'; char RESERVED_OFF = '.'; String THIRTY_TWO_RESERVED_OFF = "................................"; //~ Methods ======================================================================================================== /** * Returns the bits that represents the permission. * * @return the bits that represent the permission */ int getMask(); /** * Returns a 32-character long bit pattern String representing this permission. *

    * Implementations are free to format the pattern as they see fit, although under no circumstances may * {@link #RESERVED_OFF} or {@link #RESERVED_ON} be used within the pattern. An exemption is in the case of * {@link #RESERVED_OFF} which is used to denote a bit that is off (clear). * Implementations may also elect to use {@link #RESERVED_ON} internally for computation purposes, * although this method may not return any String containing {@link #RESERVED_ON}. *

    *

    The returned String must be 32 characters in length.

    *

    This method is only used for user interface and logging purposes. It is not used in any permission * calculations. Therefore, duplication of characters within the output is permitted.

    * * @return a 32-character bit pattern */ String getPattern(); } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/NotFoundException.javaspring-security-2.0.7.RELEASE/dist/spring-security-acl/org/springframework/security/acls/NotFoundExc0000644000000000000000000000272511623517156030437 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.acls; import org.springframework.security.SpringSecurityException; /** * Thrown if an ACL-related object cannot be found. * * @author Ben Alex * @version $Id$ */ public class NotFoundException extends SpringSecurityException { //~ Constructors =================================================================================================== /** * Constructs an NotFoundException with the specified message. * * @param msg the detail message */ public NotFoundException(String msg) { super(msg); } /** * Constructs an NotFoundException with the specified message * and root cause. * * @param msg the detail message * @param t root cause */ public NotFoundException(String msg, Throwable t) { super(msg, t); } } spring-security-2.0.7.RELEASE/dist/spring-security-taglibs/0000755000000000000000000000000011766764113020405 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-taglibs/META-INF/0000755000000000000000000000000011623522006021526 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-taglibs/META-INF/security.tld0000644000000000000000000001165711623517156024126 0ustar 1.0 1.2 security http://www.springframework.org/security/tags Spring Security Authorization Tag Library $Id$ authorize org.springframework.security.taglibs.authz.AuthorizeTag A simple tag to output or not the body of the tag if the principal has or doesn't have certain authorities. ifNotGranted false true A comma separated list of roles which the user must not have for the body to be output. ifAllGranted false true A comma separated list of roles which the user must all possess for the body to be output. ifAnyGranted false true A comma separated list of roles, one of which the user must possess for the body to be output. authentication org.springframework.security.taglibs.authz.AuthenticationTag Allows access to the current Authentication object. property true true Property of the Authentication object which should be output. Supports nested properties. For example if the principal object is an instance of UserDetails, the property "principal.username" will return the username. Alternatively, using "name" will call getName method on the Authentication object directly. var false false Name of the exported scoped variable which will contain the evaluated property of the Authentication object. scope false false Scope for var. acl org.springframework.security.taglibs.authz.AclTag Allows inclusion of a tag body if the current Authentication has one of the specified permissions to the presented domain object instance. This tag uses the first AclManager it locates via WebApplicationContextUtils.getRequiredWebApplicationContext(HttpServletContext). hasPermission true true A comma separated list of integers, each representing a required bit mask permission from a subclass of org.springframework.security.acl.basic.AbstractBasicAclEntry. domainObject true true The actual domain object instance for which permissions are being evaluated. accesscontrollist org.springframework.security.taglibs.authz.AccessControlListTag Allows inclusion of a tag body if the current Authentication has one of the specified permissions to the presented domain object instance. hasPermission true true A comma separated list of integers, each representing a required bit mask permission from a subclass of org.springframework.security.acl.basic.AbstractBasicAclEntry. domainObject true true The actual domain object instance for which permissions are being evaluated. spring-security-2.0.7.RELEASE/dist/spring-security-taglibs/META-INF/MANIFEST.MF0000644000000000000000000000014311623522004023154 0ustar Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: 20.1-b02-384 (Apple Inc.) spring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/0000755000000000000000000000000011421405512021153 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/0000755000000000000000000000000011421405512024373 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/0000755000000000000000000000000011421405512026242 5ustar spring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/0000755000000000000000000000000011623517156027703 5ustar ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/spring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/auth0000755000000000000000000000000011623517156030565 5ustar ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AuthenticationTag.javaspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/auth0000644000000000000000000001056211623517156030573 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.taglibs.authz; import org.springframework.security.Authentication; import org.springframework.security.context.SecurityContext; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.util.TextUtils; import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.BeansException; import org.springframework.web.util.TagUtils; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; import javax.servlet.jsp.tagext.TagSupport; /** * An {@link javax.servlet.jsp.tagext.Tag} implementation that allows convenient access to the current * Authentication object. *

    * Whilst JSPs can access the SecurityContext directly, this tag avoids handling null conditions. * * @author Thomas Champagne * @version $Id$ */ public class AuthenticationTag extends TagSupport { //~ Instance fields ================================================================================================ private String var; private String property; private int scope; private boolean scopeSpecified; //~ Methods ======================================================================================================== public AuthenticationTag() { init(); } // resets local state private void init() { var = null; scopeSpecified = false; scope = PageContext.PAGE_SCOPE; } public void setVar(String var) { this.var = var; } public void setProperty(String operation) { this.property = operation; } public void setScope(String scope) { this.scope = TagUtils.getScope(scope); this.scopeSpecified = true; } public int doStartTag() throws JspException { return super.doStartTag(); } public int doEndTag() throws JspException { Object result = null; // determine the value by... if (property != null) { if ((SecurityContextHolder.getContext() == null) || !(SecurityContextHolder.getContext() instanceof SecurityContext) || (SecurityContextHolder.getContext().getAuthentication() == null)) { return Tag.EVAL_PAGE; } Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth.getPrincipal() == null) { return Tag.EVAL_PAGE; } try { BeanWrapperImpl wrapper = new BeanWrapperImpl(auth); result = wrapper.getPropertyValue(property); } catch (BeansException e) { throw new JspException(e); } } if (var != null) { /* * Store the result, letting an IllegalArgumentException * propagate back if the scope is invalid (e.g., if an attempt * is made to store something in the session without any * HttpSession existing). */ if (result != null) { pageContext.setAttribute(var, result, scope); } else { if (scopeSpecified) { pageContext.removeAttribute(var, scope); } else { pageContext.removeAttribute(var); } } } else { writeMessage(TextUtils.escapeEntities(String.valueOf(result))); } return EVAL_PAGE; } protected void writeMessage(String msg) throws JspException { try { pageContext.getOut().write(String.valueOf(msg)); } catch (IOException ioe) { throw new JspException(ioe); } } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/auth0000644000000000000000000000010611623517156030564 0ustar Java implementation of security taglib. ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AclTag.javaspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/auth0000644000000000000000000001776711623517156030611 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.taglibs.authz; import org.springframework.security.Authentication; import org.springframework.security.acl.AclEntry; import org.springframework.security.acl.AclManager; import org.springframework.security.acl.basic.BasicAclEntry; import org.springframework.security.context.SecurityContextHolder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.util.ExpressionEvaluationUtils; import java.util.HashSet; import java.util.Set; import java.util.StringTokenizer; import javax.servlet.ServletContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; import javax.servlet.jsp.tagext.TagSupport; /** * An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows its body through if some authorizations * are granted to the request's principal.

    Only works with permissions that are subclasses of {@link * org.springframework.security.acl.basic.BasicAclEntry}.

    *

    One or more comma separate integer permissions are specified via the hasPermission attribute. * The tag will include its body if any of the integer permissions have been granted to the current * Authentication (obtained from the SecurityContextHolder).

    *

    For this class to operate it must be able to access the application context via the * WebApplicationContextUtils and locate an {@link AclManager}. Application contexts have no need to have * more than one AclManager (as a provider-based implementation can be used so that it locates a provider * that is authoritative for the given domain object instance), so the first AclManager located will be * used.

    * * @author Ben Alex * @version $Id$ */ public class AclTag extends TagSupport { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(AclTag.class); //~ Instance fields ================================================================================================ private Object domainObject; private String hasPermission = ""; //~ Methods ======================================================================================================== public int doStartTag() throws JspException { if ((null == hasPermission) || "".equals(hasPermission)) { return Tag.SKIP_BODY; } final String evaledPermissionsString = ExpressionEvaluationUtils.evaluateString("hasPermission", hasPermission, pageContext); Integer[] requiredIntegers = null; try { requiredIntegers = parseIntegersString(evaledPermissionsString); } catch (NumberFormatException nfe) { throw new JspException(nfe); } Object resolvedDomainObject = null; if (domainObject instanceof String) { resolvedDomainObject = ExpressionEvaluationUtils.evaluate("domainObject", (String) domainObject, Object.class, pageContext); } else { resolvedDomainObject = domainObject; } if (resolvedDomainObject == null) { if (logger.isDebugEnabled()) { logger.debug("domainObject resolved to null, so including tag body"); } // Of course they have access to a null object! return Tag.EVAL_BODY_INCLUDE; } if (SecurityContextHolder.getContext().getAuthentication() == null) { if (logger.isDebugEnabled()) { logger.debug( "SecurityContextHolder did not return a non-null Authentication object, so skipping tag body"); } return Tag.SKIP_BODY; } Authentication auth = SecurityContextHolder.getContext().getAuthentication(); ApplicationContext context = getContext(pageContext); String[] beans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, AclManager.class, false, false); if (beans.length == 0) { throw new JspException("No AclManager would found the application context: " + context.toString()); } AclManager aclManager = (AclManager) context.getBean(beans[0]); // Obtain aclEntrys applying to the current Authentication object AclEntry[] acls = aclManager.getAcls(resolvedDomainObject, auth); if (logger.isDebugEnabled()) { logger.debug("Authentication: '" + auth + "' has: " + ((acls == null) ? 0 : acls.length) + " AclEntrys for domain object: '" + resolvedDomainObject + "' from AclManager: '" + aclManager.toString() + "'"); } if ((acls == null) || (acls.length == 0)) { return Tag.SKIP_BODY; } for (int i = 0; i < acls.length; i++) { // Locate processable AclEntrys if (acls[i] instanceof BasicAclEntry) { BasicAclEntry processableAcl = (BasicAclEntry) acls[i]; // See if principal has any of the required permissions for (int y = 0; y < requiredIntegers.length; y++) { if (processableAcl.isPermitted(requiredIntegers[y].intValue())) { if (logger.isDebugEnabled()) { logger.debug("Including tag body as found permission: " + requiredIntegers[y] + " due to AclEntry: '" + processableAcl + "'"); } return Tag.EVAL_BODY_INCLUDE; } } } } if (logger.isDebugEnabled()) { logger.debug("No permission, so skipping tag body"); } return Tag.SKIP_BODY; } /** * Allows test cases to override where application context obtained from. * * @param pageContext so the ServletContext can be accessed as required by Spring's * WebApplicationContextUtils * * @return the Spring application context (never null) */ protected ApplicationContext getContext(PageContext pageContext) { ServletContext servletContext = pageContext.getServletContext(); return WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); } public Object getDomainObject() { return domainObject; } public String getHasPermission() { return hasPermission; } private Integer[] parseIntegersString(String integersString) throws NumberFormatException { final Set integers = new HashSet(); final StringTokenizer tokenizer; tokenizer = new StringTokenizer(integersString, ",", false); while (tokenizer.hasMoreTokens()) { String integer = tokenizer.nextToken(); integers.add(new Integer(integer)); } return (Integer[]) integers.toArray(new Integer[] {}); } public void setDomainObject(Object domainObject) { this.domainObject = domainObject; } public void setHasPermission(String hasPermission) { this.hasPermission = hasPermission; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AccessControlListTag.javaspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/auth0000644000000000000000000002177511623517156030603 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.taglibs.authz; import org.springframework.security.acls.Acl; import org.springframework.security.acls.AclService; import org.springframework.security.acls.NotFoundException; import org.springframework.security.acls.Permission; import org.springframework.security.acls.domain.BasePermission; import org.springframework.security.acls.objectidentity.ObjectIdentity; import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategy; import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategyImpl; import org.springframework.security.acls.sid.Sid; import org.springframework.security.acls.sid.SidRetrievalStrategy; import org.springframework.security.acls.sid.SidRetrievalStrategyImpl; import org.springframework.security.context.SecurityContextHolder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.util.ExpressionEvaluationUtils; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.HashMap; import javax.servlet.ServletContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; import javax.servlet.jsp.tagext.TagSupport; /** * An implementation of {@link Tag} that allows its body through if some authorizations are granted to the request's * principal. *

    * One or more comma separate numeric are specified via the hasPermission attribute. * These permissions are then converted into {@link Permission} instances. These instances are then presented as an * array to the {@link Acl#isGranted(Permission[], org.springframework.security.acls.sid.Sid[], boolean)} method. * The {@link Sid} presented is determined by the {@link SidRetrievalStrategy}. *

    * For this class to operate it must be able to access the application context via the * WebApplicationContextUtils and locate an {@link AclService} and {@link SidRetrievalStrategy}. * Application contexts must provide one and only one of these Java types. * * @author Ben Alex * @version $Id$ */ public class AccessControlListTag extends TagSupport { //~ Static fields/initializers ===================================================================================== protected static final Log logger = LogFactory.getLog(AccessControlListTag.class); //~ Instance fields ================================================================================================ private AclService aclService; private ApplicationContext applicationContext; private Object domainObject; private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy; private SidRetrievalStrategy sidRetrievalStrategy; private String hasPermission = ""; //~ Methods ======================================================================================================== public int doStartTag() throws JspException { initializeIfRequired(); if ((null == hasPermission) || "".equals(hasPermission)) { return Tag.SKIP_BODY; } final String evaledPermissionsString = ExpressionEvaluationUtils.evaluateString("hasPermission", hasPermission, pageContext); Permission[] requiredPermissions = null; try { requiredPermissions = parsePermissionsString(evaledPermissionsString); } catch (NumberFormatException nfe) { throw new JspException(nfe); } Object resolvedDomainObject = null; if (domainObject instanceof String) { resolvedDomainObject = ExpressionEvaluationUtils.evaluate("domainObject", (String) domainObject, Object.class, pageContext); } else { resolvedDomainObject = domainObject; } if (resolvedDomainObject == null) { if (logger.isDebugEnabled()) { logger.debug("domainObject resolved to null, so including tag body"); } // Of course they have access to a null object! return Tag.EVAL_BODY_INCLUDE; } if (SecurityContextHolder.getContext().getAuthentication() == null) { if (logger.isDebugEnabled()) { logger.debug( "SecurityContextHolder did not return a non-null Authentication object, so skipping tag body"); } return Tag.SKIP_BODY; } Sid[] sids = sidRetrievalStrategy.getSids(SecurityContextHolder.getContext().getAuthentication()); ObjectIdentity oid = objectIdentityRetrievalStrategy.getObjectIdentity(resolvedDomainObject); // Obtain aclEntrys applying to the current Authentication object try { Acl acl = aclService.readAclById(oid, sids); if (acl.isGranted(requiredPermissions, sids, false)) { return Tag.EVAL_BODY_INCLUDE; } else { return Tag.SKIP_BODY; } } catch (NotFoundException nfe) { return Tag.SKIP_BODY; } } /** * Allows test cases to override where application context obtained from. * * @param pageContext so the ServletContext can be accessed as required by Spring's * WebApplicationContextUtils * * @return the Spring application context (never null) */ protected ApplicationContext getContext(PageContext pageContext) { ServletContext servletContext = pageContext.getServletContext(); return WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); } public Object getDomainObject() { return domainObject; } public String getHasPermission() { return hasPermission; } private void initializeIfRequired() throws JspException { if (applicationContext != null) { return; } this.applicationContext = getContext(pageContext); Map map = new HashMap(); ApplicationContext context = applicationContext; while (context != null) { map.putAll(context.getBeansOfType(AclService.class)); context = context.getParent(); } if (map.size() != 1) { throw new JspException( "Found incorrect number of AclService instances in application context - you must have only have one!"); } aclService = (AclService) map.values().iterator().next(); map = applicationContext.getBeansOfType(SidRetrievalStrategy.class); if (map.size() == 0) { sidRetrievalStrategy = new SidRetrievalStrategyImpl(); } else if (map.size() == 1) { sidRetrievalStrategy = (SidRetrievalStrategy) map.values().iterator().next(); } else { throw new JspException("Found incorrect number of SidRetrievalStrategy instances in application " + "context - you must have only have one!"); } map = applicationContext.getBeansOfType(ObjectIdentityRetrievalStrategy.class); if (map.size() == 0) { objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); } else if (map.size() == 1) { objectIdentityRetrievalStrategy = (ObjectIdentityRetrievalStrategy) map.values().iterator().next(); } else { throw new JspException("Found incorrect number of ObjectIdentityRetrievalStrategy instances in " + "application context - you must have only have one!"); } } private Permission[] parsePermissionsString(String integersString) throws NumberFormatException { final Set permissions = new HashSet(); final StringTokenizer tokenizer; tokenizer = new StringTokenizer(integersString, ",", false); while (tokenizer.hasMoreTokens()) { String integer = tokenizer.nextToken(); permissions.add(BasePermission.buildFromMask(new Integer(integer).intValue())); } return (Permission[]) permissions.toArray(new Permission[permissions.size()]); } public void setDomainObject(Object domainObject) { this.domainObject = domainObject; } public void setHasPermission(String hasPermission) { this.hasPermission = hasPermission; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/authz/AuthorizeTag.javaspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/auth0000644000000000000000000002054511623517156030575 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.taglibs.authz; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthorityImpl; import org.springframework.security.context.SecurityContextHolder; import org.springframework.util.StringUtils; import org.springframework.web.util.ExpressionEvaluationUtils; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.Tag; import javax.servlet.jsp.tagext.TagSupport; /** * An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows it's body through if some authorizations * are granted to the request's principal. * * @author Francois Beausoleil * @version $Id$ */ public class AuthorizeTag extends TagSupport { //~ Instance fields ================================================================================================ private String ifAllGranted = ""; private String ifAnyGranted = ""; private String ifNotGranted = ""; //~ Methods ======================================================================================================== private Set authoritiesToRoles(Collection c) { Set target = new HashSet(); for (Iterator iterator = c.iterator(); iterator.hasNext();) { GrantedAuthority authority = (GrantedAuthority) iterator.next(); if (null == authority.getAuthority()) { throw new IllegalArgumentException( "Cannot process GrantedAuthority objects which return null from getAuthority() - attempting to process " + authority.toString()); } target.add(authority.getAuthority()); } return target; } public int doStartTag() throws JspException { if (((null == ifAllGranted) || "".equals(ifAllGranted)) && ((null == ifAnyGranted) || "".equals(ifAnyGranted)) && ((null == ifNotGranted) || "".equals(ifNotGranted))) { return Tag.SKIP_BODY; } final Collection granted = getPrincipalAuthorities(); final String evaledIfNotGranted = ExpressionEvaluationUtils.evaluateString("ifNotGranted", ifNotGranted, pageContext); if ((null != evaledIfNotGranted) && !"".equals(evaledIfNotGranted)) { Set grantedCopy = retainAll(granted, parseAuthoritiesString(evaledIfNotGranted)); if (!grantedCopy.isEmpty()) { return Tag.SKIP_BODY; } } final String evaledIfAllGranted = ExpressionEvaluationUtils.evaluateString("ifAllGranted", ifAllGranted, pageContext); if ((null != evaledIfAllGranted) && !"".equals(evaledIfAllGranted)) { if (!granted.containsAll(parseAuthoritiesString(evaledIfAllGranted))) { return Tag.SKIP_BODY; } } final String evaledIfAnyGranted = ExpressionEvaluationUtils.evaluateString("ifAnyGranted", ifAnyGranted, pageContext); if ((null != evaledIfAnyGranted) && !"".equals(evaledIfAnyGranted)) { Set grantedCopy = retainAll(granted, parseAuthoritiesString(evaledIfAnyGranted)); if (grantedCopy.isEmpty()) { return Tag.SKIP_BODY; } } return Tag.EVAL_BODY_INCLUDE; } public String getIfAllGranted() { return ifAllGranted; } public String getIfAnyGranted() { return ifAnyGranted; } public String getIfNotGranted() { return ifNotGranted; } private Collection getPrincipalAuthorities() { Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); if (null == currentUser) { return Collections.EMPTY_LIST; } if ((null == currentUser.getAuthorities()) || (currentUser.getAuthorities().length < 1)) { return Collections.EMPTY_LIST; } Collection granted = Arrays.asList(currentUser.getAuthorities()); return granted; } private Set parseAuthoritiesString(String authorizationsString) { final Set requiredAuthorities = new HashSet(); final String[] authorities = StringUtils.commaDelimitedListToStringArray(authorizationsString); for (int i = 0; i < authorities.length; i++) { String authority = authorities[i]; // Remove the role's whitespace characters without depending on JDK 1.4+ // Includes space, tab, new line, carriage return and form feed. String role = authority.trim(); // trim, don't use spaces, as per SEC-378 role = StringUtils.deleteAny(role, "\t\n\r\f"); requiredAuthorities.add(new GrantedAuthorityImpl(role)); } return requiredAuthorities; } /** * Find the common authorities between the current authentication's {@link GrantedAuthority} and the ones * that have been specified in the tag's ifAny, ifNot or ifAllGranted attributes.

    We need to manually * iterate over both collections, because the granted authorities might not implement {@link * Object#equals(Object)} and {@link Object#hashCode()} in the same way as {@link GrantedAuthorityImpl}, thereby * invalidating {@link Collection#retainAll(java.util.Collection)} results.

    *

    * CAVEAT: This method will not work if the granted authorities * returns a null string as the return value of {@link * org.springframework.security.GrantedAuthority#getAuthority()}. *

    *

    Reported by rawdave, on Fri Feb 04, 2005 2:11 pm in the Spring Security forum.

    * * @param granted The authorities granted by the authentication. May be any implementation of {@link * GrantedAuthority} that does not return null from {@link * org.springframework.security.GrantedAuthority#getAuthority()}. * @param required A {@link Set} of {@link GrantedAuthorityImpl}s that have been built using ifAny, ifAll or * ifNotGranted. * * @return A set containing only the common authorities between granted and required. * * @see authz:authorize ifNotGranted not behaving * as expected TODO: wrong article Url */ private Set retainAll(final Collection granted, final Set required) { Set grantedRoles = authoritiesToRoles(granted); Set requiredRoles = authoritiesToRoles(required); grantedRoles.retainAll(requiredRoles); return rolesToAuthorities(grantedRoles, granted); } private Set rolesToAuthorities(Set grantedRoles, Collection granted) { Set target = new HashSet(); for (Iterator iterator = grantedRoles.iterator(); iterator.hasNext();) { String role = (String) iterator.next(); for (Iterator grantedIterator = granted.iterator(); grantedIterator.hasNext();) { GrantedAuthority authority = (GrantedAuthority) grantedIterator.next(); if (authority.getAuthority().equals(role)) { target.add(authority); break; } } } return target; } public void setIfAllGranted(String ifAllGranted) throws JspException { this.ifAllGranted = ifAllGranted; } public void setIfAnyGranted(String ifAnyGranted) throws JspException { this.ifAnyGranted = ifAnyGranted; } public void setIfNotGranted(String ifNotGranted) throws JspException { this.ifNotGranted = ifNotGranted; } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/package.htmlspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/pack0000644000000000000000000000013211623517156030540 0ustar Provides security related taglibs that can be used in JSPs. ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/velocity/spring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/velo0000755000000000000000000000000011623517156030571 5ustar ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/velocity/AuthzImpl.javaspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/velo0000644000000000000000000001453511623517156030603 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.taglibs.velocity; import org.springframework.security.acl.AclManager; import org.springframework.security.taglibs.authz.AclTag; import org.springframework.security.taglibs.authz.AuthenticationTag; import org.springframework.security.taglibs.authz.AuthorizeTag; import org.springframework.context.ApplicationContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; /** * I decided to wrap several JSP tag in one class, so I have to using inner class to wrap these JSP tag. To using * this class, you need to inject Spring Context via SetAppCtx() method. AclTag need Spring Context to get AclManger * bean. */ public class AuthzImpl implements Authz { //~ Static fields/initializers ===================================================================================== static final int ALL_GRANTED = 1; static final int ANY_GRANTED = 2; static final int NONE_GRANTED = 3; //~ Instance fields ================================================================================================ private ApplicationContext appCtx; //~ Methods ======================================================================================================== public boolean allGranted(String roles) { return ifGranted(roles, ALL_GRANTED); } public boolean anyGranted(String roles) { return ifGranted(roles, ANY_GRANTED); } public ApplicationContext getAppCtx() { return appCtx; } /** * implementation of AuthenticationTag * * @return DOCUMENT ME! * * @throws IllegalArgumentException DOCUMENT ME! */ public String getPrincipal() { MyAuthenticationTag authenticationTag = new MyAuthenticationTag(); authenticationTag.setProperty("username"); try { authenticationTag.doStartTag(); } catch (JspException je) { je.printStackTrace(); throw new IllegalArgumentException(je.getMessage()); } return authenticationTag.getLastMessage(); } /** * implementation of AclTag * * @param domainObject DOCUMENT ME! * @param permissions DOCUMENT ME! * * @return DOCUMENT ME! * * @throws IllegalArgumentException DOCUMENT ME! */ public boolean hasPermission(Object domainObject, String permissions) { MyAclTag aclTag = new MyAclTag(); aclTag.setPageContext(null); aclTag.setContext(getAppCtx()); aclTag.setDomainObject(domainObject); aclTag.setHasPermission(permissions); int result = -1; try { result = aclTag.doStartTag(); } catch (JspException je) { throw new IllegalArgumentException(je.getMessage()); } if (Tag.EVAL_BODY_INCLUDE == result) { return true; } else { return false; } } /** * implementation of AuthorizeTag * * @param roles DOCUMENT ME! * @param grantType DOCUMENT ME! * * @return DOCUMENT ME! * * @throws IllegalArgumentException DOCUMENT ME! */ private boolean ifGranted(String roles, int grantType) { AuthorizeTag authorizeTag = new AuthorizeTag(); int result = -1; try { switch (grantType) { case ALL_GRANTED: authorizeTag.setIfAllGranted(roles); break; case ANY_GRANTED: authorizeTag.setIfAnyGranted(roles); break; case NONE_GRANTED: authorizeTag.setIfNotGranted(roles); break; default: throw new IllegalArgumentException("invalid granted type : " + grantType + " role=" + roles); } result = authorizeTag.doStartTag(); } catch (JspException je) { throw new IllegalArgumentException(je.getMessage()); } if (Tag.EVAL_BODY_INCLUDE == result) { return true; } else { return false; } } public boolean noneGranted(String roles) { return ifGranted(roles, NONE_GRANTED); } /** * test case can use this class to mock application context with aclManager bean in it. * * @param appCtx DOCUMENT ME! */ public void setAppCtx(ApplicationContext appCtx) { this.appCtx = appCtx; } //~ Inner Classes ================================================================================================== /** * AclTag need to access the application context via the WebApplicationContextUtils and * locate an {@link AclManager}. WebApplicationContextUtils get application context via ServletContext. I decided * to let the Authz provide the Spring application context. */ private class MyAclTag extends AclTag { private static final long serialVersionUID = 6752340622125924108L; ApplicationContext context; protected ApplicationContext getContext(PageContext pageContext) { return context; } protected void setContext(ApplicationContext context) { this.context = context; } } /** * it must output somthing to JSP page, so have to override the writeMessage method to avoid JSP related * operation. Get Idea from Acegi Test class. */ private class MyAuthenticationTag extends AuthenticationTag { private static final long serialVersionUID = -1094246833893599161L; String lastMessage = null; public String getLastMessage() { return lastMessage; } protected void writeMessage(String msg) throws JspException { lastMessage = msg; } } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/velocity/Authz.javaspring-security-2.0.7.RELEASE/dist/spring-security-taglibs/org/springframework/security/taglibs/velo0000644000000000000000000000657311623517156030606 0ustar /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.taglibs.velocity; import org.springframework.security.Authentication; import org.springframework.security.acl.AclManager; import org.springframework.security.taglibs.authz.AclTag; import org.springframework.security.taglibs.authz.AuthenticationTag; import org.springframework.security.taglibs.authz.AuthorizeTag; import org.springframework.security.userdetails.UserDetails; import org.springframework.context.ApplicationContext; /** * Wrapper the implementation of Spring Security JSP tag includes: * {@link AuthenticationTag}, {@link AclTag}, {@link AuthorizeTag} * * @author Wang Qi * @version $Id$ */ public interface Authz { //~ Methods ======================================================================================================== /** * all the listed roles must be granted to return true, otherwise fasle; * * @param roles - comma separate GrantedAuthoritys * * @return granted (true|false) */ boolean allGranted(String roles); /** * any the listed roles must be granted to return true, otherwise fasle; * * @param roles - comma separate GrantedAuthoritys * * @return granted (true|false) */ boolean anyGranted(String roles); /** * set Spring application context which contains acegi related bean * * @return DOCUMENT ME! */ ApplicationContext getAppCtx(); /** * return the principal's name, supports the various type of principals that can exist in the {@link * Authentication} object, such as a String or {@link UserDetails} instance * * @return string representation of principal's name */ String getPrincipal(); /** * return true if the principal holds either permission specified for the provided domain object

    Only * works with permissions that are subclasses of {@link org.springframework.security.acl.basic.AbstractBasicAclEntry}.

    *

    For this class to operate it must be able to access the application context via the * WebApplicationContextUtils and locate an {@link AclManager}.

    * * @param domainObject - domain object need acl control * @param permissions - comma separate integer permissions * * @return got acl permission (true|false) */ boolean hasPermission(Object domainObject, String permissions); /** * none the listed roles must be granted to return true, otherwise fasle; * * @param roles - comma separate GrantedAuthoritys * * @return granted (true|false) */ boolean noneGranted(String roles); /** * get Spring application context which contains acegi related bean * * @param appCtx DOCUMENT ME! */ void setAppCtx(ApplicationContext appCtx); } spring-security-2.0.7.RELEASE/readme.txt0000644000000000000000000000022011461662310014624 0ustar This is a release of the core project modules only, providing an upgrade path for Spring Security users who are not yet using Spring Security 3.