编写使用SpringSecurity的JUnit测试提醒
近日在使用SpringSecurity的项目中发现一个小问题,就是在接口上加了@Secured标注限制调用接口权限时,某些JUnit无法正常调用了。
例如:
@Secured(PrivilegeDAO.ROLE_REMIND_CREATE)
public Serializable save(Users user) throws BusinessException;
调用save方法时,必须具备 PrivilegeDAO.ROLE_REMIND_CREATE权限才行。
原因很简单,执行JUnit的时候并没有经过SpringSecurity的登录把资源设置到上下文,所以是无登录权限的。而调用接口的时候又要获取执行权限,这当然造成无法调用的局面了。
花了点时间,查找资源,找到个解决方案,分享下。其实就是覆盖原来认真配置信息,然后把供单元测试用的TestingAuthenticationToken设置回spring容器当中。所以之后执行单元测试时就有权限了。注意构造TestingAuthenticationToken的时候必须根据项目具体情况来添加GrantedAuthority[]。
具体代码参考如下:
import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import org.springframework.beans.factory.BeanFactory;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.TestingAuthenticationProvider;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl; import cn.com.timekey.drugmonitor.po.Privilege; /**
* @author kennylee
*
*/
public class SecurityTestingUnit { /**
* 设置SpringSecurity的登录用户权限。
*
* @param ctx
* @param auths
*/
public static void setAuthToken(BeanFactory ctx, GrantedAuthority[] auths) {
TestingAuthenticationToken token = new TestingAuthenticationToken(
"admin", "test", auths);
// Override the regular spring configuration
ProviderManager providerManager = (ProviderManager) ctx
.getBean("authenticationManager");
List<AuthenticationProvider> list = new ArrayList<AuthenticationProvider>();
TestingAuthenticationProvider testingAuthenticationProvider = new TestingAuthenticationProvider();
list.add(testingAuthenticationProvider);
providerManager.setProviders(list); // Create and store the SpringSecurity SecureContext into the
// SecurityContextHolder.
SecurityContextImpl secureContext = new SecurityContextImpl();
secureContext.setAuthentication(token);
SecurityContextHolder.setContext(secureContext);
} /**
* 构造权限组
*
* @param rolePrivileges
* @return
*/
public static GrantedAuthority[] generateAuthorities(
Collection<Privilege> privileges) {
GrantedAuthority[] auths = new GrantedAuthority[privileges.size()];
if (!privileges.isEmpty()) {
int count = 0;
for (Privilege rolePrivilege : privileges) {
String privilegeName = rolePrivilege.getPrivilegeName();
GrantedAuthority authority = new GrantedAuthorityImpl(
privilegeName);
auths[count] = authority;
count++;
}
}
return auths;
} }
其中generateAuthorities只是我的一个辅助构造方法。不是重点内容。setAuthToken为主体代码。
JUnit testing with Acegi Security
Here's a tip if you are trying to do some unit testing with Acegi Security - particularly if you are doing role based authorization of method calls on your manager objects via interception.
Basically, a secure method interceptor will a) need an authentication token to play with, and b) a way to find out what authorities the user has. We need to cater for this when running the tests.
Acegi Security conveniently provides a TestingAuthenticationToken for unit testing purposes so we are Ok with the token part. You will now need to provide a suitable authentication provider. Somewhat unsurprisingly, there is a TestingAuthenticationProvider that you can add to your Spring config file to accommodate this.
But here is the problem: we already have this configured for production using a different provider (obviously), so we would have to resort to changing the config files depending on if you are running tests or not. This is too fragile for me, so here is the essence of the tip: leave the configuration file alone and dynamically changes the provider in the setup of the unit test.
Here is some code that I have in my JUnit setUp() method:
// Grant all roles to noddy.
TestingAuthenticationToken token = new TestingAuthenticationToken(
"noddy", "test", new GrantedAuthority[] {
new GrantedAuthorityImpl("User"),
new GrantedAuthorityImpl("Administrator") });
// Override the regular spring configuration
ProviderManager providerManager = (ProviderManager) ctx.getBean("authenticationManager");
List list = new ArrayList();
list.add(new TestingAuthenticationProvider());
providerManager.setProviders(list);
// Create and store the Acegi SecureContext into the ContextHolder.
SecureContextImpl secureContext = new SecureContextImpl();
secureContext.setAuthentication(token);
ContextHolder.setContext(secureContext);
So... it sets up an authentication token, then resets the authentication managers' provider list with one that contains the TestingAuthenticationProvider. It then creates the context for the method execution.
The problem with this is it does it for every single test method - that is how JUnit works for better or worse.
Hope it proves useful for you.
参考见:http://fishdujour.typepad.com/blog/2005/02/junit_testing_w.html
编写使用SpringSecurity的JUnit测试提醒的更多相关文章
- 单元测试实战 - Junit测试
一.对加法函数进行测试 1.实例化被测单元(方法):类名 实例名=new 类名([参数]) 2.调用被测单元,对比预期值和输出值(实际值): 在没有junit测试工具的情况下,我们要进行如下的测试代码 ...
- EditBox问题的实现以及Junit测试框架的简要说明
一.这周的EditBox由一个框改为三个框,同时进行测试,下面给出程序及截图 1 import java.util.regex.Matcher; 2 import java.util.regex.Pa ...
- Android Junit测试框架
对应用进行单元测试: 使用Junit测试框架,是正规Android开发的必用技术.在Junit中可以得到组件,可以模拟发送事件和检测程序处理的正确性. 1.配置指令集和函数库: (1)配置指令集,指定 ...
- 无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)
1.android下junit测试框架配置 单元测试需要在手机中进行安装测试 (1).在清单文件中manifest节点下配置如下节点 <instrumentation android:name= ...
- applicationContext.xml文件放置位置不同而导致的jUnit测试的时候路径的不同
如果applicationContext.xml文件放置在src下面的的时候使用jUint测试的时候编写的路径应该是这样的: @Test public void testFindByPage() { ...
- 使用Cobertura统计JUnit测试覆盖率
这是一个JavaProject,关于Cobertura的用法详见代码注释 首先是应用代码(即被测试的代码) package com.jadyer.service; public class Calcu ...
- junit测试Android项目
关于junit测试Android项目方法主要有一下步骤: 1.导入junit4的jar包 在工厂中Build Path中Add Library->JUnit->JUnit4->Fin ...
- Java进阶(五)Junit测试
我们在编写大型程序的时候,需要写成千上万个方法或函数,这些函数的功能可能很强大,但我们在程序中只用到该函数的一小部分功能,并且经过调试可以确定,这一小部分功能是正确的.但是,我们同时应该确保每一个函数 ...
- Java高级特性 第10节 IDEA和Eclipse整合JUnit测试框架
一.IDEA整合Junit测试框架 1.安装插件 打开File菜单的下拉菜单settings[设置] : 点击左侧Plugins[插件]菜单 在输入框中输入JUnitGenerator 2.0,点击I ...
随机推荐
- LeetCode Word Pattern (模拟)
题意: 给出一个模式串pattern,再给出一个串str,问str的模板是否是pattern. 思路: 注意点:只要对于所有pattern[i]相同的i,str中对应的所有words[i]也必须相同, ...
- 《JavaScript模式》第2章 基本技巧
@by Ruth92(转载请注明出处) 第2章 基本技巧 一.编写可维护的代码 阅读性好 具有一致性 预见性好 看起来如同一个人编写 有文档 编写注释 编写 API 文档 @namespace:用于命 ...
- 深入理解JVM内部结构(转)
图中显示的组件将会在下面两部分中进行逐一的解释.第一部分涉及JVM为每一个线程都会创建的组件:第二部分则是独立于线程进行创建的组件. 1. Thread Thread是一个程序中的一个 ...
- (实用篇)多个PHP中文字符串截取函数
字符串截取是一个非常常见的编程任务,而往往带中文的字符串截取会经常用到.虽然不难,但是自己写函数实现又耗费时间,这里介绍一个比较好用的字符串截取函数,能够胜任基本的需求了 <?php funct ...
- hdu 1542 Atlantis
求矩形的面积之和. 线段树+离散话+扫描线 #include<iostream> #include<cstdio> #include<cstdlib> #inclu ...
- textarea元素在加上runat="server"后运行报错解决
当出现这个报错的时候,在后台引用相应的命名空间,为 using System.Web.UI; using System.Web.UI.HtmlControls;using System.Web.UI. ...
- 装载:关于拉格朗日乘子法与KKT条件
作者:@wzyer 拉格朗日乘子法无疑是最优化理论中最重要的一个方法.但是现在网上并没有很好的完整介绍整个方法的文章.我这里尝试详细介绍一下这方面的有关问题,插入自己的一些理解,希望能够对大家有帮助. ...
- html--整站制作
1.样式初置 body,div,ul,ol,h1,h2,h3,h4,h5,p,form,input,textarea,select{margin:0;padding:0;} li{list-style ...
- XUtils解析
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ...
- JQuery中的push和join
和JS 中的JOIN 方法一样,将一数组按照JOIN的参数连接起来. 比如: var arr = [ "a", "b", "c", &quo ...