`

【SSI开发总结.4】Spring中使用Acegi安全框架

 
阅读更多

Acegi认证授权主要基于两大技术,一是Filter机制,二是AOP的拦截 机制。通过FilterSecurityInterceptor很好地实现了对URI的保护,通过MethodSecurityInterceptor实 现了对Service的方法的拦截保护,通过ACL 实现了对prototype类型的Object进行过滤和保护。

HttpSessionContextIntegrationFilter 存储SecurityContext in HttpSession
ChannelProcessingFilter 重定向到另一种协议,如http到https

ConcurrentSessionFilter 因为不使用任何SecurityContextHolder的功能,但是需要更新SessionRegistry来表示当前的发送请求的 principal,通过在web.xml中注册Listener监听Session事件,并发布相关消息,然后由SessionRegistry获得消 息以判断当前用户的Session数量。

AuthenticationProcessingFilter 普通认证机制(大多数用这个)

CasProcessingFilter CAS认证机制

BasicProcessingFilter Http协议的Basic认证机制

HttpRequestIntegrationFilter Authentication 从容器的HttpServletRequest.getUserPrincipal()获得

JbossIntegrationFilter 与Jboss相关。

SecurityContextHolderAwareRequestFilter 与servlet容器结合使用。

RememberMeProcessingFilter 基于Cookies方式进行认证。

AnonymousProcessingFilter 匿名认证。

ExceptionTranslationFilter 捕获所有的Acegi Security 异常,这样要么返回一个HTTP错误响应或者加载一个对应的AuthenticationEntryPoint

AuthenticationEntryPoint 认证入口

Acegi认证授权流程
1、FilterToBeanProxy 负责代理请求给FilterChainProxy

2、FilterChainProxy 方便的将多个Filter串联起来,如上面基本概念中提到的各种Filter,当然如果对URI进行授权保护,也可以包含FilterSecurityInterceptor。注意各Filter的顺序。

3、AbstractSecurityInterceptor 调度中心。负责调用各模块完成相应功能。
FilterSecurityInterceptor 对URI进行拦截保护
AspectJSecurityInterceptor 对方法进行拦截保护
MethodSecurityInterceptor 对方法进行拦截保护

4、AuthenticationManager 用户认证
-> AuthenticationProvider 实际进行用户认证的地方(多个)。
-> UserDetailsService 返回带有GrantedAuthority的UserDetail或者抛出异常。

5、AccessDecisionManager(UnanimousBased/AffirmativeBased/ConsensusBased) 授权
-> AccessDecisionVoter(RoleVoter/BaseAclEntryVoter) 实际投票的Voter(多个).

6、RunAsManager 变更GrantedAuthority

7、AfterInvocationManager 变更返回的对象
-> BaseInvocationProvider 实际完成返回对象变更的地方(多个)。

在我的项目中,用ACEGI实现了会员系统的权限控制操作

1.配置web.xml

/****** /web-inf/web.xml ******/

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>game_proj</display-name>
<!-- 中文语言支持过滤器 -->
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>com.popoann.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<!-- Acegi过滤器 -->
<filter-name>acegiFilterChain</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>
<!-- Acegi过滤器URL映射 -->
<filter-mapping>
<filter-name>acegiFilterChain</filter-name>
<url-pattern>*.htm</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>acegiFilterChain</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>acegiFilterChain</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>

<!-- ActionContextCleanUp过滤器 -->
<filter>
<filter-name>struts-cleanup</filter-name>
<filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
</filter>
<filter-mapping>
<filter-name>struts-cleanup</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- SiteMesh的核心过滤器 -->
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Struts核心过滤器 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>struts.action.extension</param-name>
<param-value>htm</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 应用程序启动时,加载SpringIoC容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/beans-*.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 欢迎页面 -->
<welcome-file-list>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>

</web-app>

2.配置spring bean

/****** /web-inf/beans-myspace_security.xml ******/

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<!-- 1.配制认证管理器(AuthenticationManager) -->
<bean id="myspace_authenticationManager"
class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref bean="myspace_daoAuthenticationProvider"/>
<ref bean="myspace_rememberMeAuthenticationProvider"/>
</list>
</property>
</bean>

<!-- 表示通过DAO接口进行数据库验证 -->

<!-- 指定userDetailsService,表示用户列表由这个类得到,后面编程实现这个自定义用户列表类 -->

<!-- 指定passwordEncoder,表示在验证之前,对表单中的密码先进行指定编码方式的加密,这里为MD5加密策略 -->
<bean id="myspace_daoAuthenticationProvider"
class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="myspace_userDetailsBo"/>
<property name="passwordEncoder" ref="myspace_passwordEncoder"/>
</bean>
<bean id="myspace_passwordEncoder"
class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/>

<!-- 表示通过COOKIES进行验证 -->
<bean id="myspace_rememberMeAuthenticationProvider"
class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key" value="myspace_remember_me"/>
</bean>


<!-- 2.配制决策管理器(AccessDecisionManager) -->
<bean id="myspace_accessDecisionManager"
class="org.acegisecurity.vote.AffirmativeBased">
<property name="decisionVoters">
<list>
<bean class="org.acegisecurity.vote.RoleVoter"/>
</list>
</property>
<property name="allowIfAllAbstainDecisions" value="false"/>
</bean>
<!-- 3.配制拦截器链(FilterChain) -->
<bean id="myspace_filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>


PATTERN_TYPE_APACHE_ANT
/myspace/*.htm*=myspace_httpSessionContextIntegrationFilter,myspace_logoutFilter,myspace_authenticationProcessingFilter,myspace_rememberMeFilter,myspace_exceptionFilter,myspace_securityInterceptor
/**=myspace_httpSessionContextIntegrationFilter,myspace_logoutFilter,myspace_authenticationProcessingFilter,myspace_rememberMeFilter,myspace_exceptionFilter,myspace_securityInterceptor

</value>
</property>
</bean>
<!-- (1) Session会话验证拦截器-->
<bean id="myspace_httpSessionContextIntegrationFilter"
class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>
<!-- (2) 注销功能拦截器-->
<bean id="myspace_logoutFilter"
class="org.acegisecurity.ui.logout.LogoutFilter">
<!-- 注销后默认的跳转页面 -->
<constructor-arg value="/login.htm"/>
<constructor-arg>
<list>
<ref bean="myspace_rememberMeServices"/>
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
<!-- 用户注销URL -->
<property name="filterProcessesUrl" value="/j_logout.do"/>
</bean>
<!-- (3) -->
<bean id="myspace_authenticationProcessingFilter"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager" ref="myspace_authenticationManager"/>
<!-- 登录失败的页面,通常包含出错信息的登录页面 -->
<property name="authenticationFailureUrl" value="/login!error.htm"/>
<!-- 登录后默认跳转页面 -->
<property name="defaultTargetUrl" value="/myspace/hellouser.htm"/>
<!-- 用户登录URL -->
<property name="filterProcessesUrl" value="/j_login.do"/>
<property name="rememberMeServices" ref="myspace_rememberMeServices"/>
</bean>
<!-- (4) cookies验证拦截器-->
<bean id="myspace_rememberMeFilter"
class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<property name="authenticationManager" ref="myspace_authenticationManager"/>
<property name="rememberMeServices" ref="myspace_rememberMeServices"/>
</bean>
<bean id="myspace_rememberMeServices"
class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="myspace_userDetailsBo"/>
<property name="parameter" value="myspace_remember_me"/>
<property name="key" value="myspace_remember_me"/>
<property name="tokenValiditySeconds" value="31536000"/>
</bean>
<!-- (5) -->
<bean id="myspace_exceptionFilter"
class="org.acegisecurity.ui.ExceptionTranslationFilter">
<!-- 出现AuthenticationException时的登陆入口 -->
<property name="authenticationEntryPoint">
<bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.htm"/>
<property name="forceHttps" value="false"/>
</bean>
</property>

<!-- 指定错误页,当前角色不能访问本资源时,定位到错误页 -->
<!-- 出现AccessDeniedException时的handler -->
<property name="accessDeniedHandler">
<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/error.jsp" />
</bean>
</property>
</bean>
<!-- (6) 安全拦截器,整合认证和决策管理器,并定义各种目录结构对应的角色,可用ANT表达式-->
<bean id="myspace_securityInterceptor"
class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="myspace_authenticationManager"/>
<property name="accessDecisionManager" ref="myspace_accessDecisionManager"/>
<property name="objectDefinitionSource">
<value>
PATTERN_TYPE_APACHE_ANT
/myspace/sales_*.htm*=ROLE_SALES_USER
/myspace/provide_*.htm*=ROLE_PROVIDE_USER

</value>
</property>
</bean>
</beans>

一定要注意Filter的配置顺序,还有更多Filter,不过以上足够了

3.编写UserDetails类

/****** myspace_userDetailsBo.java ******/

package bo;

import org.acegisecurity.userdetails.UserDetailsService;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.User;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.springframework.dao.DataAccessException;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.GrantedAuthority;
import bo.UserBo;
import java.util.*;

public class UserDetailsBo implements UserDetailsService {

//定义两个角色
private final GrantedAuthority ROLE_SALES_USER=new GrantedAuthorityImpl("ROLE_SALES_USER");
private final GrantedAuthority ROLE_PROVIDE_USER=new GrantedAuthorityImpl("ROLE_PROVIDE_USER");


private UserBo bo;
private model.User user;
private List< model.User> myusers;
private Map<String,String> users=new HashMap<String,String>();;
private GrantedAuthority[] authorities;
//注入业务对象的同时,把得到的用户列表依次拷贝的一个HashMap对象中
public void setBo(UserBo bo) {
this.bo = bo;
myusers=bo.getUserList();
users.put("test", "test");
for(model.User user:myusers){
users.put(user.getUsername().trim(), user.getPassword().trim());
System.out.println(user.getUsername().trim()+"=="+user.getPassword().trim());
}
}
public UserDetailsBo(){

}
/* 必须实现这个接口方法,改方法表示在验证之前,该用户是否存在,如果不存在,当然就没有验证的必要了,如果存在,之前通过表单得到的用户名,密码就要和本类中定义的Hashmap中存在的用户密码名值对做对比,然后根据spring bean配置实现验证 */
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
// TODO Auto-generated method stub
System.out.println(username);
String password=users.get(username);
if(password==null)
throw new UsernameNotFoundException("No such user");
System.out.println(password);
if(bo.getUser(username).getType()==1)
authorities=new GrantedAuthority[]{ROLE_SALES_USER};
else
authorities=new GrantedAuthority[]{ROLE_PROVIDE_USER};
return new User(username,password,true,true,true,true,authorities);
}

}

4. 根据配置,制作登录表单

<table width="167" height="80" border="0" cellpadding="0" cellspacing="0">
<form onSubmit="return doValidate('_login')" id="_login" name="_login" method="post" action="j_login.do">
<tr class="style3">
<td width="60" align="right" class="style3"><span class="STYLE9 style3">用户名:</span></td>
<td width="107"><input name="j_username " type="text" class="STYLE9 " id="j_username" size="15" /></td>
</tr>
<tr class="style3">
<td align="right" class="style3"><span class="STYLE9 style3">密&nbsp;&nbsp;码:</span></td>
<td><input name="j_password " type="password" class="STYLE9 " id="j_password" size="15" /></td>
</tr>
<tr class="style3">
<td colspan="2" align="center"><table width="100%" height="27" border="0" cellpadding="0" cellspacing="0">
<tr>
<td align="center" class="style2"><input style=" background-image:url(images/btnbg.gif); width:67px; height:22px" type="submit" name="Submit" value="登录" /><input type="checkbox" name="myspace_remember_me "/>
记住用户</td>
</tr>
</table></td>
</tr>
</form>
</table>

注意高亮的三个地方,用户名和密码的字段必须是j_username,j_password,myspace_remember_me这个名称显然 要和spring bean配置中,myspace_rememberMeAuthenticationProvider这个bean的key属性对应

到此,安全验证完成。

分享到:
评论

相关推荐

    ssi框架中需要的spring包

    你提到的"ssi框架中需要的spring包"可能是理解上的误解,因为Spring是一个广泛使用的Java应用框架,而非与SSI直接关联。 Spring框架是Java企业级应用开发的核心工具,它提供了全面的基础设施支持,包括依赖注入、...

    DWC_ssi_user.pdf

    这意味着用户在使用 SSI 核心时,应该自己承担风险,并且 Synopsys 不承担因使用该产品而产生的任何责任。 ### 六、商标 文档中提到了 Synopsys 和其产品的商标信息,并提供了链接供用户查看。此外,还提到其他...

    图文搭建SSI(struts+spring+ibatis)框架

    本文将详细介绍如何使用MyEclipse8.5进行SSI(Struts2、Spring2.5、iBatis)框架的整合搭建。首先,我们需要一个新的Web项目作为基础。 1. **创建Web Project** 在MyEclipse8.5中,选择`File` -&gt; `New` -&gt; `...

    ssi框架总结及实例

    SSI框架,全称为Struts2、Spring、Ibatis集成框架,是一种常见的Java Web开发解决方案。该框架结合了三个流行的开源框架,旨在简化开发流程,提高代码的可维护性和可扩展性。下面将详细介绍这三个框架以及它们如何在...

    SSI+SSH框架

    总结起来,SSH与SSI框架组合提供了全面的Java Web开发解决方案,涵盖了从数据持久化到用户界面,再到安全性管理的各个方面。理解并熟练运用这些框架,可以帮助开发者构建出高效、安全且易于维护的应用程序。

    手把手构建Maven企业级应用(整合SSI框架).pdf

    4. **整合SSI框架**:在各个子模块中,引入Spring、Struts2和iBatis(现称为MyBatis)的相关依赖,并配置相应的XML文件,如Spring的`applicationContext.xml`、Struts2的`struts.xml`和MyBatis的`mybatis-config.xml...

    SSI_Library.rar_SSI_SSI Verilog_logic_ssi verilog_verilog ssi

    在现代数字系统设计中,SSI仍然作为理解数字逻辑设计的基础。Verilog是一种硬件描述语言(HDL),用于描述和模拟数字电子系统的逻辑行为。本压缩包“SSI_Library.rar”似乎包含了一组使用Verilog编写的SSI逻辑门的...

    fsl_ssi_dbg.rar_SOC

    在实际应用中,开发人员会使用这些调试工具来优化音频质量,确保系统在不同工作条件下都能稳定运行。这可能涉及到调整缓冲区大小、优化中断服务例程或者改善硬件同步策略。通过深入理解"Fsl_ssi_dbg.c"中的代码,...

    SSH/SSI框架

    SSH(Struts + Spring + Hibernate)和SSI(Spring Security + Spring + Hibernate)是两种常见的Java Web开发框架,它们被广泛用于构建高效、可维护的Web应用程序。这些框架结合了各自的优点,提供了强大的功能和...

    SSI-ABZ.rar_FPGA ABZ_FPGA SSI_SSI 转 ABZ信号FPAG程序_abz_ssi fpga

    压缩包内的文件"SSI-ABZ"可能是设计文件、配置文件或者是编译后的.bit文件,这些文件用于在FPGA开发工具如Xilinx Vivado、Intel Quartus或Aldec Active-HDL中加载到目标FPGA设备上,实现所述的信号转换功能。...

    eclipse开发的ssi整合struts2+ibatis2.x+spring2.5

    在IT行业中,集成Struts2、iBatis2.x和Spring2.5是常见的企业级应用开发模式,这种架构被称为“SSH”(Struts、Spring、Hibernate)的变种,因为iBatis替代了传统的Hibernate作为持久层框架。Eclipse作为Java开发的...

    omap_ssi_port.rar_SSI

    OMAP SSI Port驱动程序是针对德州仪器(TI)OMAP系列微处理器中串行外设接口(Serial Slave Interface,SSI)的特定实现。SSI在嵌入式系统中被广泛用作高速数据传输机制,特别是在音频、视频和图像处理应用中。这个...

    SSI框架 spring Struts ibatis

    通过学习这个项目,初学者可以深入理解SSI框架的集成方式,以及如何在实际开发中利用这些框架的优势。例如,Struts如何处理用户请求,Spring如何管理对象和事务,以及iBatis如何执行SQL并返回结果。此外,还可以学习...

    PyPI 官网下载 | galileo-ssi-1.2.tar.gz

    4. **Python库**:作为Python库,"galileo-ssi"提供了一组Python编程接口(APIs),让开发人员能够轻松地在他们的Python项目中利用其功能,例如处理分布式系统的协调或云原生应用的构建。 在解压"galileo-ssi-1.2....

    SSI框架整合例子(spring+struts+ibatis)

    在IT行业中,集成多种框架以构建复杂的企业级应用是一种常见的做法。本示例"SSI框架整合例子(spring+...通过这个"SSI框架整合例子",开发者可以深入理解如何在大型项目中有效地集成和使用这些流行框架,提升开发效率。

    SSH和SSI等框架常用基础配置web.xml

    对于使用SSH(Struts + Spring + Hibernate)和SSI(Struts + Spring + iBatis)等框架的应用程序而言,合理的`web.xml`配置至关重要。本文将详细介绍`web.xml`中的关键配置项,并解释其作用。 #### 一、`web.xml`...

    SSI_read.rar_SSI verilog_SSI 11bit read_SSI_read_ssi verilog_v

    SSI(Synchronous Serial Interface,同步串行接口)是一种在数字系统中常见的通信协议,用于传输数据。在本项目中,我们关注的是...通过这个项目,你可以深入理解如何在实际应用中使用Verilog来处理复杂的通信任务。

    ssi_rx.rar_SSI_SSI VHDL_VHDL SSI_uart_vhdl

    标题中的"SSI_rx.rar_SSI_SSI VHDL_VHDL SSI_uart_vhdl"表明这是一个关于SSI(Synchronous Serial Interface)串行同步接口接收部分的VHDL设计项目,使用了Xilinx ISE作为开发环境,并且包含了UART(Universal ...

    s2si框架 ssi框架 structs2+spring+ibatis组合框架(内含例子)

    "S2SI框架",全称为"Structs2+Spring+Ibatis集成框架",是一种基于Java的Web开发框架,旨在简化企业级应用的开发过程。该框架结合了三个流行的开源组件——Structs2、Spring和Ibatis,以提供一个高效、灵活且易于...

Global site tag (gtag.js) - Google Analytics