java随记

坚持就是胜利!

 

acegi之Active Directory验证

客户要求提供Active Directory登录验证.原因是他们公司是在美国的上市公司,要求上市公司的软件必须提供统一登录认证.他们想到的解决方案就是Active Directory.呵呵.而我们开发的系统使用的是acegi登录验证.嗯,这个,首先想到的就是ldap,没的想,网上搜吧,资料还不算少.那就配吧,配好了需要测试吧,那就找服务器咧.这公司的域服务器不让用,那就openldap吧.下好了又一通查资料,openldap总得配是吧.总算给配好了,不容易呀.就拿到客户环境去试吧,嘿嘿,客户说了不可能给我们管理员帐号密码,只有用户登录帐号跟密码,傻了.acegi的ldap验证就要这个啊.
回来继续搞咧,咱也没办法不是?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

 <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,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
   </value>
  </property>
 </bean>

 <bean id="authenticationManager"
  class="org.acegisecurity.providers.ProviderManager">
  <property name="providers">
   <list>
     <!-- 自己写一个认证提供者类 我加的-->
       <ref local="activeDirectoryProvider" />
    <ref local="daoAuthenticationProvider" />
    <ref local="anonymousAuthenticationProvider" />
    <ref local="rememberMeAuthenticationProvider" />
   </list>
  </property>
 
 </bean>
 
 <!-- 认证提供者类的配置 我加的-->
 <bean id="activeDirectoryProvider"
  class="net.omw.utility.AcegiTestProvider">
  <property name="url" value="ldap://172.108.4.2"> </property>
  <property name="port" value="389"> </property>
