zoukankan      html  css  js  c++  java
  • CAS单点登录和spring securtiy集成

    说明:本文章主要建立在spring-security早已集成在系统中的前提下:

    1.需要创建一个spring-security.xml文件并关联在applicationContext.xml文件中:<import resource="spring-security.xml" />

    2.在web.xml文件中配置单点登录监听:

    <!--单点登录登录登出监听器-->

    <listener>
    <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
    </listener>

    <!-- spring securtiy 过滤器配置 -->

    <filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

    3.下面把spring-security.xml的内容贴出来:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns="http://www.springframework.org/schema/security"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p"
    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-3.1.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/p
    http://www.springframework.org/schema/context/spring-p-3.1.xsd
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util-3.1.xsd">


    <beans:description>SpringSecurity</beans:description>

    <beans:bean id="customWebInvocationPrivilegeEvaluator"
    class="org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator">
    <beans:constructor-arg ref="baseFilter" />
    </beans:bean>

    <http pattern="/index.jsp" security="none" />
    <http pattern="/**/*.css" security="none" />
    <http pattern="/**/*.ico" security="none" />
    <http pattern="/**/*.js" security="none" />
    <http pattern="/**/*.jpg" security="none" />
    <http pattern="/**/*.png" security="none" />
    <http pattern="/**/*.gif" security="none" />
    <http pattern="/**/*.pdf" security="none" />
    <http pattern="/**/*.xls" security="none" />
    <http pattern="/**/*.xml" security="none" />
    <http pattern="/**/*.html" security="none" />
    <http pattern="/bsp/routePush" security="none" />
    <http pattern="/base/common/forbiddenDialog.jsp" security="none" />
    <http pattern="/**/index.html" security="none" />
    <http pattern="/**/ws/**" security="none" />
    <http pattern="/base/print/print/install_lodop32.exe" security="none" />
    <http pattern="/base/print/print/install_lodop64.exe" security="none" />
    <http pattern="/index/login" security="none" />
    <http pattern="/orderAlcsProcess" security="none" />
    <http pattern="/customerProcess" security="none" />
    <http pattern="/remote/**" security="none" />
    <http pattern="/notice/findAllNotice" security="none" />
    <http pattern="/notice/findNoticeById" security="none" />
    <http pattern="/dwr/**" security="none" />
    <http pattern="/base/common/image.jsp" security="none" />
    <http pattern="/randCode/takeRand" security="none" />

    <!-- http安全配置 -->
    <http auto-config="true" entry-point-ref="casEntryPoint"
    use-expressions="true" servlet-api-provision="true">
    <intercept-url pattern="/**/*" access="isAuthenticated()" />

    <!-- 尝试访问没有权限的页面时跳转的页面 -->
    <access-denied-handler error-page="/index.jsp" />

    <!-- authentication-success-handler-ref 成功之后处理类 -->
    <form-login login-page="/base/login.jsp"
    default-target-url="/base/login.jsp"
    authentication-failure-url="${cas.logoutUrl}"
    authentication-success-handler-ref="baseSuccessHandler" />
    <logout invalidate-session="true" logout-success-url="${cas.logoutUrl}" />
    <session-management session-fixation-protection="none">
    <concurrency-control />
    </session-management>
    <!-- 增加一个filter,这点与Acegi是不一样的,不能修改默认的filter了,这个filter位于FILTER_SECURITY_INTERCEPTOR之前 -->
    <custom-filter ref="casFilter" position="CAS_FILTER" />
    <custom-filter ref="baseFilter" before="FILTER_SECURITY_INTERCEPTOR" />
    </http>

    <beans:bean id="baseFilter"
    class="com.sf.oms.security.spring.BaseFilterSecurityInterceptor">
    <beans:property name="authenticationManager" ref="authenticationManager" />
    <beans:property name="accessDecisionManager" ref="accessDecisionManagerBean" />
    <beans:property name="securityMetadataSource" ref="securityMetadataSource" />
    </beans:bean>
    <!-- 用户的密码加密或解密 -->
    <beans:bean id="passwordEncoder"
    class="org.springframework.security.authentication.encoding.Md5PasswordEncoder">
    </beans:bean>
    <!-- 项目实现的用户查询服务,将用户信息查询出来 -->
    <beans:bean id="userDetailsService"
    class="com.sf.oms.security.spring.BaseUserDetailsServiceImpl">
    <beans:property name="messageSource" ref="messageSource"></beans:property>
    <beans:property name="userService" ref="userService"></beans:property>
    <beans:property name="tmDepartmentMqService" ref="departmentMqService"></beans:property>

    </beans:bean>
    <!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源 -->
    <beans:bean id="accessDecisionManagerBean"
    class="com.sf.oms.security.spring.BaseAccessDecisionManager"></beans:bean>
    <!-- 资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色访问 -->
    <beans:bean id="securityMetadataSource"
    class="com.sf.oms.security.spring.FilterInvocationSecurityMetadataSourceImpl">
    <beans:constructor-arg index="0" ref="roleService" />
    <beans:constructor-arg index="1" ref="resourceService" />
    </beans:bean>
    <!-- 定义国际化 -->
    <beans:bean id="messageSource"
    class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <beans:property name="basename" value="classpath:message_zh_CN" />
    </beans:bean>
    <!-- 成功之后处理类 该类继承springsecurity 成功后的处理类 处理一些自己的操作后再交给 springsecurity成功后的处理类
    跳转 -->
    <beans:bean id="baseSuccessHandler"
    class="com.sf.oms.security.spring.BaseAuthenticationSuccessHandler">
    <beans:property name="defaultTargetUrl" value="/base/index.jsp"></beans:property>
    <beans:property name="alwaysUseDefaultTargetUrl" value="false"></beans:property>
    <beans:property name="loginLogService" ref="loginLogService"></beans:property>
    </beans:bean>

    <!-- cas中心认证服务入口 -->
    <beans:bean id="casEntryPoint"
    class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
    <beans:property name="loginUrl"
    value="${cas.loginUrl}" />
    <beans:property name="serviceProperties" ref="serviceProperties" />
    </beans:bean>

    <!-- cas中心认证服务配置,登录成功后的返回地址 -->
    <beans:bean id="serviceProperties"
    class="org.springframework.security.cas.ServiceProperties">
    <beans:property name="service"
    value="${cas.service}" />
    <beans:property name="sendRenew" value="false" />
    </beans:bean>

    <!-- CAS service ticket(中心认证服务凭据)验证 -->
    <beans:bean id="casFilter"
    class="org.springframework.security.cas.web.CasAuthenticationFilter">
    <beans:property name="authenticationManager" ref="authenticationManager" />
    <beans:property name="authenticationSuccessHandler"
    ref="authenticationSuccessHandler" />
    <beans:property name="authenticationFailureHandler"
    ref="authenticationFailureHandler" />
    </beans:bean>

    <!-- 登录成功处理器 -->
    <beans:bean id="authenticationSuccessHandler"
    class="com.sf.oms.security.spring.BaseAuthenticationSuccessHandler">
    <beans:property name="alwaysUseDefaultTargetUrl" value="true"></beans:property>
    <beans:property name="defaultTargetUrl" value="/base/index.jsp"></beans:property>
    </beans:bean>
    <!-- 登录失败 -->
    <beans:bean id="authenticationFailureHandler"
    class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
    <beans:property name="defaultFailureUrl"
    value="${cas.logoutUrl}"></beans:property>
    </beans:bean>

    <authentication-manager alias="authenticationManager">
    <authentication-provider ref="casAuthenticationProvider" />
    </authentication-manager>

    <beans:bean id="casAuthenticationProvider"
    class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
    <beans:property name="authenticationUserDetailsService"
    ref="casAuthenticationUserDetailsService" />
    <beans:property name="serviceProperties" ref="serviceProperties" />
    <beans:property name="ticketValidator">
    <beans:bean
    class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
    <beans:constructor-arg index="0"
    value="${cas.ServerUrlPrefix}" />
    </beans:bean>
    </beans:property>
    <beans:property name="key"
    value="an_id_for_this_auth_provider_only" />
    </beans:bean>

    <beans:bean id="casAuthenticationUserDetailsService"
    class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
    <beans:property name="userDetailsService">
    <beans:ref bean="userDetailsService" />
    </beans:property>
    </beans:bean>
    <!--客户端注销 -->
    <beans:bean id="singleLogoutFilter"
    class="org.jasig.cas.client.session.SingleSignOutFilter" />


    </beans:beans>

    4.重写配置中用到的拦截器 BaseFilterSecurityInterceptor

    /**
    *
    * BaseFilterSecurityInterceptor.java
    *
    */
    package com.sf.oms.security.spring;

    import java.io.IOException;

    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;

    import org.springframework.security.access.SecurityMetadataSource;
    import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
    import org.springframework.security.access.intercept.InterceptorStatusToken;
    import org.springframework.security.web.FilterInvocation;
    import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

    /**
    * The Class BaseFilterSecurityInterceptor.
    */
    public class BaseFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {

    /** The security metadata source. */
    private FilterInvocationSecurityMetadataSource securityMetadataSource;

    /* (non-Javadoc)
    * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
    */
    public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) throws IOException, ServletException {
    FilterInvocation fi = new FilterInvocation(request, response, chain);
    invoke(fi);
    }

    /**
    * Gets the security metadata source.
    *
    * @author 596570
    * @date 2014-12-8 20:41:01
    * @since
    * @return the security metadata source
    */
    public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
    return this.securityMetadataSource;
    }

    /* (non-Javadoc)
    * @see org.springframework.security.access.intercept.AbstractSecurityInterceptor#getSecureObjectClass()
    */
    public Class<? extends Object> getSecureObjectClass() {
    return FilterInvocation.class;
    }

    /**
    * Invoke.
    *
    * @author 596570
    * @date 2014-12-8 20:41:01
    * @since
    * @param fi the fi
    * @throws IOException Signals that an I/O exception has occurred.
    * @throws ServletException the servlet exception
    */
    public void invoke(FilterInvocation fi) throws IOException,ServletException {
    InterceptorStatusToken token = super.beforeInvocation(fi);
    try {
    fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
    }finally {
    super.afterInvocation(token, null);
    }
    }

    /* (non-Javadoc)
    * @see org.springframework.security.access.intercept.AbstractSecurityInterceptor#obtainSecurityMetadataSource()
    */
    @Override
    public SecurityMetadataSource obtainSecurityMetadataSource() {
    return this.securityMetadataSource;
    }

    /**
    * Sets the security metadata source.
    *
    * @author 596570
    * @date 2014-12-8 20:41:01
    * @since
    * @param securityMetadataSource the new security metadata source
    */
    public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {
    this.securityMetadataSource = securityMetadataSource;
    }

    /* (non-Javadoc)
    * @see javax.servlet.Filter#destroy()
    */
    public void destroy() {
    // TODO Auto-generated method stub

    }

    /* (non-Javadoc)
    * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
    */
    public void init(FilterConfig filterconfig) throws ServletException {
    // TODO Auto-generated method stub

    }

    }

    5.BaseUserDetailsServiceImpl

    /**
    *
    * BaseUserDetailsServiceImpl.java
    *
    */
    package com.sf.oms.security.spring;

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;

    import org.apache.commons.collections.CollectionUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.context.MessageSource;
    import org.springframework.context.support.MessageSourceAccessor;
    import org.springframework.dao.DataAccessException;
    import org.springframework.ldap.core.DirContextAdapter;
    import org.springframework.ldap.core.DirContextOperations;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;

    import com.sf.oms.common.base.BaseUserDetail;
    import com.sf.oms.mq.dto.TmDepartmentMq;
    import com.sf.oms.mq.service.TmDepartmentMqService;
    import com.sf.oms.security.user.dto.BaseUser;
    import com.sf.oms.security.user.dto.BaseUserRole;
    import com.sf.oms.security.user.service.UserService;
    import com.sf.oms.utils.Constants;

    /**
    * The Class BaseUserDetailsServiceImpl.
    */
    @SuppressWarnings({ "unused" })
    public class BaseUserDetailsServiceImpl implements UserDetailsService,UserDetailsContextMapper {


    /** The Constant logger. */
    private static final Logger LOGGER = LoggerFactory
    .getLogger(BaseUserDetailsServiceImpl.class);

    /** The messages. */
    protected MessageSourceAccessor messages;

    /** The user service. */
    private UserService userService;

    /** The org service. */
    private TmDepartmentMqService tmDepartmentMqService;

    /* (non-Javadoc)
    * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
    */
    public UserDetails loadUserByUsername(String userAccount)
    throws UsernameNotFoundException, DataAccessException {
    Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
    BaseUser baseUser = userService.findUserByUserName(userAccount);
    if (null == baseUser) {
    LOGGER.info("用户名:{}不存在", userAccount);
    throw new UsernameNotFoundException(
    messages.getMessage("BaseUserDetailServiceImpl.notExistUser"));
    }
    try {

    //根据用户查找它所拥有的资源
    List<BaseUserRole> list = userService.findRoleByUserId(baseUser
    .getId());

    // 去重
    Set<String> l = new HashSet<String>();
    for (BaseUserRole userRole : list) {
    l.add(userRole.getRoleId());
    }
    List<GrantedAuthority> auth = new ArrayList<GrantedAuthority>();
    SimpleGrantedAuthority sga = null;
    boolean isAdminRole = false;
    if (CollectionUtils.isNotEmpty(list)) {
    for (BaseUserRole userRole : list) {
    if(Constants.ADMIN_ROLE_ID.equals(userRole.getRoleId())){
    isAdminRole = true;
    }
    sga = new SimpleGrantedAuthority(userRole.getRoleId());
    auth.add(sga);
    }
    }
    //根据用户所属区部查找经营本部
    TmDepartmentMq headerOrg = this.tmDepartmentMqService.findHeaderByAreaCode(baseUser.getRostralCode());
    String headerAreaCode = null;
    String headerAreaName = null;
    if(headerOrg != null){
    headerAreaCode = headerOrg.getDeptCode();
    headerAreaName = headerOrg.getDeptName();
    }

    // 取得用户的密码
    String password = baseUser.getPassword();
    boolean isValidity = 1 == baseUser.getIsValidity() ? true : false;
    BaseUserDetail user = new BaseUserDetail(baseUser.getId(), userAccount, baseUser.getUserName(),
    baseUser.getPassword(), baseUser.getUserCode(), baseUser.getDeptCode(), null,
    baseUser.getRostralCode(), baseUser.getRostralName(), headerAreaCode, headerAreaName, true,isAdminRole, true,
    true,l, isValidity, auth);
    return user;
    } catch (Exception e) {
    LOGGER.error(e.getMessage(), e);
    throw new UsernameNotFoundException("系统错误");
    }

    }

    /**
    * Sets the message source.
    */
    public void setMessageSource(MessageSource messageSource) {
    this.messages = new MessageSourceAccessor(messageSource);
    }

    /**
    * Sets the user service.
    */
    public void setUserService(UserService userService) {
    this.userService = userService;
    }

    /**
    * @param tmDepartmentMqService the tmDepartmentMqService to set
    */
    public void setTmDepartmentMqService(TmDepartmentMqService tmDepartmentMqService) {
    this.tmDepartmentMqService = tmDepartmentMqService;
    }

    @Override
    public UserDetails mapUserFromContext(DirContextOperations ctx,
    String username, Collection<? extends GrantedAuthority> authorities) {
    return this.loadUserByUsername(username);
    }

    @Override
    public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
    // TODO Auto-generated method stub
    }

    }

    5.BaseAccessDecisionManager

    /**
    *
    * BaseAccessDecisionManager.java
    *
    */
    package com.sf.oms.security.spring;

    import java.util.Collection;
    import java.util.Iterator;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.security.access.AccessDecisionManager;
    import org.springframework.security.access.AccessDeniedException;
    import org.springframework.security.access.ConfigAttribute;
    import org.springframework.security.access.SecurityConfig;
    import org.springframework.security.authentication.InsufficientAuthenticationException;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;

    /**
    * The Class BaseAccessDecisionManager.
    */
    public class BaseAccessDecisionManager implements AccessDecisionManager {

    /** The Constant logger. */
    private static final Logger LOGGER = LoggerFactory.getLogger(BaseAccessDecisionManager.class);

    //In this method, need to compare authentication with configAttributes.
    // 1, A object is a URL, a filter was find permission configuration by this URL, and pass to here.
    // 2, Check authentication has attribute in permission configuration (configAttributes)
    // 3, If not match corresponding authentication, throw a AccessDeniedException.
    /* (non-Javadoc)
    * @see org.springframework.security.access.AccessDecisionManager#decide(org.springframework.security.core.Authentication, java.lang.Object, java.util.Collection)
    */
    public void decide(Authentication authentication, Object object,Collection<ConfigAttribute> configAttributes)throws AccessDeniedException, InsufficientAuthenticationException {
    if(configAttributes == null){
    return ;
    }
    Iterator<ConfigAttribute> ite=configAttributes.iterator();
    while(ite.hasNext()){
    ConfigAttribute ca=ite.next();

    String needAuthority=((SecurityConfig)ca).getAttribute();
    for(GrantedAuthority ga:authentication.getAuthorities()){
    if(needAuthority.equals(ga.getAuthority())){
    return;
    }
    }
    }

    if(authentication.getPrincipal() instanceof UserDetails){
    UserDetails userDetails = (UserDetails)authentication.getPrincipal();
    LOGGER.info( userDetails.getUsername() + " access " + object);
    }
    LOGGER.info(authentication + "访问无权限的" + object);
    throw new AccessDeniedException("no right");
    }

    /* (non-Javadoc)
    * @see org.springframework.security.access.AccessDecisionManager#supports(org.springframework.security.access.ConfigAttribute)
    */
    public boolean supports(ConfigAttribute attribute) {
    return true;
    }

    /* (non-Javadoc)
    * @see org.springframework.security.access.AccessDecisionManager#supports(java.lang.Class)
    */
    public boolean supports(Class<?> clazz) {
    return true;
    }

    }

    6.FilterInvocationSecurityMetadataSourceImpl

    /**
    *
    * FilterInvocationSecurityMetadataSourceImpl.java
    *
    */
    package com.sf.oms.security.spring;

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;

    import org.apache.commons.lang3.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.security.access.ConfigAttribute;
    import org.springframework.security.access.SecurityConfig;
    import org.springframework.security.web.FilterInvocation;
    import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

    import com.sf.oms.cache.base.CacheUtil;
    import com.sf.oms.cache.buscache.base.CacheConstant;
    import com.sf.oms.security.resource.dto.BaseResource;
    import com.sf.oms.security.resource.service.ResourceService;
    import com.sf.oms.security.role.dto.BaseRoleResource;
    import com.sf.oms.security.role.service.RoleService;

    /**
    * The Class FilterInvocationSecurityMetadataSourceImpl.
    */
    public class FilterInvocationSecurityMetadataSourceImpl implements
    FilterInvocationSecurityMetadataSource {

    /** The role service. */
    private RoleService roleService;

    /** The resource service. */
    private ResourceService resourceService;

    /** The Constant logger. */
    private static final Logger LOGGER = LoggerFactory
    .getLogger(FilterInvocationSecurityMetadataSourceImpl.class);

    /**
    * Instantiates a new filter invocation security metadata source impl.
    *
    * @param roleService
    * the role service
    * @param resourceService
    * the resource service
    */
    public FilterInvocationSecurityMetadataSourceImpl(RoleService roleService,
    ResourceService resourceService) {
    this.resourceService = resourceService;
    this.roleService = roleService;
    }

    /**
    * Gets the resource map.
    */
    private Map<String, Collection<ConfigAttribute>> getResourceMap() {
    Map<String, Collection<ConfigAttribute>> resourceMap = null;
    try {
    //先从缓存中查找是否有资源,如果没有就从数据库加载,并放入缓存
    resourceMap = CacheUtil.getMap(CacheConstant.OMS_RESOURCE_MAP);
    if (null == resourceMap) {
    resourceMap = loadResourceDefine();
    CacheUtil.setMapAll(CacheConstant.OMS_RESOURCE_MAP, resourceMap);
    }
    } catch (Exception e) {
    LOGGER.error(e.getMessage(), e);
    }
    return resourceMap;
    }

    /**
    * Load resource define.
    */
    private Map<String, Collection<ConfigAttribute>> loadResourceDefine() {
    //定义SpringSecurity的权限集合
    Map<String, Collection<ConfigAttribute>> resourceMaps = new HashMap<String, Collection<ConfigAttribute>>();
    //查询所有的角色与资源的关系
    List<BaseRoleResource> roleResourceList = roleService.findAllRoleResource();
    //查询所有的资源
    List<BaseResource> baseResourceList = resourceService.findAllResource();
    Collection<ConfigAttribute> atts = null;

    //找到角色与资源的对应有关系
    for (BaseResource baseResource : baseResourceList) {
    // 查找resourceCode对应的roleCode
    List<String> roleCodeList = searchRole(baseResource.getId(),
    roleResourceList);

    ConfigAttribute ca = null;
    String url = baseResource.getResourceUrl();
    if (StringUtils.isEmpty(url)) {
    continue;
    }
    String[] urls = url.split(",");
    for (String key : urls) {
    key = getTrueUrl(key);
    if (resourceMaps.containsKey(key)) {
    atts = resourceMaps.get(key);
    } else {
    atts = new ArrayList<ConfigAttribute>();
    }

    for (String string : roleCodeList) {
    ca = new SecurityConfig(string);
    atts.add(ca);
    }

    resourceMaps.put(key, atts);
    }

    }
    return resourceMaps;
    }

    /**
    * Search role.
    */
    private List<String> searchRole(String resCode,
    List<BaseRoleResource> roleResourceList) {
    List<String> result = new ArrayList<String>();
    for (Iterator<BaseRoleResource> iterator = roleResourceList.iterator(); iterator
    .hasNext();) {
    BaseRoleResource baseRoleResource = (BaseRoleResource) iterator
    .next();
    if (resCode.equals(baseRoleResource.getResourceId())) {
    result.add(baseRoleResource.getRoleId());
    iterator.remove();
    }
    }
    return result;
    }

    // According to a URL, Find out permission configuration of this URL.
    /*
    * (non-Javadoc)
    *
    * @see
    * org.springframework.security.access.SecurityMetadataSource#getAttributes
    * (java.lang.Object)
    */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Collection<ConfigAttribute> getAttributes(Object object)
    throws IllegalArgumentException {
    //SpringSecurity会调用此方法,根据URL获取拥有该URL的角色
    //如果没有就返回一个DENY的SecurityConfig
    String url = ((FilterInvocation) object).getRequestUrl();
    url = getTrueUrl(url);
    Map<String, Collection<ConfigAttribute>> resourceMap = getResourceMap();
    Collection<ConfigAttribute> cca = resourceMap.get(url);
    if (cca == null || cca.size() < 1) {
    cca = new ArrayList(1);
    ConfigAttribute ca = new SecurityConfig("DENY");
    cca.add(ca);
    }
    return cca;
    }

    /**
    * Gets the true url.
    *
    * @author 596570
    * @date 2014-12-8 20:41:07
    * @since
    * @param url
    * the url
    * @return the true url
    */
    private String getTrueUrl(String url) {
    //处理URL,去其参数
    int index = url.indexOf("?");
    if (index > 0) {
    url = url.substring(0, index);
    }
    return url;
    }

    /*
    * (non-Javadoc)
    *
    * @see
    * org.springframework.security.access.SecurityMetadataSource#supports(java
    * .lang.Class)
    */
    public boolean supports(Class<?> clazz) {
    return true;
    }

    /*
    * (non-Javadoc)
    *
    * @see org.springframework.security.access.SecurityMetadataSource#
    * getAllConfigAttributes()
    */
    public Collection<ConfigAttribute> getAllConfigAttributes() {
    return null;
    }

    /**
    * Refresh resource.
    *
    * @author 596570
    * @date 2014-12-8 20:41:07
    * @since
    */
    public void refreshResource() {
    try {
    //清除缓存中的资源集合,让其重新从数据库中加载
    CacheUtil.removeKey(CacheConstant.OMS_RESOURCE_MAP);
    } catch (Exception e) {
    LOGGER.error(e.getMessage(), e);
    }
    }

    }

    7.BaseAuthenticationSuccessHandler

    /**
    *
    * BaseAuthenticationSuccessHandler.java
    *
    */
    package com.sf.oms.security.spring;

    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.NetworkInterface;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    import java.sql.Timestamp;
    import java.util.Date;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;

    import com.sf.oms.common.base.BaseUserDetail;
    import com.sf.oms.common.log.dto.LoginLog;
    import com.sf.oms.common.log.service.LoginLogService;
    import com.sf.oms.security.user.dto.BaseUser;

    /**
    * The Class BaseAuthenticationSuccessHandler.
    */
    @SuppressWarnings("unused")
    public class BaseAuthenticationSuccessHandler extends
    SavedRequestAwareAuthenticationSuccessHandler {

    /** The Constant USER_AGENT. */
    private static final String USER_AGENT = "User-Agent";

    /** The Constant logger. */
    private static final Logger LOGGER = LoggerFactory
    .getLogger(BaseAuthenticationSuccessHandler.class);

    /** The login log service. */
    @Autowired
    private LoginLogService loginLogService;

    /* (non-Javadoc)
    * @see org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler#onAuthenticationSuccess(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.Authentication)
    */
    public void onAuthenticationSuccess(HttpServletRequest request,
    HttpServletResponse response, Authentication authentication)
    throws IOException, ServletException {
    LOGGER.debug(
    "用户:{}在时间{},IP地址为{}登录成功!",
    new Object[] { authentication.getPrincipal(),
    new Timestamp(new Date().getTime()),
    request.getRemoteAddr() });
    LoginLog login = new LoginLog();

    // modify by wds 20141048,user-agent,去掉特殊字符,防止XSS注入
    String agent = request.getHeader(USER_AGENT);
    agent = agent.replace("<", "").replace(">", "").replace("%", "")
    .replace("/", "");
    login.setAgent(agent);
    // login.setIp(request.getRemoteAddr());
    String ip = getIpAddr(request);
    String serverIp=getLocalIP();//服务器节点Ip
    login.setIp(ip);
    login.setServerIp(serverIp);
    login.setUserId(((BaseUserDetail) authentication.getPrincipal())
    .getUserName());
    login.setLoginTime(new Timestamp(new Date().getTime()));
    this.loginLogService.insertLog(login);
    super.onAuthenticationSuccess(request, response, authentication);
    }

    /**
    * Sets the login log service.
    *
    */
    public void setLoginLogService(LoginLogService loginLogService) {
    this.loginLogService = loginLogService;
    }

    /**
    * Gets the ip addr.
    */
    private String getIpAddr(HttpServletRequest request) {
    String ipAddress = null;
    // ipAddress = this.getRequest().getRemoteAddr();
    ipAddress = request.getHeader("x-forwarded-for");
    if (ipAddress == null || ipAddress.length() == 0
    || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getHeader("Proxy-Client-IP");
    }
    if (ipAddress == null || ipAddress.length() == 0
    || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getHeader("WL-Proxy-Client-IP");
    }
    if (ipAddress == null || ipAddress.length() == 0
    || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getRemoteAddr();
    if ("127.0.0.1".equals(ipAddress)) {
    // 根据网卡取本机配置的IP
    InetAddress inet = null;
    try {
    inet = InetAddress.getLocalHost();
    } catch (UnknownHostException e) {
    LOGGER.error(e.getMessage(), e);
    }
    ipAddress = inet.getHostAddress();
    }

    }
    // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
    if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
    // = 15
    if (ipAddress.indexOf(",") > 0) {
    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
    }
    }
    return ipAddress;
    }

    /**
    * 获取本机的IP地址
    * 目的:可记录用户访问系统时被分配到某个节点为,方便日志查询
    *
    * @date 2014年12月22日 上午10:15:46
    * @author 596570
    * @since V2.2
    * @return 本机的IP地址
    */
    public String getLocalIP(){
    InetAddress addr = null;
    try {
    addr = InetAddress.getLocalHost();
    } catch (Exception e) {
    LOGGER.error(e.getMessage(), e);
    }

    byte[] ipAddr = addr.getAddress();
    String ipAddrStr = "";
    for (int i = 0; i < ipAddr.length; i++) {
    if (i > 0) {
    ipAddrStr += ".";
    }
    ipAddrStr += ipAddr[i] & 0xFF;
    }
    return ipAddrStr;
    }

    }

    8.配置文件中的变量参数

    cas.logoutUrl=http://cas.sit.com/cas/logout?service=http://localhost:10008/oms-front/base/login.jsp
    cas.service=http://localhost:10008/oms-front/j_spring_cas_security_check
    cas.loginUrl=http://cas.sit.com/cas/login
    cas.ServerUrlPrefix=http://cas.sit.com/cas

    9.所需jar包

    //cas
    compile group: "cas", name: "cas-client-core", version:"3.2.1"
    compile group: "cas", name: "sf-framework-share-cas", version:"1.7.9"
    compile group: "cas", name: "sf-cas-encrypt", version:"1.4"
    compile group: "cas", name: "spring-security-cas", version:"3.1.0.RC3"

    主要参考:http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece763105392230e54f73c6f888b442282c45f93130a1c187bb8e7737f0704a5932b2152f4174bea863c72320925a09bbfd20c82e5866d72c8713b214fc75612a248e88a00789e37912aacf849f0bb8069cfea8f828c1208970f127bf0b2cb01444f9438a54326e2d6ce0c460157e9ab6d25&p=9a6cc64ad4af19ff57ee9478445d88&newp=9a79c54ad5c347e940fec92d02148a231610db2151d2d601298ffe0cc4241a1a1a3aecbf26241a00d0c77c6500a84e56e8fa3076350834f1f689df08d2ecce7e69903469&user=baidu&fm=sc&query=cas+customWebInvocationPrivilegeEvaluator&qid=c5838a270000c537&p1=3

  • 相关阅读:
    数据访问(从数据库中访问数据)
    加载类、设计模式(单例模式和工厂模式)
    面向对象之静态
    面向对象三大特性之继承和多态
    面向对象三大特性之封装
    面向对象基础知识
    mysql下载与安装过程
    Idea添加依赖的步骤:
    Java JDBC 在IDEA环境下连接MySQL
    JAVA中集合HashMap嵌套联系
  • 原文地址:https://www.cnblogs.com/junwangzhe/p/6069861.html
Copyright © 2011-2022 走看看