论坛首页 Java企业应用论坛

浅谈Acegi配置

浏览 72284 次
该帖已经被评为良好帖
作者 正文
   发表时间:2007-03-11  
不错,写的很清楚,看了之后总体上更加清楚了
0 请登录后投票
   发表时间:2007-03-13  
管理员大哥,这里边的内容能不能不要两边拉动啊。看起来真烦哦。
0 请登录后投票
   发表时间:2007-03-14  
您写到:只有在服务器上配置哪个目录在访问的时候用HTTP基本认证,它才会起作用(一开始还以为是Acegi的BUG呢)

怎么配:配置哪个目录在访问的时候用HTTP基本认证呀?

谢谢!
0 请登录后投票
   发表时间:2007-03-15  

daquan198163 写道:
请教几个问题:
1、密码加密如何处理;
2、select username,authority from authorities where username=?取出的authority是什么,应该是role吧;
3、如果像“/ok.html=ROLE_USER”这样配置,当系统运行期间,role的增删改如何处理;


1.密码加密

  原理解析:

(1)authenticationProcessingFilter 中会从你的登陆页面获得用户名和密码

 (2)userDetatilService.loadUserByUsername(String username)需要你根据用户名把用户的信息(

 用户名,密码,用户权限)放到你自己的UserDetail;

(3) 调用daoAuthenticationProvider中的passwordEncoder对页面密码进行加密,判断与数据库得到的密钥

     是否相等;

<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
    <property name="userDetailsService">
      <ref local="userDetailsService"/>
    </property>
    <property name="passwordEncoder">
      <ref local="passwordEncoder"/>
      <!--密码加密算法,客户端输入的密码是明文,但是数据库可能是密钥-->
    </property>

</bean>

2.是权限

3.只能自己扩展objectDefinitionSource扩展方式

0 请登录后投票
   发表时间:2007-03-17  
正在学习这东西,感谢楼主!
0 请登录后投票
   发表时间:2007-03-17  

ahau205109 写道:

daquan198163 写道:
请教几个问题:
1、密码加密如何处理;
2、select username,authority from authorities where username=?取出的authority是什么,应该是role吧;
3、如果像“/ok.html=ROLE_USER”这样配置,当系统运行期间,role的增删改如何处理;


1.密码加密

  原理解析:

(1)authenticationProcessingFilter 中会从你的登陆页面获得用户名和密码

 (2)userDetatilService.loadUserByUsername(String username)需要你根据用户名把用户的信息(

 用户名,密码,用户权限)放到你自己的UserDetail;

(3) 调用daoAuthenticationProvider中的passwordEncoder对页面密码进行加密,判断与数据库得到的密钥

     是否相等;

<bean class="org.acegisecurity.providers.dao.DaoAuthenticationProvider" id="daoAuthenticationProvider"></bean>
    <property name="userDetailsService">
      <ref local="userDetailsService"></ref>
    </property>
    <property name="passwordEncoder">
      <ref local="passwordEncoder"></ref>
      <!---->
    </property>

 

2.是权限

3.只能自己扩展objectDefinitionSource扩展方式


本人还是最总关心第三个问题

哪有写好了objectDefinitionSource的扩展??

期待中。。。。。。


0 请登录后投票
   发表时间:2007-03-17  

晨星★~雨泪 写道:

ahau205109 写道:

daquan198163 写道:
请教几个问题:
1、密码加密如何处理;
2、select username,authority from authorities where username=?取出的authority是什么,应该是role吧;
3、如果像“/ok.html=ROLE_USER”这样配置,当系统运行期间,role的增删改如何处理;


1.密码加密

  原理解析:

(1)authenticationProcessingFilter 中会从你的登陆页面获得用户名和密码

 (2)userDetatilService.loadUserByUsername(String username)需要你根据用户名把用户的信息(

 用户名,密码,用户权限)放到你自己的UserDetail;

(3) 调用daoAuthenticationProvider中的passwordEncoder对页面密码进行加密,判断与数据库得到的密钥

     是否相等;

<bean class="org.acegisecurity.providers.dao.DaoAuthenticationProvider" id="daoAuthenticationProvider"></bean>
    <property name="userDetailsService">
      <ref local="userDetailsService"></ref>
    </property>
    <property name="passwordEncoder">
      <ref local="passwordEncoder"></ref>
      <!---->
    </property>

 

