`
webdev2014
  • 浏览: 681750 次
文章分类
社区版块
存档分类
最新评论

acegi security实践教程—form认证

 
阅读更多
上篇博客给大家介绍了basic认证,同时也带领大家debug了一下源码,所以流程想必大家都已经了解了,那么现在只剩下各种认证的配置了。

具体步骤如下:

开发环境:

MyEclispe10.7.1+tomcat6.0.37+acegi1.0.5+spring2.0
项目目录如下: 其中readme主要用来记录本次验证目的

配置文件

web.xml:
 <?xml version="1.0" encoding= "UTF-8"?>
<web-app xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns= "http://java.sun.com/xml/ns/javaee" xmlns:web= "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version= "2.5">
  < display-name></display-name >
  <!-- spring 配置文件 -->
  < context-param>
    <param-name >contextConfigLocation </param-name >
    <param-value > 
            classpath:config/spring/spring-acegi.xml 
        </param-value >
  </ context-param>
 
  <!-- acegi对页面校验控制 -->
  < filter>
    <filter-name >AcegiFilterChainProxy </filter-name >
    <filter-class >
                org.acegisecurity.util.FilterToBeanProxy
            </filter-class >
    <init-param >
      <param-name >targetBean </param-name >
      <param-value >filterChainProxy </param-value >
    </init-param >
  </ filter>
  < filter-mapping>
    <filter-name >AcegiFilterChainProxy </filter-name >
    <url-pattern >/j_acegi_security_check </url-pattern >
  </ filter-mapping>
  < filter-mapping>
    <filter-name >AcegiFilterChainProxy </filter-name >
    <url-pattern >/j_acegi_logout </url-pattern >
  </ filter-mapping>
  < filter-mapping>
    <filter-name >AcegiFilterChainProxy </filter-name >
    <url-pattern >*.do </url-pattern >
  </ filter-mapping>
  < filter-mapping>
    <filter-name >AcegiFilterChainProxy </filter-name >
    <url-pattern >*.jsp </url-pattern >
  </ filter-mapping>
 
 
  < welcome-file-list>
      <welcome-file >index.jsp </welcome-file >
  </ welcome-file-list>
 
  <!-- spring配置 -->
  < listener>
       <listener-class >
        org.springframework.web.context.ContextLoaderListener
       </listener-class >
 </ listener>
</web-app> 

acegi配置文件:
 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns= "http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" >
     
     <!-- 通过过滤连形式,acegi提供很多filter,其中过滤器执行也有一定的顺序 ,同事支持正则和ant匹配-->
     
     <bean id ="filterChainProxy" class= "org.acegisecurity.util.FilterChainProxy" >
            <property name ="filterInvocationDefinitionSource">
                 <value >
                     PATTERN_TYPE_APACHE_ANT
                     /**=authenticationProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
                 </value >
            </property >
     </bean >

           
 <!-- 表单认证处理filter -->  
     <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"/> 
    </bean >
     
     <bean id ="authenticationManager"
            class= "org.acegisecurity.providers.ProviderManager" >
            <property name ="providers">
                 <list >
                      <ref local ="daoAuthenticationProvider" />
                 </list >
            </property >
     </bean >
     
     
    <!-- 从数据库中读取用户信息验证身份 -->
     <bean id ="daoAuthenticationProvider"
           class= "org.acegisecurity.providers.dao.DaoAuthenticationProvider" >
            <property name ="userDetailsService" ref= "inMemDaoImpl" />
     </bean >

    <!-- 基于内存实现方式-->
     <bean id ="inMemDaoImpl"
           class= "org.acegisecurity.userdetails.memory.InMemoryDaoImpl" >
            <property name ="userMap">
                 <value >
                     test=1,ROLE_USER
                     lisi=1,ROLE_SUPERVISOR
                     zhangsan=1,ROLE_SUPERVISOR,disabled
                 </value >
            </property >
     </bean >
     
     <!-- exception filter -->
   <bean id ="exceptionTranslationFilter" class= "org.acegisecurity.ui.ExceptionTranslationFilter" >
     <!-- 尚未登录, 进入非法(未认证不可访问)区域 -->  
        <property name ="authenticationEntryPoint">  
            <bean class= "org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint" > 
                <property name ="loginFormUrl" value= "/login.jsp"/>  <!--若没登陆,则转向 用户登陆页面 -->
                <property name ="forceHttps" value="false"/>   <!-- 是否强制使用https -->
            </bean > 
        </property >
     <!-- 登录后, 进入非授权区域 -->
        <property name ="accessDeniedHandler">  
            <bean class= "org.acegisecurity.ui.AccessDeniedHandlerImpl" > 
                <property name ="errorPage" value= "/accessDenied.jsp"/>  <!-- 进入无权限页面 ,根据需求写相应的信息-->
            </bean > 
        </property > 
    </bean >     
     
   <bean id ="filterInvocationInterceptor"
           class= "org.acegisecurity.intercept.web.FilterSecurityInterceptor" >
            <property name ="authenticationManager" ref= "authenticationManager" />
            <property name ="accessDecisionManager" ref= "httpRequestAccessDecisionManager" />
            <property name ="objectDefinitionSource">
                 <value ><![CDATA[
                     CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                     PATTERN_TYPE_APACHE_ANT
                     /userinfo.jsp=ROLE_SUPERVISOR
                 ]]></value>
            </property >
     </bean >

     <bean id ="httpRequestAccessDecisionManager"
            class= "org.acegisecurity.vote.AffirmativeBased" >
            <property name ="decisionVoters">
                 <list >
                      <bean class= "org.acegisecurity.vote.RoleVoter" />
                 </list >
            </property >
     </bean >
</beans>


讲解如下:

filterInvocationInterceptor配置了受保护的资源,访问userinfo.jsp则需要ROLE_SUPERVISOR权限。而其他的资源则不需要保护。
表单authenticationProcessingFilter认证,也是依靠认证管理器,并委托给Provider来实现。
<beanid="authenticationProcessingFilter"class= "org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<!-- 认证管理器,然后委托给Provides -->
<propertyname="authenticationManager"ref="authenticationManager"/>
<!-- 认证失败后转向的url,包含出错信息的的登陆页面 -->
<propertyname="authenticationFailureUrl"value="/login.jsp?login_error=1"/>
<!-- 登陆成功后转向的url -->
<propertyname="defaultTargetUrl"value="/userinfo.jsp"/>
<!-- 登陆的url,这个是默认的acegi自带的 -->
<propertyname="filterProcessesUrl"value="/j_acegi_security_check"/>
</bean>
其中的exception异常fiter,若没登陆,则转向登陆页面;若登陆了却访问了无权限资源,则转向accessDefined页面。

页面如下:

userinfo.jsp:显示用户信息
因为SecurityContextHolder容器中存放securitycontext,其中securitycontext存放Authentication对象。实际上Authentication和UserDetails很相似,只不过从后台取出来UserDetails转换到Authentication对象,存放到securitycontext
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import= "org.acegisecurity.context.SecurityContextHolder" %> 
<%@ page import ="org.acegisecurity.userdetails.*"%>  
<html>
<head>
<meta http-equiv= "Content-Type" content ="text/html; charset=UTF-8">
<title> 当前用户的具体信息 </title >
</head>
<body>
        当前用户: 
        <% 
            Object obj = SecurityContextHolder.getContext().getAuthentication();         
            if ( null != obj){ 
                Object userDetail = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 
                String username = ""; 
                String pwd= "";
                if (userDetail instanceof UserDetails) { 
                    username = ((UserDetails) userDetail).getUsername(); 
                    pwd = ((UserDetails) userDetail).getPassword(); 
                } else { 
                    username = userDetail.toString(); 
                } 
                out.print(username+ ",密码:"+pwd); 
            }
        %>        
</body>
</html>
登陆页:login.jsp:
<%@ page language ="java" pageEncoding="UTF-8"%>  
<%@ page import ="org.acegisecurity.ui.AbstractProcessingFilter" %> 
<%@ page import= "org.acegisecurity.ui.webapp.AuthenticationProcessingFilter" %>  
<%@ page import ="org.acegisecurity.AuthenticationException" %> 
<html>
<body >    
      <% 
        String strError = request.getParameter( "login_error");       
        if (null != strError){  
     %> 
      <font color ="red"> 
        你的登陆失败,请重试。 <BR ><BR > 
         原因: <%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %> 
      </font > 
      <% 
        }//end if 
      %> 
 
  < FORM METHOD= POST ACTION ="j_acegi_security_check">
  < table>
    <tr >
      <td >用户名: </td >
      <td ><input NAME ="j_username"  type= "text" title ="用户名" /></td>
    </tr >
    <tr >
      <td > 密码: </td >
      <td ><input   name ="j_password"  type= "text" title = "密码"/></td >
    </tr >
    <tr >
       <td > </td >
      <td > <input type ="submit" value="登陆"/></ td></ tr>
  </ table>  
     </FORM >
  </ body>

其中注意:用户名和密码的name必须是j_username和j_password,以及action必须是j_acegi_security_check,这是acegi规则。

测试如下:

1.第一次运行userinfo.jsphttp://localhost:8080/acegitest2/userinfo.jsp
2.因为访问受保护资源,没有登录,则转到登陆页面
3.输入无权限用户,test/1,因为无权限,则转向accessDefined页面
4.输入有权限用户,lisi/1,则成功转向到userinfo.jsp
sendRedirect(request, response, targetUrl);
OK,运行成功了,这篇博客实践源码:
ps:关闭浏览器,重新再打开浏览器,运行http://localhost:8080/acegitest2/userinfo.jsp,测试一下会出现啥现象?再换个浏览器比如谷歌,运行url会出现啥现象?这个现象的原因能猜到吗?


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics