`
liuguofeng
  • 浏览: 462601 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Acegi

 
阅读更多
[简介] 
Acegi Security System 是一种功能强大并易于使用的替代性方案,使您不必再为 Java 企业应用程序编写大量的安全代码。虽然它专门针对使用 Spring 框架编写的应用程序,但是任何类型的 Java 应用程序都没有理由不去使用 Acegi。

本文的主要目的是希望能够说明如何在基于Spring构架的Web应用中使用Acegi,而不是详细介绍其中的每个接口、每个类。注意,即使对已经存在的Spring应用,通过下面介绍的步骤,也可以马上享受到Acegi提供的认证和授权。 


 

Acegi Security System 使用安全过滤器来提供企业应用程序的身份验证和授权服务。该框架提供了不同类型的过滤器,可以根据应用程序的需求进行配置。您将在本文后面了解到 安全过滤器的不同类型 ;现在,只需注意可以为如下任务配置 Acegi 安全过滤器:

在访问一个安全资源之前提示用户登录。


通过检查安全标记(如密码),对用户进行身份验证。


检查经过身份验证的用户是否具有访问某个安全资源的特权。


将成功进行身份验证和授权的用户重定向到所请求的安全资源。


对不具备访问安全资源特权的用户显示 Access Denied 页面。


在服务器上记录成功进行身份验证的用户,并在用户的客户机上设置安全 cookie。使用该 cookie 执行下一次身份验证,而无需要求用户登录。


将身份验证信息存储在服务器端的会话对象中,从而安全地进行对资源的后续请求。


在服务器端对象中构建并保存安全信息的缓存,从而优化性能。


当用户退出时,删除为用户安全会话而保存的服务器端对象。


与大量后端数据存储服务(如目录服务或关系数据库)进行通信,这些服务用于存储用户的安全信息和 ECM 的访问控制策略。 
正如这个列表显示的那样,Acegi 的安全过滤器允许您执行保护企业应用程序所需的几乎任何事情。

 

 

[基础工作] 
在你的Web应用的lib中添加Acegi下载包中的acegi-security.jar 

 

[web.xml] 

在web.xml配置

Xml代码  
<filter>  
        <filter-name>Acegi Filter Chain Proxy</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>  

<filter>
		<filter-name>Acegi Filter Chain Proxy</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> 

<filter-mapping>限定了FilterToBeanProxy 的URL匹配模式 ,

Xml代码  
<filter-mapping>  
        <filter-name>Acegi Filter Chain Proxy</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  

<filter-mapping>
		<filter-name>Acegi Filter Chain Proxy</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping> 

<listener>的HttpSessionEventPublisher 用于发布HttpSessionApplicationEvents 和HttpSessionDestroyedEvent 事件给spring的applicationcontext 。

 

Xml代码  
<listener>  
        <listener-class>  
            org.acegisecurity.ui.session.HttpSessionEventPublisher   
        </listener-class>  
    </listener>  

<listener>
		<listener-class>
			org.acegisecurity.ui.session.HttpSessionEventPublisher
		</listener-class>
	</listener> 

[applicationContext-acegi-security.xml] 

 

 applicationContext-acegi-security.xml文件配置

 

FilterChainProxy 会按顺序来调用这些filter,使这些filter能享用Spring ioc的功能 , CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON定义了url比较前先转为小写, PATTERN_TYPE_APACHE_ANT定义了使用Apache ant的匹配模式 

Xml代码  
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">  
     <property name="filterInvocationDefinitionSource">  
        <value>  
        CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON   
        PATTERN_TYPE_APACHE_ANT   
           /**=httpSessionContextIntegrationFilter, logoutFilter, authenticationProcessingFilter,   
              basicProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,   
            switchUserProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor   
        </value>  
     </property>  
   </bean>  

	<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
      <property name="filterInvocationDefinitionSource">
         <value>
		    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
		    PATTERN_TYPE_APACHE_ANT
            /**=httpSessionContextIntegrationFilter, logoutFilter, authenticationProcessingFilter,
               basicProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,
             switchUserProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
         </value>
      </property>
    </bean> 

定义数据源为调用tomcat容器数据源 登入验证时需要获取数据源连接数据库

Xml代码  
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">  
    <property name="jndiName"><value>java:/comp/env/jdbc/test</value></property>  
</bean>  

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName"><value>java:/comp/env/jdbc/test</value></property>
    </bean> 

认证管理 ,从数据库中读取用户信息验证身份

Xml代码  
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">  
   <property name="providers">  
      <list>  
         <ref local="daoAuthenticationProvider"/>  
      </list>  
   </property>  
</bean>  

   <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
      <property name="providers">
         <list>
            <ref local="daoAuthenticationProvider"/>
         </list>
      </property>
   </bean> 

 

 

 

daoAuthenticationProvider 
  进行简单的基于数据库的身份验证。DaoAuthenticationProvider 获取数据库中的账号密码并进行匹配,若成功则在通过用户身份的同时返回一个包含授权信息的Authentication对象 ,否则身份验证失败,抛出一个AuthenticatiionException 。 

Xml代码  
 <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">  
      <property name="userDetailsService"><ref local="jdbcDaoImpl"/></property>  
      <property name="passwordEncoder"><ref local="passwordEncoder"/></property>  
      <property name="userCache"><ref local="userCache"/></property>  
 </bean>  

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

jdbcDaoImpl 

用于在数据中获取用户信息

Xml代码  
<bean id="jdbcDaoImpl" class="com.milesup.acegi.userdetails.jdbc.JdbcDaoImpl">  
      <property name="dataSource"><ref bean="dataSource"/></property>  
      <property name="rolePrefix"><value>ROLE_</value></property>  
   </bean>  

<bean id="jdbcDaoImpl" class="com.milesup.acegi.userdetails.jdbc.JdbcDaoImpl">
      <property name="dataSource"><ref bean="dataSource"/></property>
      <property name="rolePrefix"><value>ROLE_</value></property>
   </bean> 

passwordEncoder 

  使用加密器对用户输入的明文进行加密。Acegi提供了三种加密器:


Xml代码  
1 :   PlaintextPasswordEncoder—默认,不加密,返回明文.   
2 :   ShaPasswordEncoder—哈希算法(SHA)加密   
3 :   Md5PasswordEncoder—消息摘要(MD5)加密  

1 :   PlaintextPasswordEncoder—默认,不加密,返回明文.
2 :   ShaPasswordEncoder—哈希算法(SHA)加密
3 :   Md5PasswordEncoder—消息摘要(MD5)加密  
使用加密器对用户输入的明文进行加密 为MD5加密方式

Xml代码  
<bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/>  

<bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/>  

缓存用户和资源相对应的权限信息。每当请求一个受保护资源时,daoAuthenticationProvider 就会被调用以获取用户授权信息 。如果每次都从数据库获取的话,那代价很高,对于不常改变的用户和资源信息来说,最好是把相关授权信息缓存起来。
userCache提供了两种实现: NullUserCache 和EhCacheBasedUserCache , NullUserCache 实际上就是不进行任何缓存,EhCacheBasedUserCache 是使用Ehcache来实现缓功能。

Xml代码  
<!-- 缓存管理 -->  
   <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>  
    <!-- 缓存用户和资源相对应的权限信息 -->  
   <bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">  
      <property name="cacheManager">  
         <ref local="cacheManager"/>  
      </property>  
      <property name="cacheName">  
         <value>userCache</value>  
      </property>  
   </bean>  
      
   <bean id="userCache" class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">  
      <property name="cache"><ref local="userCacheBackend"/></property>  
   </bean>  

<!-- 缓存管理 -->
   <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
    <!-- 缓存用户和资源相对应的权限信息 -->
   <bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
      <property name="cacheManager">
         <ref local="cacheManager"/>
      </property>
      <property name="cacheName">
         <value>userCache</value>
      </property>
   </bean>
   
   <bean id="userCache" class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
      <property name="cache"><ref local="userCacheBackend"/></property>
   </bean> 

该过滤器用来处理在系统认证授权过程中抛出的异常

Xml代码  
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">  
     <property name="authenticationEntryPoint"><ref local="authenticationProcessingFilterEntryPoint"/></property>  
  </bean>  

 <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
      <property name="authenticationEntryPoint"><ref local="authenticationProcessingFilterEntryPoint"/></property>
   </bean> 

 

一个没有进行身份验证的用户试图访问受保护的资源验证是否授权  Exception Translation Filter(ETF)

Xml代码  
<bean id="authenticationProcessingFilterEntryPoint" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">  
      <property name="loginFormUrl"><value>/login.jsp</value></property>  
      <property name="forceHttps"><value>false</value></property>  
   </bean>  

<bean id="authenticationProcessingFilterEntryPoint" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
      <property name="loginFormUrl"><value>/login.jsp</value></property>
      <property name="forceHttps"><value>false</value></property>
   </bean> 

登入验证

成功进入main.jsp页面  ,失败跳转到/login.jsp?login_error=1  ,登入url为 /j_acegi_security_check, Authentication Processing Filter(APF)

        authenticationFailureUrl 定义登陆失败时转向的页面
         defaultTargetUrl 定义登陆成功时转向的页面
         filterProcessesUrl 定义登陆请求的页面
         rememberMeServices 用于在验证成功后添加cookie信息

Xml代码  
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">  
      <property name="authenticationManager"><ref bean="authenticationManager"/></property>  
      <property name="authenticationFailureUrl"><value>/login.jsp?login_error=1</value></property>  
      <property name="defaultTargetUrl"><value>/main.jsp</value></property>  
      <property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property>  
     <property name="rememberMeServices"><ref local="rememberMeServices"/></property>  
 </bean>  

<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
      <property name="authenticationManager"><ref bean="authenticationManager"/></property>
      <property name="authenticationFailureUrl"><value>/login.jsp?login_error=1</value></property>
      <property name="defaultTargetUrl"><value>/main.jsp</value></property>
      <property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property>
     <property name="rememberMeServices"><ref local="rememberMeServices"/></property>
 </bean> 

 

Xml代码  
用于处理HTTP头的认证信息,如从<SPAN style="COLOR: #0000ff"><STRONG>Spring远程协议</STRONG>  
</SPAN>  
(如Hessian和Burlap)或<SPAN style="COLOR: #0000ff"><STRONG>普通的浏览器如IE,Navigator的HTTP头</STRONG>  
</SPAN>  
中获取用户   
信息,将他们转交给通过<SPAN style="TEXT-DECORATION: underline">authenticationManager</SPAN>  
属性装配的认证管理器。如果认证成功,会<SPAN style="TEXT-DECORATION: underline">将一个Authentication对象放到会话中</SPAN>  
  
,否则,如果认证失败,会将控制<SPAN style="TEXT-DECORATION: underline">转交给认证入口点</SPAN>  
(通过authenticationEntryPoint属性装配)   
<!-- 用于处理HTTP头的认证信息 -->  
   <bean id="basicProcessingFilter" class="org.acegisecurity.ui.basicauth.BasicProcessingFilter">  
      <property name="authenticationManager"><ref local="authenticationManager"/></property>  
      <property name="authenticationEntryPoint"><ref local="basicProcessingFilterEntryPoint"/></property>  
   </bean>  
      
   <!-- 通过向浏览器发送一个HTTP401(未授权)消息,提示用户登录 -->  
   <bean id="basicProcessingFilterEntryPoint" class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">  
      <property name="realmName"><value>Milesup Realm</value></property>  
   </bean>  

用于处理HTTP头的认证信息,如从Spring远程协议

(如Hessian和Burlap)或普通的浏览器如IE,Navigator的HTTP头

中获取用户
信息,将他们转交给通过authenticationManager
属性装配的认证管理器。如果认证成功,会将一个Authentication对象放到会话中

,否则,如果认证失败,会将控制转交给认证入口点
(通过authenticationEntryPoint属性装配)
<!-- 用于处理HTTP头的认证信息 -->
   <bean id="basicProcessingFilter" class="org.acegisecurity.ui.basicauth.BasicProcessingFilter">
      <property name="authenticationManager"><ref local="authenticationManager"/></property>
      <property name="authenticationEntryPoint"><ref local="basicProcessingFilterEntryPoint"/></property>
   </bean>
   
   <!-- 通过向浏览器发送一个HTTP401(未授权)消息,提示用户登录 -->
   <bean id="basicProcessingFilterEntryPoint" class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
      <property name="realmName"><value>Milesup Realm</value></property>
   </bean>  
注销 退出验证 跳转到/login.jsp

Xml代码  
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">  
      <constructor-arg value="/login.jsp"/><constructor-arg>  
         <list>  
              <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>  
         </list>  
      </constructor-arg>  
   </bean>  

<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
      <constructor-arg value="/login.jsp"/><constructor-arg>
         <list>
              <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
         </list>
      </constructor-arg>
   </bean> 

经过投票 机制来决定是否可以访问某一资源(URL 或方法 )。allowIfAllAbstainDecisions为false时如果有一个或以上的decisionVoters投票通过,则授权通过。可选的决策机制有ConsensusBased和UnanimousBased

 

roleVoter 
  必须是以rolePrefix设定的value开头的权限才能进行投票,如 ROLE_

Xml代码  
<bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter">  
      <property name="rolePrefix">  
         <value>ROLE_</value>  
      </property>  
   </bean>  
  
  <!-- 组件管理授权过程  决策管理器-->  
   <bean id="httpRequestAccessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">  
      <property name="allowIfAllAbstainDecisions"><value>false</value></property>  
      <property name="decisionVoters">  
         <list>  
            <ref bean="roleVoter"/>  
         </list>  
      </property>  
   </bean>  

<bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter">
      <property name="rolePrefix">
         <value>ROLE_</value>
      </property>
   </bean>

  <!-- 组件管理授权过程  决策管理器-->
   <bean id="httpRequestAccessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
      <property name="allowIfAllAbstainDecisions"><value>false</value></property>
      <property name="decisionVoters">
         <list>
            <ref bean="roleVoter"/>
         </list>
      </property>
   </bean>  
 

过滤器安全拦截器  是否认证,是否有权限访问受保护的资源

 在执行转向url前检查objectDefinitionSource 中设定的用户权限信息。首先,objectDefinitionSource 中定义了访问URL需要的属性信息(这里的属性信息仅仅是标志,告诉accessDecisionManager 要用哪些voter来投票)。然后,authenticationManager 掉用自己的provider来对用户的认证信息进行校验。最后,有投票者根据用户持有认证和访问url需要的属性,调用自己的voter来投票,决定是否允许访问。

Xml代码  
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">  
      <property name="authenticationManager"><ref bean="authenticationManager"/></property>  
      <property name="accessDecisionManager"><ref local="httpRequestAccessDecisionManager"/></property>  
      <property name="objectDefinitionSource">  
         <value>  
            PATTERN_TYPE_APACHE_ANT   
            /user.jsp=ROLE_ADMIN  
            /admin=ROLE_ADMIN  
         </value>  
      </property>  
   </bean>  

<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
      <property name="authenticationManager"><ref bean="authenticationManager"/></property>
      <property name="accessDecisionManager"><ref local="httpRequestAccessDecisionManager"/></property>
      <property name="objectDefinitionSource">
         <value>
			PATTERN_TYPE_APACHE_ANT
			/user.jsp=ROLE_ADMIN
			/admin=ROLE_ADMIN
         </value>
      </property>
   </bean>  
 

[login.jsp] 

 

Html代码  
<form action="/j_acegi_security_check" method="post" >  
    <table>  
                  <tr>  
                    <td width="140" height="22" align="right">用户名</td>  
                    <td width="47%" align="left"><input value="${lastUserName}" name="j_username" type="text" class="inputstyle" id="j_username"></td>  
                    <td align="left" nowrap><div class="loginmeon"> </div></td>  
                  </tr>  
                  <tr>  
                    <td width="140" height="22" align="right">密 码</td>  
                    <td width="47%" align="left"><input name="j_password" type="password" class="inputstyle" id="j_password" size="21"></td>  
                  </tr>  
 <tr>  
                    <td height="60" colspan="3" align="center" valign="middle">  
                 <input type="submit" name="imageField2" value="登入"></td>  
                  </tr>  
                </table>  
                </td>  
              </tr>  
           </table>  
         </td>  
      </tr>  
    </table>  
 </form>     

<form action="/j_acegi_security_check" method="post" >
    <table>
                  <tr>
                    <td width="140" height="22" align="right">用户名</td>
                    <td width="47%" align="left"><input value="${lastUserName}" name="j_username" type="text" class="inputstyle" id="j_username"></td>
                    <td align="left" nowrap><div class="loginmeon"> </div></td>
                  </tr>
                  <tr>
                    <td width="140" height="22" align="right">密 码</td>
                    <td width="47%" align="left"><input name="j_password" type="password" class="inputstyle" id="j_password" size="21"></td>
                  </tr>
 <tr>
                    <td height="60" colspan="3" align="center" valign="middle">
                 <input type="submit" name="imageField2" value="登入"></td>
                  </tr>
                </table>
                </td>
              </tr>
           </table>
         </td>
      </tr>
    </table>
 </form>     
[JdbcDaoImpl.java] 

 

Java代码  
public class JdbcDaoImpl extends org.acegisecurity.userdetails.jdbc.JdbcDaoImpl {   
  
    private String anonymousRoleName = "ROLE_ANONYMOUS";   
  
    private Log logger = LogFactory.getLog(JdbcDaoImpl.class);   
  
    private PreparedStatement userPstmt;   
  
    private PreparedStatement rolePstmt;   
  
    public UserDetails loadUserByUsername(String userName)   
            throws UsernameNotFoundException, DataAccessException {   
        UserDetails user = findUserByName(userName);   
  
        if (user == null) {   
            throw new UsernameNotFoundException("User not found");   
        }   
  
        return user;   
    }   
  
    private UserDetails findUserByName(String userName) {   
        Connection connection = null;   
        ResultSet rsUser = null;   
        ResultSet rsRole = null;   
        UserDetails user = null;   
        String logonName = null;   
        String password = null;   
        String roleName = null;   
        int status = -1;   
        boolean enabled = false;   
        Vector roles = null;   
        GrantedAuthority[] rolesArray = null;   
  
        try {   
            connection = getDataSource().getConnection();   
            userPstmt = connection   
                    .prepareStatement("select * from users where user_NAME=?");   
            userPstmt.setString(1, userName);   
            rsUser = userPstmt.executeQuery();   
            if (rsUser.next()) {   
                logonName = rsUser.getString("USER_NAME");   
                password = rsUser.getString("PASSWORD");   
                status = rsUser.getInt("STATUS");   
                if (status == 1)   
                    enabled = true;   
            } else {   
                return null;   
            }   
            rolePstmt = connection   
                    .prepareStatement("SELECT ROLE.NAME Role FROM ROLE,  users_ROLES,  users WHERE ROLE.ID= user_ROLES.FK_ROLES  and users.user_NAME=?");   
            rolePstmt.setString(1, userName);   
            rsRole = rolePstmt.executeQuery();   
            roles = new Vector();   
            while (rsRole.next()) {   
                roleName = getRolePrefix() + rsRole.getString("Role");   
                roles.add(new GrantedAuthorityImpl(roleName));   
            }   
            rolesArray = new GrantedAuthority[roles.size() + 1];   
            int index = 0;   
            for (index = 0; index < roles.size(); index++)   
                rolesArray[index] = (GrantedAuthority) roles.get(index);   
            rolesArray[index] = new GrantedAuthorityImpl(anonymousRoleName);   
            user = new User(logonName, password, enabled, true, true, true,   
                    rolesArray);   
        } catch (SQLException e) {   
            logger.fatal("", e);   
        } finally {   
            try {   
                rsRole.close();   
                rsUser.close();   
                userPstmt.close();   
                rolePstmt.close();   
                connection.close();   
            } catch (SQLException sqlx) {   
                logger.fatal("", sqlx);   
            } catch (NullPointerException x) {   
                logger.fatal("", x);   
            }   
        }   
        return user;   
    }   
  
}  

public class JdbcDaoImpl extends org.acegisecurity.userdetails.jdbc.JdbcDaoImpl {

	private String anonymousRoleName = "ROLE_ANONYMOUS";

	private Log logger = LogFactory.getLog(JdbcDaoImpl.class);

	private PreparedStatement userPstmt;

	private PreparedStatement rolePstmt;

	public UserDetails loadUserByUsername(String userName)
			throws UsernameNotFoundException, DataAccessException {
		UserDetails user = findUserByName(userName);

		if (user == null) {
			throw new UsernameNotFoundException("User not found");
		}

		return user;
	}

	private UserDetails findUserByName(String userName) {
		Connection connection = null;
		ResultSet rsUser = null;
		ResultSet rsRole = null;
		UserDetails user = null;
		String logonName = null;
		String password = null;
		String roleName = null;
		int status = -1;
		boolean enabled = false;
		Vector roles = null;
		GrantedAuthority[] rolesArray = null;

		try {
			connection = getDataSource().getConnection();
			userPstmt = connection
					.prepareStatement("select * from users where user_NAME=?");
			userPstmt.setString(1, userName);
			rsUser = userPstmt.executeQuery();
			if (rsUser.next()) {
				logonName = rsUser.getString("USER_NAME");
				password = rsUser.getString("PASSWORD");
				status = rsUser.getInt("STATUS");
				if (status == 1)
					enabled = true;
			} else {
				return null;
			}
			rolePstmt = connection
					.prepareStatement("SELECT ROLE.NAME Role FROM ROLE,  users_ROLES,  users WHERE ROLE.ID= user_ROLES.FK_ROLES  and users.user_NAME=?");
			rolePstmt.setString(1, userName);
			rsRole = rolePstmt.executeQuery();
			roles = new Vector();
			while (rsRole.next()) {
				roleName = getRolePrefix() + rsRole.getString("Role");
				roles.add(new GrantedAuthorityImpl(roleName));
			}
			rolesArray = new GrantedAuthority[roles.size() + 1];
			int index = 0;
			for (index = 0; index < roles.size(); index++)
				rolesArray[index] = (GrantedAuthority) roles.get(index);
			rolesArray[index] = new GrantedAuthorityImpl(anonymousRoleName);
			user = new User(logonName, password, enabled, true, true, true,
					rolesArray);
		} catch (SQLException e) {
			logger.fatal("", e);
		} finally {
			try {
				rsRole.close();
				rsUser.close();
				userPstmt.close();
				rolePstmt.close();
				connection.close();
			} catch (SQLException sqlx) {
				logger.fatal("", sqlx);
			} catch (NullPointerException x) {
				logger.fatal("", x);
			}
		}
		return user;
	}

}  

 

分享到:
评论

相关推荐

    C2000系列DSP芯片串口读写方案与FlashPro2000编程器应用详解

    内容概要:本文详细介绍了基于TMS320F系列芯片的C2000串口读写方案及其编程器——FlashPro2000的功能特点和支持的接口模式。文中不仅涵盖了硬件连接的具体步骤,还提供了代码实例来展示Flash擦除操作,并对比了JTAG和SCI-BOOT两种模式的优缺点。此外,针对不同型号的C2000系列芯片,给出了详细的适配指导以及避免烧录过程中可能出现的问题的方法。 适合人群:从事DSP开发的技术人员,尤其是对TI公司C2000系列芯片有一定了解并希望深入了解其编程和烧录细节的人群。 使用场景及目标:适用于实验室环境下的程序调试阶段,以及生产线上的批量烧录任务。主要目的是帮助开发者选择合适的编程工具和技术手段,提高工作效率,减少因误操作导致设备损坏的风险。 其他说明:文中提供的代码片段和命令行指令可以直接用于实际项目中,同时附带了一些实用技巧,如防止芯片变砖的小贴士和自动化重试脚本,有助于解决常见的烧录难题。

    汉字字库存储芯片扩展实验通常是为了学习和理解如何在嵌入式系统或计算机硬件中增加或管理存储资源,特别是针对需要处理中文字符的应用 这类实验对于想要深入了解计算机体系结构、嵌入式开发以及汉字编码的学生和工

    汉字字库存储芯片扩展实验 # 汉字字库存储芯片扩展实验 ## 实验目的 1. 了解汉字字库的存储原理和结构 2. 掌握存储芯片扩展技术 3. 学习如何通过硬件扩展实现大容量汉字字库存储 ## 实验原理 ### 汉字字库存储基础 - 汉字通常采用点阵方式存储(如16×16、24×24、32×32点阵) - 每个汉字需要占用32字节(16×16)到128字节(32×32)不等的存储空间 - 国标GB2312-80包含6763个汉字,需要较大存储容量 ### 存储芯片扩展方法 1. **位扩展**:增加数据总线宽度 2. **字扩展**:增加存储单元数量 3. **混合扩展**:同时进行位扩展和字扩展 ## 实验设备 - 单片机开发板(如STC89C52) - 存储芯片(如27C256、29C040等) - 逻辑门电路芯片(如74HC138、74HC373等) - 示波器、万用表等测试设备 - 连接线若干 ## 实验步骤 ### 1. 单芯片汉字存储实验 1. 连接27C256 EPROM芯片到单片机系统 2. 将16×16点阵汉字字库写入芯片 3. 编写程序读取并显示汉字 ### 2. 存储芯片字扩展实验 1. 使用地址译码器(如74HC138)扩展多片27C256 2. 将完整GB2312字库分布到各芯片中 3. 编写程序实现跨芯片汉字读取 ### 3. 存储芯片位扩展实验 1. 连接两片27C256实现16位数据总线扩展 2. 优化字库存储结构,提高读取速度 3. 测试并比较扩展前后的性能差异 ## 实验代码示例(单片机部分) ```c #include <reg52.h> #include <intrins.h> // 定义存储芯片控制引脚 sbit CE = P2^7; // 片选 sbit OE = P2^6; // 输出使能 sbit

    测控装备干扰源快速侦测系统设计研究.pdf

    测控装备干扰源快速侦测系统设计研究.pdf

    嵌入式八股文面试题库资料知识宝典-【开发】嵌入式开源项目&库&资料.zip

    嵌入式八股文面试题库资料知识宝典-【开发】嵌入式开源项目&库&资料.zip

    嵌入式八股文面试题库资料知识宝典-百度2022年嵌入式面试题.zip

    嵌入式八股文面试题库资料知识宝典-百度2022年嵌入式面试题.zip

    少儿编程scratch项目源代码文件案例素材-空间站.zip

    少儿编程scratch项目源代码文件案例素材-空间站.zip

    基于关联规则的商业银行个性化产品推荐.pdf

    基于关联规则的商业银行个性化产品推荐.pdf

    嵌入式八股文面试题库资料知识宝典-Linux基础使用.zip

    嵌入式八股文面试题库资料知识宝典-Linux基础使用.zip

    MATLAB仿真轴棱锥生成贝塞尔高斯光束及环形光束光强图像分析

    内容概要:本文详细介绍了利用MATLAB进行轴棱锥生成贝塞尔高斯光束及环形光束光强图像的仿真研究。首先阐述了实验的背景与目标,强调了MATLAB在光学和计算科学领域的广泛应用。接着,具体描述了实验的方法与步骤,包括材料准备、仿真过程中的参数设定和光束生成代码编写。最后,对实验结果进行了深入分析,展示了贝塞尔高斯光束和环形光束的光强分布特点,验证了其光学性能的预期表现。文章还对未来的研究方向和技术改进提出了展望。 适合人群:从事光学、物理学及相关领域研究的专业人士,特别是对光束生成和光学性能分析感兴趣的科研工作者。 使用场景及目标:适用于需要进行光束生成和性能分析的实验室环境,旨在帮助研究人员更好地理解和优化光束特性和传播行为。 其他说明:本文不仅提供了详细的实验方法和步骤,还附有丰富的实验结果和数据分析,为后续研究提供了宝贵的参考资料。

    三电平NPC型APF模型预测控制中滞环控制模块的应用与开关频率优化研究

    内容概要:本文探讨了三电平NPC型有源电力滤波器(APF)的模型预测控制(MPC)中存在的开关频率过高问题及其解决方案。传统MPC方法会导致极高的开关频率,增加了系统的能耗和热量。通过引入滞环控制模块,可以在不大幅牺牲性能的情况下有效降低开关频率。具体来说,滞环控制通过在价值函数计算后增加一个判断条件,对状态切换进行惩罚,从而减少不必要的开关动作。实验结果显示,开关频率从4392Hz降至3242Hz,降幅达26.2%,虽然电流总谐波畸变率(THD)略有上升,但仍符合国家标准。此外,文中还提出了动态调整滞环宽度的方法,以进一步优化不同负载条件下的表现。 适合人群:从事电力电子、电力系统控制领域的研究人员和技术人员,特别是关注APF和MPC技术的人群。 使用场景及目标:适用于需要优化APF系统开关频率的研究和工程项目,旨在提高系统效率并降低成本。目标是在不影响系统性能的前提下,显著降低开关频率,减少能量损失和热管理难度。 其他说明:文章不仅提供了理论分析,还包括具体的实现代码片段,有助于读者理解和实践。同时,强调了在实际应用中需要注意的问题,如中点电位漂移等。

    计算流体力学中三维POD DMD程序的原网格处理方法及应用

    内容概要:本文介绍了三维POD DMD程序在处理原网格数据方面的独特优势和技术细节。首先阐述了该程序能读取结构化和非结构化网格数据及其拓扑关系,在生成模态数据过程中保持原始网格形态而不需要进行网格插值操作。接着展示了简化版本的Python代码片段,揭示了读取网格数据和生成模态数据的核心逻辑。最后提到提供的辅助学习资料如代码、视频教程、Word教程和实例数据,帮助用户深入理解并掌握该程序的应用。 适合人群:从事计算流体力学领域的研究人员和技术爱好者,尤其是那些希望提高数据处理效率的人群。 使用场景及目标:适用于需要处理复杂网格数据的研究项目,旨在简化数据处理流程,提升工作效率,同时保持数据的原始特性。 其他说明:文中不仅提供了理论性的讲解,还有具体的代码示例和丰富的学习资源,使读者可以边学边练,快速上手。

    融合双向路由注意力的多尺度X光违禁品检测.pdf

    融合双向路由注意力的多尺度X光违禁品检测.pdf

    嵌入式八股文面试题库资料知识宝典-Linux_Shell基础使用.zip

    嵌入式八股文面试题库资料知识宝典-Linux_Shell基础使用.zip

    嵌入式八股文面试题库资料知识宝典-联发科2021武汉嵌入式软件开发.zip

    嵌入式八股文面试题库资料知识宝典-联发科2021武汉嵌入式软件开发.zip

    基于有限体积法Godunov格式的管道泄漏检测模型研究.pdf

    基于有限体积法Godunov格式的管道泄漏检测模型研究.pdf

    嵌入式八股文面试题库资料知识宝典-ARM常见面试题目.zip

    嵌入式八股文面试题库资料知识宝典-ARM常见面试题目.zip

    基于LWR问题的无证书全同态加密方案.pdf

    基于LWR问题的无证书全同态加密方案.pdf

    嵌入式八股文面试题库资料知识宝典-符坤面试经验.zip

    嵌入式八股文面试题库资料知识宝典-符坤面试经验.zip

    三电平逆变器带不平衡负载的DSC与双闭环PI控制策略仿真研究

    内容概要:本文详细探讨了三电平逆变器在带不平衡负载条件下的仿真研究。主要内容包括仿真环境的搭建、不同拓扑结构的选择(如T型、I型NPC和ANPC)、延时相消法(DSC)和双二阶广义积分器(DSOGI)的正负序分离控制策略、SVPWM或SPWM调制技术的应用、双闭环PI控制以及直流均压控制。文中通过具体的参数设置(交流电压220V,直流侧电压750V)进行了详细的仿真实验,并展示了各个控制策略的效果。最终,通过仿真实验验证了所提出方法的有效性,确保了交流侧三相电压波形的对称性和电流波形的自适应调节。 适合人群:从事电力电子、电机驱动、新能源发电等领域研究的技术人员和研究人员。 使用场景及目标:适用于需要理解和掌握三电平逆变器在复杂负载条件下控制策略的研究人员和技术人员。目标是提高对三电平逆变器及其控制策略的理解,优化实际应用中的性能。 其他说明:本文不仅提供了理论分析,还包含了具体的仿真步骤和代码实现,有助于读者更好地理解和应用相关技术。

    汽车工程中4WID-4WIS 14自由度整车动力学模型的Matlab/Simulink建模及应用

    内容概要:本文介绍了如何使用Matlab/Simulink软件构建一个14自由度的四轮驱动-四轮转向(4WID-4WIS)整车动力学模型。该模型涵盖了整车纵向、横向、横摆、车身俯仰、侧倾、垂向跳动及四轮旋转和垂向自由度等多个方面,旨在全面反映车辆在不同工况下的动态行为。文中详细描述了各子系统的建模方法,包括转向系统、整车系统、悬架系统、魔术轮胎pac2002、车轮系统和PI驾驶员模块。同时,提供了Simulink源码文件、建模说明文档及相关参考资料,便于用户理解和应用。 适用人群:主要面向汽车工程师、研究人员以及对汽车动力学和Simulink建模感兴趣的学习者。 使用场景及目标:①帮助用户深入了解车辆在各种工况下的动态行为;②为车辆控制策略的制定提供理论支持和技术手段;③作为学习和研究整车动力学建模的有效工具。 其他说明:该模型采用模块化建模方法,提高了模型的清晰度和可维护性,同时也提升了建模效率。

Global site tag (gtag.js) - Google Analytics