2.是权限

3.只能自己扩展objectDefinitionSource扩展方式


本人还是最总关心第三个问题

哪有写好了objectDefinitionSource的扩展??

期待中。。。。。。

  且看配置:

   objectDefinitionSource :  FilterInvocationDefinitionSource

  FilterInvocationDefinitionSourceEditor类

加载权限方法:

权限定义:

s参数值格式如下:

CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
        PATTERN_TYPE_APACHE_ANT
        /secure/extreme/**=ROLE_SUPERVISOR
        /secure/**=IS_AUTHENTICATED_REMEMBERED
        /**=IS_AUTHENTICATED_ANONYMOUSLY

public void setAsText(String s) throws IllegalArgumentException {
        FilterInvocationDefinitionDecorator source = new FilterInvocationDefinitionDecorator();

        if ((s == null) || "".equals(s)) {
            // Leave target object empty
            source.setDecorated(new RegExpBasedFilterInvocationDefinitionMap());
        } else {
            // Check if we need to override the default definition map
            if (s.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) {
                source.setDecorated(new PathBasedFilterInvocationDefinitionMap());

                if (logger.isDebugEnabled()) {
                    logger.debug(("Detected " + DIRECTIVE_PATTERN_TYPE_APACHE_ANT
                        + " directive; using Apache Ant style path expressions"));
                }
            } else {
                source.setDecorated(new RegExpBasedFilterInvocationDefinitionMap());
            }

            if (s.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Detected " + DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                        + " directive; Instructing mapper to convert URLs to lowercase before comparison");
                }

                source.setConvertUrlToLowercaseBeforeComparison(true);
            }

            BufferedReader br = new BufferedReader(new StringReader(s));
            int counter = 0;
            String line;

            List mappings = new ArrayList();

            while (true) {
                counter++;

                try {
                    line = br.readLine();
                } catch (IOException ioe) {
                    throw new IllegalArgumentException(ioe.getMessage());
                }

                if (line == null) {
                    break;
                }

                line = line.trim();

                if (logger.isDebugEnabled()) {
                    logger.debug("Line " + counter + ": " + line);
                }

                if (line.startsWith("//")) {
                    continue;
                }

                // Attempt to detect malformed lines (as per SEC-204)
                if (line.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1) {
                    // Directive found; check for second directive or name=value
                    if ((line.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) || (line.lastIndexOf("=") != -1)) {
                        throw new IllegalArgumentException("Line appears to be malformed: " + line);
                    }
                }

                // Attempt to detect malformed lines (as per SEC-204)
                if (line.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) {
                    // Directive found; check for second directive or name=value
                    if ((line.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1)
                        || (line.lastIndexOf("=") != -1)) {
                        throw new IllegalArgumentException("Line appears to be malformed: " + line);
                    }
                }

                // Skip lines that are not directives
                if (line.lastIndexOf('=') == -1) {
                    continue;
                }

                if (line.lastIndexOf("==") != -1) {
                    throw new IllegalArgumentException("Only single equals should be used in line " + line);
                }

                // Tokenize the line into its name/value tokens
                // As per SEC-219, use the LAST equals as the delimiter between LHS and RHS
                String name = StringSplitUtils.substringBeforeLast(line, "=");
                String value = StringSplitUtils.substringAfterLast(line, "=");

                if (!StringUtils.hasText(name) || !StringUtils.hasText(value)) {
                    throw new IllegalArgumentException("Failed to parse a valid name/value pair from " + line);
                }

                // Attempt to detect malformed lines (as per SEC-204)
                if (source.isConvertUrlToLowercaseBeforeComparison()
                    && source.getDecorated() instanceof PathBasedFilterInvocationDefinitionMap) {
                    // Should all be lowercase; check each character
                    // We only do this for Ant (regexp have control chars)
                    for (int i = 0; i < name.length(); i++) {
                        String character = name.substring(i, i + 1);

                        if (!character.toLowerCase().equals(character)) {
                            throw new IllegalArgumentException("You are using the "
                                + DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                                + " with Ant Paths, yet you have specified an uppercase character in line: " + line
                                + " (character '" + character + "')");
                        }
                    }
                }

                FilterInvocationDefinitionSourceMapping mapping = new FilterInvocationDefinitionSourceMapping();
                mapping.setUrl(name);

                String[] tokens = org.springframework.util.StringUtils
                        .commaDelimitedListToStringArray(value);

                for (int i = 0; i < tokens.length; i++) {
                    mapping.addConfigAttribute(tokens[i].trim());
                }

                mappings.add(mapping);
            }
            source.setMappings(mappings);
        }

        setValue(source.getDecorated());
    }

  
=========================================

定义自己的类:

package common.spring.acegi.business;

import java.util.*;

import org.acegisecurity.*;
import org.acegisecurity.intercept.*;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
import org.acegisecurity.intercept.web.FilterInvocationDefinitionDecorator;
import org.acegisecurity.intercept.web.PathBasedFilterInvocationDefinitionMap;
import org.acegisecurity.intercept.web.FilterInvocationDefinitionSourceMapping;

import common.spring.acegi.vo.PreviligeVo;

public class MObjectDefinitionSource implements ObjectDefinitionSource {
    private MObjectDefinitionSource() {

    }

    private static MObjectDefinitionSource mobjectDefinitionSource;
    public MObjectDefinitionSource getInstance() {
        if (mobjectDefinitionSource == null) {
            mobjectDefinitionSource = new MObjectDefinitionSource();
        }
        return mobjectDefinitionSource;
    }

    private static final Log logger = LogFactory.getLog(
            MObjectDefinitionSource.class);
    private boolean lowercase = true; //采取的匹配模式
    //Object 是FillterInvocation
    public ConfigAttributeDefinition getAttributes(Object object) throws
            IllegalArgumentException {
        if (!init) {
            this.initConfigAttributeDefinitions();
        }
        return source.getAttributes(object);
    }

    public Iterator getConfigAttributeDefinitions() {
        if (!init) {
            this.initConfigAttributeDefinitions();
        }
        return source.getConfigAttributeDefinitions();
    }

    public boolean supports(Class clazz) {
        return true;
    }

    public void setLowercase(boolean lowercase) {
        this.lowercase = lowercase;
    }

    public void setPreviligeType(Integer[] previligeType) {
        this.previligeType = previligeType;
    }

    public boolean isLowercase() {
        return lowercase;
    }

    public Integer[] getPreviligeType() {
        return previligeType;
    }

    //需要加载的权限类型
    private Integer[] previligeType;
    private static FilterInvocationDefinitionDecorator source;
    private static boolean init = false;
    /*
     * 功能:重新更新权限列表
     **/
    public static void refreshSource() {
        mobjectDefinitionSource.initConfigAttributeDefinitions();
    }

    /*
     * 加载权限
     **/
    private void initConfigAttributeDefinitions() {
        source = null;
        //查找系统的权限
        source = new FilterInvocationDefinitionDecorator();
        source.setDecorated(new PathBasedFilterInvocationDefinitionMap());
        source.setConvertUrlToLowercaseBeforeComparison(this.lowercase);
        List mappings = new ArrayList();
        PreviligeVo vo[] = PreviligeFactory.loadPrevilige(this.previligeType);
        if (vo == null) {
            vo = new PreviligeVo[0];
        }
        for (int i = 0; i < vo.length; i++) {
            FilterInvocationDefinitionSourceMapping mapping = new
                    FilterInvocationDefinitionSourceMapping();
            mapping.setUrl(vo[i].getCode()); //其实就是url 如 /login.html
            mapping.setConfigAttributes(Arrays.asList(vo[i].getRole())); //login.html里的角色
            mappings.add(mapping);
        }
        source.setMappings(mappings);
        init = true;
    }

}





