SSO单点登录

一.实现原理

     SSO是一种统一认证和授权机制,指访问同一服务器不同应用中的受保护资源的同一用户,只需要登录一次,即通过一个应用中的安全验证后,再访问其他应用中的受保护资源时,不再需要重新登录验证。简单的说就是在一个多系统共存的环境下,用户在某一系统中登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。

二.实现方式

 方式1:共享session

 1.web.xml
<!--  Spring Session Filter -->
<filter>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
     
<filter>
    <filter-name>sso</filter-name>
    <filter-class>com.capital.bbs.filter.UserSsoLoginVerifyFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>sso</filter-name>
    <url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>sso</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>sso</filter-name>
    <url-pattern>*.html</url-pattern>
</filter-mapping>
2.添加jar包:  jedis-x.x.x.jar
3.redis.properties
jedis.host=127.0.0.1
jedis.port=7408
jedis.password=123123
jedis.timeout=30000
jedis.pool.maxTotal=200
jedis.pool.minIdle=1
jedis.pool.maxIdle=50
jedis.pool.maxWaitMillis=5000
jedis.pool.testOnBorrow=true
jedis.pool.testOnReturn=true
4.applicationContext_client.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                       http://cxf.apache.org/transports/http/configuration
                 http://cxf.apache.org/schemas/configuration/http-conf.xsd ">

    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-xml.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-http.xml"/>

    <http-conf:conduit name="*.http-conduit">
         <http-conf:client ConnectionTimeout="180000" ReceiveTimeout="300000"/>
    </http-conf:conduit>

    <!-- redis -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="${jedis.pool.maxTotal}"/>
        <property name="maxIdle" value="${jedis.pool.maxIdle}"/>
        <property name="minIdle" value="${jedis.pool.minIdle}"/>
        <property name="maxWaitMillis" value="${jedis.pool.maxWaitMillis}"/>
        <property name="testOnBorrow" value="${jedis.pool.testOnBorrow}"/>
        <property name="testOnReturn" value="${jedis.pool.testOnReturn}"/>
    </bean>

    <bean id="jedisConnectionFactory"
          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${jedis.host}" />
        <property name="port" value="${jedis.port}" />
        <property name="password" value="${jedis.password}" />
        <property name="timeout" value="${jedis.timeout}" />
        <property name="poolConfig" ref="jedisPoolConfig" />
        <property name="usePool" value="true" />
    </bean>

    <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
        </property>
        <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
        </property>
        <property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
        </property>
    </bean>

    <!-- 将session放入redis -->
    <bean id="redisHttpSessionConfiguration"
          class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
        <property name="maxInactiveIntervalInSeconds" value="1800" />
    </bean>
    <bean id="defaultCookieSerializer"
          class="org.springframework.session.web.http.DefaultCookieSerializer">
        <property name="cookieName" value="WEB_SESSION_ID" />
        <property name="cookiePath" value="/" />
    </bean>
    <bean id="cookieHttpSessionStrategy"
          class="org.springframework.session.web.http.CookieHttpSessionStrategy">
        <property name="cookieSerializer" ref="defaultCookieSerializer" />
    </bean>
</beans>
5.applicationContext_hibernate.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-2.5.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
      http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">


    <!-- JDBC参数配置 -->
    <bean id="propertyConfigurer"  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"   lazy-init="true">
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
        <property name="ignoreResourceNotFound" value="true" />
        <property name="locations">
            <list>
                <value>classpath:/jdbc.properties</value>
                <!--begin redis sso-->
                <value>classpath:/redis.properties</value>
                <!--end redis sso-->
            </list>
        </property>
    </bean>
</beans>
6.UserSsoLoginVerifyFilter过滤器示例:
import com.capital.bbs.common.criteria.UserCriteria;
import com.capital.bbs.common.dto.user.UserDTO;
import com.capital.bbs.manager.user.IUserManager;
import com.capital.common.vo.user.UserVO;
import com.opensymphony.xwork2.ActionContext;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class UserSsoLoginVerifyFilter extends StrutsPrepareAndExecuteFilter {

    private static final Logger LOGGER = LogManager.getLogger(UserSsoLoginVerifyFilter.class);

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        //当前系统登录存放的session
        Object userOid = request.getSession().getAttribute("userOid");
        if (null == userOid) {
            //单点登录,其他相关系统共享存放的session
            UserVO user = (UserVO) ActionContext.getContext().getSession().get("loginUser");
            if (null != user) {
                try {
                    ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
                    IUserManager userManager = (IUserManager) ac.getBean("userManager");
                    UserCriteria userCriteria = new UserCriteria();
                    UserDTO userDTO = new UserDTO();
                    //通过共享session里面的用户名获取用户信息
                    userDTO.setUserName(user.getUserName());
                    userDTO.setUserOid(user.getUserOid());
                    userCriteria.setUser(userDTO);
                    userDTO = userManager.doSsoLogin(userCriteria);
                    if (null != userDTO) {
                        request.getSession().setAttribute("userOid", user.getUserOid());
                    }
                }catch (Exception e){
                    LOGGER.error("单点登录过滤器中查询用户信息失败");
                }
            }
        }
        filterChain.doFilter(request, response);
    }

}

三.约束:

  1.session中所涉及的类型必须是子系统中共同拥有的(即程序集、类型都需要一致),这导致session的使用受到诸多限制;
  2.跨顶级域名的情况完全无法处理。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值