侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

利用Spring Security 3.2的remember-me搭建SSO

2022-07-02 星期六 / 0 评论 / 0 点赞 / 92 阅读 / 12151 字

回顾 在上一篇文章,我实现了Spring Security3.2搭建的第一个网站应用firstWeb.进阶-使用Spring Security3.2搭建LDAP认证授权和Remember-me。 而在

回顾

在上一篇文章,我实现了Spring Security3.2搭建的第一个网站应用firstWeb. 进阶-使用Spring Security3.2搭建LDAP认证授权和Remember-me。 而在更早的时候,我有使用Apache+tomcat搭建cluster,Apache httpd与tomcat集群。接下来,我将利用之前的作品,继续向更远的地方前进。

提纲

  1. 为firstWeb应用创建cluster。

  2. 创建并部署一个新的应用secondWeb。

  3. 使用Remember-me机制实现firstWeb与secondWeb的SSO。

架构示意图

此图是为最终形态而画的,今天的实验并不涉及CAS,请忽略CAS。

由上图可见,Apache作为一个逆向代理,提供两个虚拟主机,两个虚拟主机均在.test.com域中。其中一个虚拟主机为cluster, Apache需要为其提供负载平衡服务。另外,Apache开启了SSL。

所有Apache的配置可以在此下载:http://pan.baidu.com/s/1i37fUFb

由于之前的文章已经有配置好OpenLDAP,OpenSSL,所以本文将在此基础上搭建网站。想从头开始的请往前翻。

FirstWeb集群

FirstWeb是我们在上一篇文章所产生的应用,如果需要将FirstWeb部署为cluster的话,需要四个步骤:

  1. 在FristWeb的web.xml中添加配置,使其支持session同步。

    <distributable/>
  2. 配置tomcat1和tomcat2的server.xml,使它们成为cluster。详细见Apache httpd与tomcat集群 。

  3. 配置Apache逆向代理,做负载平衡。

    <VirtualHost *:443>   ServerAdmin joey   ServerName first.test.com   ErrorLog "logs/firstWebDetail"   CustomLog "logs/accessFisrtWeb" common      SSLEngine on   SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5   SSLCertificateFile "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/conf/server.crt"   SSLCertificateKeyFile "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/conf/server.key"      LogLevel debug   ProxyRequests Off   ProxyPreserveHost On   ProxyPass /firstWeb balancer://mycluster/firstWeb   ProxyPassReverse /firstWeb balancer://mycluster/firstWeb   <Proxy balancer://mycluster>      BalancerMember ajp://127.0.0.1:8009 loadfactor=1 route=node1      BalancerMember ajp://127.0.0.1:8010 loadfactor=1 route=node2	  ProxySet stickysession=JSESSIONID	  ProxySet lbmethod=byrequests   </Proxy></VirtualHost>
  4. 配置DNS,建立ip和域名映射。(无条件的同学可以修改本地的hosts文件)。

FirstWeb的源码在此:http://pan.baidu.com/s/1nthpuDN 

SecondWeb开发部署

快速开发secondWeb,并将其部署到tomcat3上。

SecondWeb非常简单,它只包含两个页面,一个登陆页面和一个Index页面。Index页面是受保护的,未认证的用户访问奖杯转到登陆页面。secondWeb的源码可以从这里下载http://pan.baidu.com/s/1o64TQ9k。 SecondWeb同样使用Spring Security 3.2,并使用和FirstWeb相同的LDAP。

配置逆向代理:

<VirtualHost *:443>   ServerAdmin joey   ServerName second.test.com   ErrorLog "logs/secondWebDetail"   CustomLog "logs/accessSecondWeb" common      SSLEngine on   SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5   SSLCertificateFile "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/conf/server.crt"   SSLCertificateKeyFile "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/conf/server.key"      LogLevel debug   ProxyRequests Off   ProxyPreserveHost On   ProxyPass /secondWeb ajp://127.0.0.1:8011/secondWeb   ProxyPassReverse /secondWeb ajp://127.0.0.1:8011/secondWeb</VirtualHost>

现在启动tomcat1,2,3, 然后启动apache,我们可以访问以下两个网站了:

https://first.test.com/firstWeb

https://second.test.com/secondWeb

使用Remember-me构建SSO

Remember-me的原理是在cookie中存有一个token,这个token包含了用户名,加密后的密码,过期时间,以及一个混入的key。remember me cookie value的生成默认算法为:

value = Base64(username:MD5(password):expireDateValue:key)

MD5是默认的,可以选择不同的算法为密码加密。 key可以声明,如果没有声明key,Spring Security将使用一个Random GUUID. GUUID在不同的server,不同的context下都是不同的。每次重启server也会不同。我们当然可以声明一个固定的key值。

当用户携带这个cookie访问网站的时候,网站会使用此token与LDAP中的用户信息比对,比对成功以后,则自动登录此用户。

于是我想,如果我的两个网站共用remember me的cookie的话,一旦一个网站登录了,另一个网站就可以实现自动登录了。

需要克服的一个难点,Spring Security中的RememberMeAuthenticationFilter所使用的cookie是有限制的,例如

secondWeb的remember-me cookie只对http://second.test.com/secondWeb有用,我需要改写cookie的作用域和cookie的过期时间,以达到对整个.test.com域的作用。

我需要在上面的firstWeb和secondWeb基础上,修改代码。步骤如下:

  1. 配置相同的LDAP认证。(已经满足,跳过)

  2. 修改代码,为每个remember me指定相同的混入key -".test.com"。 如下:

            @Override	public void configure(HttpSecurity http) throws Exception {		http		... ...		.and()		.rememberMe().tokenValiditySeconds(15*24*60*60)		.key(".test.com"); // 使用一个固定的key.	}
  3. 创建一个新的SevletFilter,进行RememberMe cookie的改写。

    //RememberMeCookieFilter.java    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {        HttpServletRequest req = (HttpServletRequest)request;        Cookie newCookie = null;        Cookie[] cookies = req.getCookies();        if ((cookies != null) && (cookies.length > 0)) {            for (Cookie cookie : cookies) {                if ("remember-me".equals(cookie.getName())) {                    newCookie = new Cookie(cookie.getName(), cookie.getValue());                    newCookie.setHttpOnly(cookie.isHttpOnly());                    newCookie.setSecure(cookie.getSecure());                    // Control following                    // 设置cookie过期时间                    newCookie.setMaxAge(cookie.getMaxAge());                    // 设置cookie的有效路径                    newCookie.setPath("/");                    // 设置cookie的有效域                    newCookie.setDomain(".test.com");                }            }        }         chain.doFilter(request, response);        if (newCookie != null) {            HttpServletResponse rep = (HttpServletResponse)response;            rep.addCookie(newCookie);        }    }
  4. 将RememberMeCookieFilter注册到SpringSecurityFilterChain中去。在每个httpSecurity中注册,如下例子:

        public void configure(HttpSecurity http) throws Exception {        // 将RememberMeCookieFilter注册到SpringSecurityFilterChain中        // 并放置在HeaderWriterFilter之前。        http        .addFilterBefore(new RememberMeCookieFilter(), HeaderWriterFilter.class)        ... ...    }
  5. (没有包含在实验中)为logout添加一个handler,将cookie删除。

  6. 然后重新打包部署FirstWeb和SecondWeb。

通过上面的filter,remember me cookie的作用域变成了

domain:   .test.com path:     /

两个网站 https://first.test.com/firstWeb 与 https://second.test.com/secondWeb 共用remember me cookie.

现在两个网站可以通过使用Remember Me的cookie进行SSO了。得到启发的人,可以对上面的代码进行改进,使得更健壮。

这部分的代码可以从以下地址下载:http://pan.baidu.com/s/1jDDpW

下一步使用CAS搭建Cluster

Spring Security 3和CAS 3.5.2集成的完整实例 



广告 广告

评论区