0 请登录后投票
   发表时间:2007-03-21  
我在acegi中用到了remembeme,但是在页面上选择rememberme之后没有任何反映,还得手动登陆。
cookies里的相关信息:ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE
YWRtaW46MTE3NTY3NDk3ODc5NjphYjEzNzk3YzMxYmRkMDg3YjQ2MTY0YjIzOWRlOTlmZQ==
172.10.0.40/acegiPlatform
1536
2108775680
30213545
575214272
29846418
*

不知道还有哪里没配到的,以下是相关的配置:
1.login.jsp中加入了一个单选钮:保存我的信息<input type="checkbox" name="rememberme"/>
2.认证filter
bean id="authenticationProcessingFilter"
		class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
		<property name="authenticationManager"
			ref="authenticationManager" />
		<!-- 登陆失败转向页 -->
		<property name="authenticationFailureUrl"
			value="/jsp/login.jsp?login_error=1" />
		<!-- 登陆成功转向页 -->
		<property name="defaultTargetUrl" value="/jsp/s.jsp" />
		<!-- 对应表单的action请求 -->
		<property name="filterProcessesUrl"
			value="/jsp/j_acegi_security_check" />
		<property name="rememberMeServices" ref="rememberMeServices" />
		<property name="exceptionMappings">
			<value>
				org.acegisecurity.AuthenticationException=/jsp/login.jsp?login_error=user_psw_error
				org.acegisecurity.concurrent.ConcurrentLoginException=/jsp/login.jsp?login_error=too_many_user_error
			</value>
		</property>
	</bean>

