使用Arquillian测试安全的EJB

从历史上讲,很难对安全的EJB进行测试。 到目前为止,我一直在使用诸如用Arquillian 在WildFly 8.1.x上测试安全的EJB文章中描述的JBossLoginContextFactory等专有技术来测试安全的EJB。

在本年度Devoxx中Apache TomEE项目(轻量级Java EE应用程序服务器)的创始人David Blevins为我带来了一个小窍门,我们可以使用该技巧以一种标准方式处理Java EE安全性,该方法可在所有符合Java EE的服务器上运行。

GitHub上的javaee-testing / security提供了本文中使用的示例。

编码

要测试的代码包括一个实体和一个EJB服务,如下所示。

图书实体
@Entity
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String isbn;
    private String title;

    public Book() {
    }

    public Book(String isbn, String title) {
        this.isbn = isbn;
        this.title = title;
    }

    // getters and setters omitted for brevity
}
书架EJB服务
@Stateless
public class BookshelfService {

    @PersistenceContext(unitName = "bookshelfManager")
    private EntityManager entityManager;

    @RolesAllowed({ "User", "Manager" })
    public void addBook(Book book) {
        entityManager.persist(book);
    }

    @RolesAllowed({ "Manager" })
    public void deleteBook(Book book) {
        entityManager.remove(book);
    }

    @PermitAll
    @TransactionAttribute(TransactionAttributeType.SUPPORTS)
    public List<Book> getBooks() {
        TypedQuery<Book> query = entityManager.createQuery("SELECT b from Book as b", Book.class);
        return query.getResultList();
    }
}

测试类使用Arquillian进行集成测试,并断言尊重我们EJB上定义的安全角色。

书架服务测试
@RunWith(Arquillian.class)
public class BookshelfServiceIT {

    @Inject
    private BookshelfService bookshelfService;
    @Inject
    private BookshelfManager manager;
    @Inject
    private BookshelfUser user;

    @Deployment
    public static JavaArchive createDeployment() throws IOException {
        return ShrinkWrap.create(JavaArchive.class, "javaee-testing-security.jar")
                .addClasses(Book.class, BookshelfService.class, BookshelfManager.class, BookshelfUser.class)
                .addAsManifestResource("META-INF/persistence.xml", "persistence.xml")
                .addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml"));
    }

    @Test
    public void testAsManager() throws Exception {
        manager.call(new Callable<Book>() {
            @Override
            public Book call() throws Exception {
                bookshelfService.addBook(new Book("978-1-4302-4626-8", "Beginning Java EE 7"));
                bookshelfService.addBook(new Book("978-1-4493-2829-0", "Continuous Enterprise Development in Java"));

                List<Book> books = bookshelfService.getBooks();
                Assert.assertEquals("List.size()", 2, books.size());

                for (Book book : books) {
                    bookshelfService.deleteBook(book);
                }

                Assert.assertEquals("BookshelfService.getBooks()", 0, bookshelfService.getBooks().size());
                return null;
            }
        });
    }

    @Test
    public void testAsUser() throws Exception {
        user.call(new Callable<Book>() {
            @Override
            public Book call() throws Exception {
                bookshelfService.addBook(new Book("978-1-4302-4626-8", "Beginning Java EE 7"));
                bookshelfService.addBook(new Book("978-1-4493-2829-0", "Continuous Enterprise Development in Java"));

                List<Book> books = bookshelfService.getBooks();
                Assert.assertEquals("List.size()", 2, books.size());

                for (Book book : books) {
                    try {
                        bookshelfService.deleteBook(book);
                        Assert.fail("Users should not be allowed to delete");
                    } catch (EJBAccessException e) {
                        // Good, users cannot delete things
                    }
                }

                // The list should not be empty
                Assert.assertEquals("BookshelfService.getBooks()", 2, bookshelfService.getBooks().size());
                return null;
            }
        });
    }

    @Test
    public void testUnauthenticated() throws Exception {
        try {
            bookshelfService.addBook(new Book("978-1-4302-4626-8", "Beginning Java EE 7"));
            Assert.fail("Unauthenticated users should not be able to add books");
        } catch (EJBAccessException e) {
            // Good, unauthenticated users cannot add things
        }

        try {
            bookshelfService.deleteBook(null);
            Assert.fail("Unauthenticated users should not be allowed to delete");
        } catch (EJBAccessException e) {
            // Good, unauthenticated users cannot delete things
        }

        try {
            // Read access should be allowed
            List<Book> books = bookshelfService.getBooks();
            Assert.assertEquals("BookshelfService.getBooks()", 0, books.size());
        } catch (EJBAccessException e) {
            Assert.fail("Read access should be allowed");
        }
    }
}

技巧是在两个辅助EJB上,它们通过使用@RunAs标准注释允许我们的测试代码在所需的安全范围内执行。

书架经理角色
@Stateless
@RunAs("Manager")
@PermitAll
public class BookshelfManager {
    public <V> V call(Callable<V> callable) throws Exception {
        return callable.call();
    }
}
书架用户角色
@Stateless
@RunAs("User")
@PermitAll
public class BookshelfUser {
    public <V> V call(Callable<V> callable) throws Exception {
        return callable.call();
    }
}

跑步

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.samaxes.javaeetesting.security.BookshelfServiceIT
nov 23, 2014 2:44:48 AM org.xnio.Xnio <clinit>
INFO: XNIO version 3.2.0.Beta4
nov 23, 2014 2:44:48 AM org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.2.0.Beta4
nov 23, 2014 2:44:49 AM org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version (unknown)
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 36.69 sec - in com.samaxes.javaeetesting.security.BookshelfServiceIT

Results :

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0

测试愉快!

翻译自: https://www.javacodegeeks.com/2014/11/testing-secured-ejbs-with-arquillian.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值