<!--domain取值域服务器的配置-->
  <property name="domain" value="SUNTECH"> </property>
  <!--    <property name="sessionController" ref="concurrentSessionController"></property> -->
 </bean>


 <bean id="jdbcDaoImpl"
  class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
  <property name="dataSource">
   <ref bean="coreDataSource" />
  </property>
  <property name="usersByUsernameQuery">
   <value>
    select C_OPER_ID,C_PASSWORD,1 from Operator where
    C_OPER_ID = ? and C_STATUS='Y'
   </value>
  </property>
  <property name="authoritiesByUsernameQuery">
   <value>
    select C_OPER_ID,C_PASSWORD,1 from Operator where
    C_OPER_ID = ? and C_STATUS='Y'
   </value>
  </property>
 </bean>

 <bean id="passwordEncoder"
  class="org.acegisecurity.providers.encoding.Md5PasswordEncoder">
  <property name="encodeHashAsBase64" value="false"></property>
 </bean>

 <bean id="daoAuthenticationProvider"
  class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
  <property name="userDetailsService">
   <ref local="jdbcDaoImpl" />
  </property>
  <!-- <property name="userCache">
   <ref local="userCache" />
  </property>-->
  <property name="passwordEncoder">
   <ref local="passwordEncoder" />
  </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>

 <bean id="loggerListener"
  class="org.acegisecurity.event.authentication.LoggerListener" />

 <bean id="anonymousProcessingFilter"
  class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
  <property name="key">
   <value>foobar</value>
  </property>
  <property name="userAttribute">
   <value>anonymousUser,ROLE_ANONYMOUS</value>
  </property>
 </bean>

 <bean id="anonymousAuthenticationProvider"
  class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
  <property name="key">
   <value>foobar</value>
  </property>
 </bean>

 <bean id="httpSessionContextIntegrationFilter"
  class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
 </bean>

 <bean id="rememberMeProcessingFilter"
  class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
  <property name="authenticationManager">
   <ref local="authenticationManager" />
  </property>
  <property name="rememberMeServices">
   <ref local="rememberMeServices" />
  </property>
 </bean>

 <bean id="rememberMeServices"
  class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
  <property name="userDetailsService">
   <ref local="jdbcDaoImpl" />
  </property>
  <property name="key">
   <value>springRocks</value>
  </property>
 </bean>

 <bean id="rememberMeAuthenticationProvider"
  class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
  <property name="key">
   <value>springRocks</value>
  </property>
 </bean>

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

 <bean id="securityContextHolderAwareRequestFilter"
  class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter" />

 <bean id="exceptionTranslationFilter"
  class="org.acegisecurity.ui.ExceptionTranslationFilter">
  <property name="authenticationEntryPoint">
   <ref local="authenticationProcessingFilterEntryPoint" />
  </property>
  <property name="accessDeniedHandler">
   <bean
    class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
    <property name="errorPage"
     value="/common/AccessDenied.jsp" />
   </bean>
  </property>
 </bean>

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

 <bean id="authenticationProcessingFilterEntryPoint"
  class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
  <property name="loginFormUrl">
   <value>/login/loginPage.jsp</value>
  </property>
  <property name="forceHttps">
   <value>false</value>
  </property>
  <property name="serverSideRedirect" value="false"></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" />

 <bean id="filterInvocationInterceptor"
  class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
  <property name="validateConfigAttributes" value="true" />
  <property name="authenticationManager">
   <ref bean="authenticationManager" />
  </property>
  <property name="accessDecisionManager">
   <ref local="httpRequestAccessDecisionManager" />
  </property>
  <property name="objectDefinitionSource"
   ref="rdbmsFilterInvocationDefinitionSource" />

 </bean>

 <bean id="rdbmsFilterInvocationDefinitionSource"
  class="net.omw.utility.acegi.interceptor.RdbmsFilterInvocationDefinitionSource">
  <property name="dataSource">
   <ref bean="coreDataSource" />
  </property>
  <property name="webresdbCache" ref="webresCacheBackend" />
 </bean>

 <bean id="webresCacheBackend"
  class="org.springframework.cache.ehcache.EhCacheFactoryBean">
  <property name="cacheManager">
   <ref local="cacheManager" />
  </property>
  <property name="cacheName">
   <value>webresdbCache</value>
  </property>
 </bean>

 <!-- 
  <bean id="switchUserProcessingFilter" class="org.acegisecurity.ui.switchuser.SwitchUserProcessingFilter">
  <property name="userDetailsService" ref="jdbcDaoImpl" />
  <property name="switchUserUrl"><value>/j_acegi_switch_user</value></property>
  <property name="exitUserUrl"><value>/j_acegi_exit_user</value></property>
  <property name="targetUrl"><value>/secure/index.htm</value></property>
  </bean>   
 -->

 <bean id="authenticationLoggerListener"
  class="org.acegisecurity.event.authentication.LoggerListener" />

 <bean id="authorizationLoggerListener"
  class="org.acegisecurity.event.authorization.LoggerListener" />
</beans>

AcegiTestProvider类从AbstractUserDetailsAuthenticationProvider继承,有两个方法必须实现
additionalAuthenticationChecks()和retrieveUser()方法.retrieveUser返回UserDetails,UserDetails的实现可以包装更多的信息.但在本例中几乎没什么太大的作用,仅仅是为了返回而重新定义了一个类
真正的验证逻辑发生在additionalAuthenticationChecks方法里抛出异常就算用户登录失败

package net.omw.utility;

import java.util.Properties;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;

import org.acegisecurity.AuthenticationException;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UsernameNotFoundException;

public class AcegiTestProvider extends
  AbstractUserDetailsAuthenticationProvider {
   private String url;
   private String port;
   private String domain;
 
 /*
  * 验证逻辑
  * @see org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider#additionalAuthenticationChecks(org.acegisecurity.userdetails.UserDetails, org.acegisecurity.providers.UsernamePasswordAuthenticationToken)
  *
  */
 @Override
 protected void additionalAuthenticationChecks(UserDetails arg0,
   UsernamePasswordAuthenticationToken arg1)
   throws AuthenticationException {
  // TODO Auto-generated method stub

  String URL = url+":"+port;

        String username=domain+"\\"+arg0.getUsername();
  String password = arg0.getPassword();


  Properties env = new Properties();  
  env.put(Context.INITIAL_CONTEXT_FACTORY,
  "com.sun.jndi.ldap.LdapCtxFactory");
  env.put(Context.PROVIDER_URL,"ldap://172.18.0.42:389");
  env.put(Context.SECURITY_AUTHENTICATION,"simple");
  env.put(Context.SECURITY_PRINCIPAL,
  username);
  env.put(Context.SECURITY_CREDENTIALS,password);
  env.put("com.sun.jndi.ldap.connect.pool","true");
  env.put("java.naming.referral","follow"); 
  try{
    new InitialLdapContext(env,null);
  }
  catch(NamingException e){
   // Authentication failed
   throw new UsernameNotFoundException(e.toString());
   
  }


 }

 @Override
 protected UserDetails retrieveUser(String arg0,
   UsernamePasswordAuthenticationToken arg1)
   throws AuthenticationException {
  // TODO Auto-generated method stub
  GrantedAuthority[] authorities = new GrantedAuthority[1];
  authorities[0] = new GrantedAuthorityImpl("ROLE_SUPERVISOR");
  String password = (String) arg1.getCredentials();  
        /*String username = "";
  Object obj = arg1.getPrincipal();
  if (obj instanceof UserDetails) {
   username = ((UserDetails) obj).getUsername();
  } else {
   username = obj.toString();
  }
        */
  UserDetails userDetails = new UserDetailsImpl(authorities, password,
    arg1.getName(), true, true, true, true);
  //if(true)
    //  throw new AuthenticationCredentialsNotFoundException("t");
  
  return userDetails;
 }

 public String getUrl() {
  return url;
 }

 public void setUrl(String url) {
  this.url = url;
 }

 public String getPort() {
  return port;
 }

 public void setPort(String port) {
  this.port = port;
 }

 public String getDomain() {
  return domain;
 }

 public void setDomain(String domain) {
  this.domain = domain;
 }

 
}

package net.omw.utility;

import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.userdetails.UserDetails;

public class UserDetailsImpl implements UserDetails {
 GrantedAuthority[] authorities;

 String password;

 String username;
 boolean isAccountNonExpired;

 boolean isAccountNonLocked;

 boolean isCredentialsNonExpired;

 boolean isEnabled;

 UserDetailsImpl(GrantedAuthority[] authorities, String password,
            String username, boolean isAccountNonExpired,
            boolean isCredentialsNonExpired, boolean isEnabled,
            boolean isAccountNonLocked) {
        this.authorities = authorities;
        this.isAccountNonExpired = isAccountNonExpired;
        this.isAccountNonLocked = isAccountNonLocked;
        this.isEnabled = isEnabled;
        this.password = password;
        this.username = username;
        this.isCredentialsNonExpired = isCredentialsNonExpired;

    }

 
 @Override
 public GrantedAuthority[] getAuthorities() {
  // TODO Auto-generated method stub
  return authorities;
 }

 @Override
 public String getPassword() {
  // TODO Auto-generated method stub
  return password;
 }

 @Override
 public String getUsername() {
  // TODO Auto-generated method stub
  return username;
 }

 @Override
 public boolean isAccountNonExpired() {
  // TODO Auto-generated method stub
  return isAccountNonExpired;
 }

 @Override
 public boolean isAccountNonLocked() {
  // TODO Auto-generated method stub
  return isAccountNonLocked;
 }

 @Override
 public boolean isCredentialsNonExpired() {
  // TODO Auto-generated method stub
  return isCredentialsNonExpired;
 }

 @Override
 public boolean isEnabled() {
  // TODO Auto-generated method stub
  return isEnabled;
 }

}





 

posted on 2009-10-30 17:48 傻 瓜 阅读(1409) 评论(0)  编辑  收藏 所属分类: 杂项


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

常用链接

留言簿(5)

我参与的团队

随笔分类

随笔档案

文章分类

友情链接

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