This commit is contained in:
Arjen Poutsma
2008-05-03 12:13:14 +00:00
parent fa36d6e461
commit 13f5bb8872
8 changed files with 115 additions and 111 deletions

View File

@@ -1,4 +1,5 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>spring-ws-samples</artifactId>
<groupId>org.springframework.ws</groupId>
@@ -134,7 +135,8 @@
<phase>process-classes</phase>
<configuration>
<tasks>
<java classname="org.apache.openjpa.enhance.PCEnhancer" classpathref="maven.runtime.classpath" dir="target/classes" fork="true" />
<java classname="org.apache.openjpa.enhance.PCEnhancer"
classpathref="maven.runtime.classpath" dir="target/classes" fork="true"/>
</tasks>
</configuration>
<goals>
@@ -307,49 +309,12 @@
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.acegisecurity</groupId>
<artifactId>acegi-security</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-remoting</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-support</artifactId>
</exclusion>
<exclusion>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</exclusion>
<exclusion>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</exclusion>
<exclusion>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
<exclusion>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</exclusion>
</exclusions>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>org.acegisecurity</groupId>
<artifactId>acegi-security-tiger</artifactId>
<version>1.0.5</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
</exclusions>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core-tiger</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>

View File

@@ -16,9 +16,9 @@
package org.springframework.ws.samples.airline.security;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.userdetails.UserDetails;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.ws.samples.airline.domain.FrequentFlyer;
/**

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2006 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.ws.samples.airline.security;
import org.springframework.dao.DataAccessException;
import org.springframework.security.Authentication;
import org.springframework.security.context.SecurityContext;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ws.samples.airline.dao.FrequentFlyerDao;
import org.springframework.ws.samples.airline.domain.FrequentFlyer;
import org.springframework.ws.samples.airline.service.NoSuchFrequentFlyerException;
/**
* Implementation of the <code>FrequentFlyerSecurityService</code> that uses Spring Security.
*
* @author Arjen Poutsma
*/
public class SpringFrequentFlyerSecurityService implements FrequentFlyerSecurityService, UserDetailsService {
private FrequentFlyerDao frequentFlyerDao;
public SpringFrequentFlyerSecurityService(FrequentFlyerDao frequentFlyerDao) {
this.frequentFlyerDao = frequentFlyerDao;
}
@Transactional
public FrequentFlyer getCurrentlyAuthenticatedFrequentFlyer() {
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
if (authentication != null) {
if (authentication.getPrincipal() instanceof FrequentFlyerDetails) {
FrequentFlyerDetails details = (FrequentFlyerDetails) authentication.getPrincipal();
return details.getFrequentFlyer();
}
else {
return (FrequentFlyer) authentication.getPrincipal();
}
}
else {
return null;
}
}
@Transactional
public FrequentFlyer getFrequentFlyer(String username) throws NoSuchFrequentFlyerException {
FrequentFlyer frequentFlyer = frequentFlyerDao.get(username);
if (frequentFlyer != null) {
return frequentFlyer;
}
else {
throw new NoSuchFrequentFlyerException(username);
}
}
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
FrequentFlyer frequentFlyer = frequentFlyerDao.get(username);
if (frequentFlyer != null) {
return new FrequentFlyerDetails(frequentFlyer);
}
else {
throw new UsernameNotFoundException("Frequent flyer '" + username + "' not found");
}
}
}

View File

@@ -22,7 +22,7 @@ import org.springframework.ws.samples.airline.service.NoSuchFrequentFlyerExcepti
/**
* Stub implementation of <code>FrequentFlyerSecurityService</code>. This implementation is used by default by {@link
* org.springframework.ws.samples.airline.service.impl.AirlineServiceImpl}, to allow it to run without depending on
* Acegi Security.
* Spring Security.
*
* @author Arjen Poutsma
*/

View File

@@ -17,11 +17,9 @@ package org.springframework.ws.samples.airline.service;
import java.util.List;
import org.acegisecurity.annotation.Secured;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ws.samples.airline.domain.Flight;
import org.springframework.ws.samples.airline.domain.FrequentFlyer;
import org.springframework.ws.samples.airline.domain.Passenger;
@@ -74,8 +72,6 @@ public interface AirlineService {
* @see org.springframework.ws.samples.airline.domain.Passenger
* @see org.springframework.ws.samples.airline.domain.FrequentFlyer
*/
@Transactional(readOnly = false,
rollbackFor = {NoSuchFlightException.class, NoSeatAvailableException.class, NoSuchFrequentFlyerException.class})
Ticket bookFlight(String flightNumber, DateTime departureTime, List<Passenger> passengers)
throws NoSuchFlightException, NoSeatAvailableException, NoSuchFrequentFlyerException;
@@ -84,6 +80,5 @@ public interface AirlineService {
*
* @return the amount of frequent flyer miles
*/
@Secured({"ROLE_FREQUENT_FLYER"})
int getFrequentFlyerMileage();
}

View File

@@ -23,6 +23,7 @@ import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.annotation.Secured;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
@@ -134,6 +135,7 @@ public class AirlineServiceImpl implements AirlineService {
return flights;
}
@Secured({"ROLE_FREQUENT_FLYER"})
public int getFrequentFlyerMileage() {
if (logger.isDebugEnabled()) {
logger.debug("Using " + frequentFlyerSecurityService + " for security");

View File

@@ -1,83 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<description>
This application context contains the WS-Security and Acegi beans.
This application context contains the WS-Security and Sprign Security beans.
</description>
<aop:config>
<aop:pointcut id="getFrequentFlyerMileage"
expression="execution(* org.springframework.ws.samples.airline.service.AirlineService+.*(..))"/>
<aop:advisor advice-ref="methodSecurityInterceptor" pointcut-ref="getFrequentFlyerMileage"/>
</aop:config>
<security:global-method-security secured-annotations="enabled"/>
<security:authentication-provider user-service-ref="securityService"/>
<bean id="securityService"
class="org.springframework.ws.samples.airline.security.AcegiFrequentFlyerSecurityService">
class="org.springframework.ws.samples.airline.security.SpringFrequentFlyerSecurityService">
<description>
A security service used to obtain Frequent Flyer information.
</description>
<constructor-arg ref="frequentFlyerDao"/>
</bean>
<!-- ===================== WS-SECURITY ============================== -->
<bean id="wsSecurityInterceptor" class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor">
<description>
This interceptor validates incoming messages according to the policy defined in 'securityPolicy.xml'.
The policy defines that all incoming requests must have a UsernameToken with a password digest in it.
The actual authentication is performed by the Acegi callback handler.
The actual authentication is performed by the Spring Security callback handler.
</description>
<property name="secureResponse" value="false"/>
<property name="policyConfiguration"
value="classpath:org/springframework/ws/samples/airline/security/securityPolicy.xml"/>
<property name="callbackHandler">
<bean class="org.springframework.ws.soap.security.xwss.callback.acegi.AcegiDigestPasswordValidationCallbackHandler">
<bean class="org.springframework.ws.soap.security.xwss.callback.SpringDigestPasswordValidationCallbackHandler">
<property name="userDetailsService" ref="securityService"/>
</bean>
</property>
</bean>
<!-- ======================== ACEGI AUTHENTICATION ======================= -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<description>
A standard Acegi authentication manager.
</description>
<property name="providers">
<bean class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="securityService"/>
</bean>
</property>
</bean>
<bean id="loggerListener" class="org.acegisecurity.event.authentication.LoggerListener"/>
<!-- ======================== ACEGI AUTHORIZATION =========================== -->
<bean id="methodSecurityInterceptor"
class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager">
<ref local="authenticationManager"/>
</property>
<property name="accessDecisionManager">
<bean class="org.acegisecurity.vote.AffirmativeBased">
<property name="decisionVoters">
<bean class="org.acegisecurity.vote.RoleVoter"/>
</property>
</bean>
</property>
<property name="objectDefinitionSource">
<bean class="org.acegisecurity.intercept.method.MethodDefinitionAttributes">
<property name="attributes">
<bean class="org.acegisecurity.annotation.SecurityAnnotationAttributes"/>
</property>
</bean>
</property>
</bean>
</beans>

View File

@@ -17,23 +17,24 @@
package org.springframework.ws.samples.airline.security;
import junit.framework.TestCase;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.context.SecurityContextImpl;
import org.acegisecurity.providers.TestingAuthenticationToken;
import static org.easymock.EasyMock.*;
import org.springframework.security.context.SecurityContext;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.context.SecurityContextImpl;
import org.springframework.security.providers.TestingAuthenticationToken;
import org.springframework.ws.samples.airline.dao.FrequentFlyerDao;
import org.springframework.ws.samples.airline.domain.FrequentFlyer;
public class AcegiFrequentFlyerSecurityServiceTest extends TestCase {
public class SpringFrequentFlyerSecurityServiceTest extends TestCase {
private AcegiFrequentFlyerSecurityService securityService;
private SpringFrequentFlyerSecurityService securityService;
private FrequentFlyerDao flyerDaoMock;
protected void setUp() throws Exception {
flyerDaoMock = createMock(FrequentFlyerDao.class);
securityService = new AcegiFrequentFlyerSecurityService(flyerDaoMock);
securityService = new SpringFrequentFlyerSecurityService(flyerDaoMock);
}
public void testGetCurrentlyAuthenticatedFrequentFlyer() throws Exception {