3.认证管理器
<bean id="authenticationManager"
		class="org.acegisecurity.providers.ProviderManager">
		<property name="providers"><!-- 可有多个认证提供器,其中一个证通过就可以了 -->
			<list>
				<ref local="rememberMeAuthenticationProvider" />
				<ref local="daoAuthenticationProvider" />
				<ref local="anonymousAuthenticationProvider" />
			</list>
		</property>
		<property name="sessionController">
			<ref bean="concurrentSessionController" />
		</property>

	</bean>

4.
<!--
		当SecurityContextHolder中不存在Authentication.用户授权信息,
		rememberMeProcessingFilter就会调用autoLogin()方法从cookie中获取用户信息,在验证filter之前使用
	-->
	<bean id="rememberMeProcessingFilter"
		class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
		<property name="authenticationManager"
			ref="authenticationManager" />
		<property name="rememberMeServices" ref="rememberMeServices" />
	</bean>

	<!--
		提供rememberMe功能
		
		登陆验证时:登陆成功后会调用loginSuccess方法,在cookie里面保留用户信息,
		格式为:username + ":" + expiryTime + ":" + Md5Hex(username + ":" + expiryTime + ":" + password + ":" + key)
		
		访问页面时:rememberMeProcessingFilter会调用autoLogin方法,在cookie中获取用户信息
	-->
	<bean id="rememberMeServices"
		class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
		<property name="userDetailsService" ref="jdbcDaoImpl" />
		<property name="authenticationDetailsSource"
			ref="authenticationDetailsSourceHelper" />
		<property name="key" value="springRocks" />
		<property name="parameter" value="rememberme" />
	</bean>

	<bean id="authenticationDetailsSourceHelper"
		class="edu.ccut.acegi.intercept.AuthenticationDetailsSourceHelper" />

	<!--
		验证rememberMe证明信息的合法性,利用两个的key来进行比较验证
	-->
	<bean id="rememberMeAuthenticationProvider"
		class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
		<property name="key" value="springRocks" />
	</bean>

	<bean id="sessionRegistry"
		class="org.acegisecurity.concurrent.SessionRegistryImpl" />

	<!--
		退出登陆并且remember-me cookie
	-->
	<bean id="logoutFilter"
		class="org.acegisecurity.ui.logout.LogoutFilter">
		<property name="filterProcessesUrl" value="/jsp/j_acegi_logout" />
		<!-- 退出后指向的 URL -->
		<constructor-arg value="/jsp/index.jsp" />
		<constructor-arg>
			<list>
				<ref bean="rememberMeServices" />
				<bean
					class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" />
				<ref bean="sessionLogoutHandler" />
			</list>
		</constructor-arg>
	</bean>
	<bean id="sessionLogoutHandler"
		class="edu.ccut.acegi.intercept.SessionLogoutHandler">
		<property name="sessionRegistry">
			<ref bean="sessionRegistry" />
		</property>
	</bean>


在我登陆一次并关闭浏览器时,cookies文件还在,当重新打开浏览器并访问登陆页面时cookies文件被删除。不知道cookies是被什么删除的。
请大家给点建议。
0 请登录后投票
   发表时间:2007-05-25  
正在学习Acegi中,看了之后对其原理有了初步的认识
0 请登录后投票
   发表时间:2007-05-25  
是得好好学习一下!!!支持,投良好
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics