acegi security实践教程—访问系统中资源前必须登陆系统

问题:

处于安全角度,访问本系统时,是需要登陆才可以访问其下的资源。根据上篇博客的调试,我们发现,若其url在数据库中没有没有配置其角色,则是可以直接访问其url的。
那为了避免这种情况,我们如何改进自己的系统,进一步接近真实的企业开发呢?
概要:
这节我们将会讲到匿名权限,securitycontext中随时都包含权限,而不是只有登录后才有。
进一步改进上一篇博客中自定义objectDefinitionSource类,因为若返回null,则直接进入其url。

具体开发:
开发环境:

MyEclispe10.7.1+tomcat6.0.37+acegi1.0.5+spring2.0+jdk1.6【其中数据库和数据结构保持不变】
项目目录如下:
其中readme主要用来记录本次验证目的

配置匿名Filter:

<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,
anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
</value>
</property>
</bean>
    <!--匿名过滤器 -->
    <bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
      <!-- 其中key随意提供一个名字即可,但是必须提供,类似用户名 -->
      <property name="key" value="test"></property>
      <!-- userAttribute提供了其密码和相应的角色 -->
      <property name="userAttribute" value="testpwd,ROLE_ANONYMOUS"></property>
    </bean>

配置原因:

根据以往的经验,我们还是来看其源码,为什么必须提供key以及userAttribute呢?
doFilter中的:
SecurityContextHolder.getContext().setAuthentication(createAuthentication(request));
而createAuthentication代码如下:
protected Authentication createAuthentication(ServletRequest request) {
Assert.isInstanceOf(HttpServletRequest.class, request,
"ServletRequest must be an instance of HttpServletRequest");
AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(key, userAttribute.getPassword(),
userAttribute.getAuthorities());
auth.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request));
return auth;
}
而AnonymousAuthenticationToken代码:
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);
}
所以key、principal【密码】、authorities三个属性必须配置,通过这三个属性来new一个匿名的权限,然后存放到securitycontext中,这样SecurityContextHolder.getContext().getAuthentication()中的权限不是null,而是匿名的权限,其中角色信息ROLE_ANONYMOUS
完善自定义objectDefinitionSource类:
若是保护资源,则返回数据库中其对应的角色信息;若不是保护资源,我们不返回null,否则直接进入其url,我们返回一个自定义角色信息。
//若是保护的资源
if(matched){
//进一步查询此url的角色权限
String urlRole="select role from test_resource_role where url=?";
List<Map> roleList=this.jdbcTemplate.queryForList(urlRole,new Object[]{url});
return converURLRole(roleList);
}
ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition();
configDefinition.addConfigAttribute(new SecurityConfig("IS_AUTHENTICATED_FULLY"));
return configDefinition;
这样改进后,我们再看看AbstractSecurityInterceptor中的beforeInvocation方法:

结果讲解:

投票失败后,则根据错误分类信息,转向不同的页面。
另一个注意点:
若想登陆成功后一直转到默认页面而非访问的目的地时,如何操作?
比如:访问http://localhost/acegitest8/test.jsp,首先出现login.jsp页面,若登陆成功后,你想跳转到默认的/userinfo.jsp页面。跳转之后,再访问http://localhost/acegitest8/test.jsp。
无论何种情况,只要登陆后就转到acegi.xml默认的配置页面。如何配置?
AuthenticationProcessingFilter中alwaysUseDefaultTargetUrl属性默认情况为false,所以只要我们在aceg.xml配置为true即可。
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<!-- 认证管理器,然后委托给Provides -->
<property name="authenticationManager" ref="authenticationManager"/>
<!-- 认证失败后转向的url,包含出错信息的的登陆页面 -->
<property name="authenticationFailureUrl" value="/login.jsp?login_error=1"/>
<!-- 登陆成功后转向的url -->
<property name="defaultTargetUrl" value="/userinfo.jsp"/>
<!-- 登陆的url,这个是默认的acegi自带的 -->
<property name="filterProcessesUrl" value="/j_acegi_security_check"/>
<!-- 永远转到登陆成功后默认的目的地,如上文/userinfo.jsp -->
<property name="alwaysUseDefaultTargetUrl" value="true"/>
</bean>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值