需求:将项目从springSecurity验证登录改为统一认证sso登录,将原数据库中用户账号、密码、邮箱信息迁移至统一认证端数据中,保留原客户端项目的使用SpringSecurity进行权限角色管理部分

最终选择spring boot +oauth2 ,用到 @EnableOAuth2Sso注解实现单点登录,主要参考:

  Spring Boot+OAuth2,一个注解搞定单点登录! - 江南一点雨 (javaboy.org)

本文记录踩坑与学习与实战记录(未更完)

目录

基础知识学习

cas和sso(了解):

cas

通过cas实现单点登录 

Spring Security

身份认证流程解析

自定义用户密码验证

Sprint Security 用户权限管理

做到一个用户只能登录一次

彻底理解 Cookie、Session、Token

Spring Security基于oauth2的sso单点登录(最后使用的方式)

 开源框架XXL-SSO

实战江南一点雨:

遇到的问题:

用户权限管理时

auth端无法跳转index


一.基础知识学习

1.1 cas和sso(了解):

【单点登录】什么是 SSO 与 CAS?_happydecai的博客-CSDN博客_cas和sso

sso是一种框架,cas是实现sso的一种方法,当然,还有其他的方法,例如cookie

1.1.1 cas

从结构上看,CAS 包含两个部分: CAS Server 和 CAS Client。CAS Server 需要独立部署,主要负责对用户的认证工作;CAS Client 负责处理对客户端受保护资源的访问请求,需要登录时,重定向到 CAS Server。下图是 CAS 最

链接:单点登录之CAS原理和实现_金玉良缘-CSDN博客_cas单点登录实现原理

1.1.2 cas和oauth2 的区别

CAS的单点登录和oauth2的最大区别 - 剑握在手 - 博客园

1.1.3. 通过cas实现单点登录 

Spring Security 集成CAS实现单点登录 - 阿狸哥哥 - 博客园

1.2 Spring Security

security 有认证和授权两个功能 以session作为交互

1.2.1 身份认证流程解析

最简单易懂的Spring Security 身份认证流程讲解 - 曾俊杰的专栏 - 博客园 (cnblogs.com)

1.2.2 自定义用户密码验证

关于密码验证源码解读写于0706 · 语雀 (yuque.com)

重写密码验证filter:

SpringSecurity的自定义用户密码验证 - 洋洋哥 - 博客园 (cnblogs.com)

1.2.3 Sprint Security 用户权限管理

1. 在config配置文件中配置:分为hasAuthority(String)、hasRole(String)、hasIpAddress(String)

(2条消息) Spring Security--角色权限判断_我和井盖都笑了博客-CSDN博客_springsecurity 判断权限

protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/**").hasAnyRole("ROLE_USER", "ROLE_ADMIN")
                .antMatchers("/admin/**").hasRole("ROLE_ADMIN")
                // 如果发来的请求是指定的 IP 就允许访问
                // 可以通过 request.getRemoteAddr()获取 ip 地址。
                .antMatchers("/api/**").hasIpAddress("localhost")
                .antMatchers("/api/**").hasAuthority("admin")
                  

                .and().logout().deleteCookies("JSESSIONID", oauthCookieName).invalidateHttpSession(true)
                // 这样保证在客户端logout的时候就在服务端logout
                .logoutSuccessUrl("http://{server.ip}/logout")

                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated();
        // 保证只有单方登录,同时需要在auth端也配置这条,客户端/logout了同时就会在统一认证端也执行logout
        http.sessionManagement().maximumSessions(1).expiredUrl("/logout");

    }

2. 使用注解@PreAuthorize 进行管理权限

@PreAuthorize 注解,顾名思义是进入方法前的权限验证,@PreAuthorize 声明这个方法所需要的权限表达式,例如:@PreAuthorize("hasAuthority('sys:dept:delete')"),

@PreAuthorize 权限控制的原理 - 简书 (jianshu.com)

3. 自定义注解进行权限管理

(2条消息) Java自定义注解实现权限管理_小识的博客-CSDN博客_注解实现权限管理

1.2.4 做到一个用户只能登录一次

1. 最大同时登录为1,且配置session过期重定位地址,直接将原来登录处踢出
当spring security检查到session过期后,若未做任何配置,spring security会返回一个用户不友好的页面,因此我们通常需要设置一个地址,当spring security检查到session过期后,将请求重定位到我们的地址上,设置代码如下所示:

 http
                .sessionManagement().maximumSessions(1).expiredUrl("/logout");

参考链接:

spring scurity session管理 - SegmentFault 思否

2. 当再次登录时阻止其认证而不是强制踢出上一次登录:

当一个用户已经认证过了,在另外一个地方重新进行登录认证,spring security可以阻止其再次登录认证,从而保持原来的会话可用性;具体的代码设置如下所示

http.sessionManager().maximumSession(1).maxSessionsPreventsLogin(true);

参考链接: 

spring security 关于 http.sessionManagement().maximumSessions(1);的探究 - 岑惜 - 博客园 (cnblogs.com)

1.2.5  Cookie、Session、Token

1. 三者的关系

springbsecurity 登录token验证过滤器_彻底理解 Cookie、Session、Token_weixin_39693662的博客-CSDN博客

2. springsecurity session详解:

参考:

Spring Security 控制Session详解 - 简书 (jianshu.com)

3. springSecurity 修改session中的信息

遇到场景 : 前端通过session获取当前用户信息,当前用户信息在前端页面发生了改变时(比如用户update了自己的email属性);可能数据库里面已经update了,而程序没有重启或者用户没有重新登陆,则session中的值是不会发生改变的,即验证的用户信息也是不变的,前端显示也并不会更新

SpringSecurity-日常踩坑,修改session中的用户信息。 - EalenXie - 博客园 (cnblogs.com)

4. 根据session获取用户名

SpringSecurity-日常踩坑,修改session中的用户信息。 - EalenXie - 博客园 (cnblogs.com)

1.3 Spring Security基于oauth2的sso单点登录(最后使用的方式)

1. oauth2 主要目的是为了第三方登录(例如微信授权), 提供以token作为访问权限

参考:Spring Security基于Oauth2的SSO单点登录怎样做? - 程序员大本营

2. 当客户端用security时:(2条消息) 基于Spring Security + OAuth2 的SSO单点登录(客户端)_Janche的博客-CSDN博客_oauth2 客户端登录

3.  @EnableOAuth2Sso注解实现单点登录(在客户端使用,客户端用的是security验证登录)

(最终参考的方案) 

 Spring Boot+OAuth2,一个注解搞定单点登录! - 江南一点雨 (javaboy.org)

auth端连接数据库验证用户账号和密码需要配置datasource config需要配置

客户端有单独的权限管理,在security中配置,详见"Sprint Security 用户权限管理"

4. 注册

spring-security-oauth2(二十二) 重构注册逻辑_codeing-tiger-CSDN博客_oauth2 注册

1.4 开源框架XXL-SSO

分布式单点登录框架XXL-SSO - 许雪里 - 博客园

实现时遇到的问题:

做了很多尝试把xxl-sso框架和springSecurity框架集成,但客户端无法获取用户信息,无法实现原因:统一验证那边验证登录成功了,两边的session统一,但是客户端项目的security验证没有通过,而我们需要它的username password拦截器验证通过,才能获得我们所需要的principal

二. 实战:

参考项目地址:

https://github.com/lenve/oauth2-samples

clone项目后分别打开oauth2-sso/auth-server(认证端)、oauth2-sso/client1(客户端1)、oauth2-sso/client2(客户端2),开启后可以实现统一认证登录

接下来进行一些拓展:

2.1 客户端登录成功后跳转index页面

传送门:

SpringBoot 登陆后跳转到index页面_aqing617的博客-CSDN博客

2.2 客户端登出

客户端的登出添加配置

          http
            .logout()
//                .logoutUrl("/logout")
//                .deleteCookies("s1","JSESSIONID")
                 // 在登出后,是否要清空当前session
//                .invalidateHttpSession(true)
            //   服务端登出
            .logoutSuccessUrl("http://localhost:1111/logout");

认证端添加的配置:

http
      .logout();

2.3 一个用户只允许登录一次 

需求:每个用户在浏览器a登录后,在浏览器b再次登录,此时要求浏览器a 该用户被踢出

在认证端和客户端都添加配置

 http
                .sessionManagement().maximumSessions(1).expiredUrl("/logout");

2.4 认证端连接数据库验证用户信息

原项目中,用户信息是存在与程序内存中的,现添加配置,使得用户信息存储于数据库中

1. securityConfig中替换

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(userAuthenticationProvider).userDetailsService(userService).passwordEncoder(passwordEncoder);
    }

2. 添加datasourceConfig,连接数据库        

通过添加import com.mysql.jdbc.Driver;自动在pom文件中添加依赖

搭建单点登录服务器,新建数据库用户表用于用户验证

3. 注入bean

4. 定义user类,实现UserDetails接口

5.定义UseDAO

6. 定义UserService实现UserDetailService接口

7.添加认证处理类,即1.中所用的

8. application.properties添加配置,连接数据库

2.5 新增user-center客户端,用于展示引导链接到各个客户端

首先在认证端新增接口,登录成功后跳转用户中心客户端

@GetMapping("/")
    public void redirect2UserCenter(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.sendRedirect("http://localhost:1112");
    }

(未完待续) 

2.6 添加统一认证端的注册逻辑 

在认证端新增注册接口,调用后转发调用客户端接口,在认证端数据库和客户端数据库都添加用户信息

(未完待续)

2.7 客户端权限管理

(未完待续) 

遇到的问题:

(未完待续)

用户权限管理时

尝试了多种方法解决用户权限管理,用security自己的配置(获取不到aizoo数据库中的权限信息,只能获取统一身份认证的),@PreAuthorize(同样的问题),自己写了拦截器和自定义注解拦截无果(拦截顺序的问题,无法跳转到统一身份认证)

auth端无法跳转index,无法直接访问任何接口

试图解决统一认证服务器登录之后无法跳转index的bug,尝试了后台控制跳转,报401错误(没有权限

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