SpringBoot+CAS整合服务端和客户端实现SSO单点登录与登出快速入门上手

一、教学讲解视频

教学讲解视频地址:视频地址

二、前言

因为CAS支持HTTP请求访问,而我们是快速入门上手视频,所以这期教程就不教大家如何配置HTTPS了,如果需要使用HTTPS,可以参考其他博客去云服务器申请证书或者使用JDK自行生成一个证书。

三、准备工作

下载CAS Server(直接下载压缩包就可以)
这里我们用的是5.3版本的服务端,5.3之前的服务端都是maven项目,大于5.3的服务端就是gradle项目

下载链接

在这里插入图片描述

四、CAS Server服务端搭建

1.解压我们前面下载好的压缩包。
2.然后进入解压好的目录,打开cmd窗口,输入命令:bulid.cmd run
在这里插入图片描述
看到BUILD SUCCESS就可以关掉这个cmd窗口了。

3.接下来用我们idea打开这个解压好的目录,拉取maven依赖
因为我们5.3版本是maven项目,因此先让他去下载依赖,耐心等待依赖加载完成~

4.拉取完依赖后,创建对应java目录和resources目录
在这里插入图片描述

5.在resources目录中,我们把target目录下的services文件夹和application.properties文件拷贝到我们的resources目录下
在这里插入图片描述

6.打开HTTPSandIMAPS-10000001这个文件,在里面加上http,让他支持http请求访问
在这里插入图片描述

7.然后打开我们application.properties文件,把这三行注释掉,这是给配置证书情况下使用的,也就是要给配置https使用的。我们这里暂时不用
在这里插入图片描述
8.接下来我们需要在我们的pom.xml文件中加上支持数据库链接的依赖
因为我们不需要用他的默认账号和密码,我们要用我自己数据库中的数据登录
在这里插入图片描述
注意这里MySQL驱动包的版本要和自己MySQL版本对应上

<dependency>
    <groupId>org.apereo.cas</groupId>
    <artifactId>cas-server-support-jdbc</artifactId>
    <version>${cas.version}</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.21</version>
</dependency>

这里我们要检查下这个jar包有没有下载下来,判断依据如下图
在这里插入图片描述
如果没下载下来的话,点下面链接下载这个jar包
jar包下载链接
点击下载
在这里插入图片描述
然后把这个jar包放到本地仓库的对应目录下
在这里插入图片描述
9.然后我们还需要在application.properties文件中加上一些配置,具体说明看下图
在这里插入图片描述

#允许http
cas.tgc.secure=false
cas.serviceRegistry.initFromJson=true
#查询账号密码sql,必须包含密码字段
cas.authn.jdbc.query[0].sql=select * from user where username = ?
#指定上面的sql查询字段名(必须)
cas.authn.jdbc.query[0].fieldPassword=password
#指定过期字段,1为过期,若过期需要修改密码
cas.authn.jdbc.query[0].fieldExpired=expired
#为不可用字段段,1为不可用,
cas.authn.jdbc.query[0].fieldDisabled=disabled
#数据库方言hibernate的知识
cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect
#数据库驱动
cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
#数据库连接
cas.authn.jdbc.query[0].url=jdbc:mysql://localhost:3306/db_user2?useUnicode=true&characterEncoding=UTF-8
#数据库用户名
cas.authn.jdbc.query[0].user=root
#数据库密码
cas.authn.jdbc.query[0].password=
#默认加密策略,通过encodingAlgorithm来指定算法,默认NONE不加密
cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT
cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5

注意下,这里我们配置文件中写了对密码进行MD5加密,因此我们数据库中存储的密码必须是MD5加密过的,不然的话登录不进去
在这里插入图片描述

可以这样去获取对应明文密码的MD5加密密码,然后存回数据库中的password字段中
在这里插入图片描述

10.然后我们idea中配置Tomcat,就可以启动项目访问我们的服务端了
在这里插入图片描述
这时候,我们就可以用我们数据库中的账号和密码进行登录了
在这里插入图片描述
在这里插入图片描述

五、CAS Client客户端搭建

1.先用我们的idea创建一个SpringBoot项目,然后在pom.xml文件中,引入对应的依赖,这边我直接贴上我客户端pom.xml里面的代码

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.5.RELEASE</version><!--2.3.3.RELEASE-->
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <groupId>com.yjq.programmer</groupId>
  <artifactId>business</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>business</name>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <!-- 整合web开发依赖 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 引入mysql连接依赖 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
      <scope>runtime</scope>
    </dependency>

    <!--引入阿里巴巴druid连接池-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.19</version>
    </dependency>

    <dependency>
      <groupId>net.unicon.cas</groupId>
      <artifactId>cas-client-autoconfig-support</artifactId>
      <version>2.3.0-GA</version>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>

        <plugin>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>


      </plugins>
    </pluginManagement>
  </build>

</project>

2.然后我们要在这里加上对应配置文件代码,主要就是指明server端的地址以及当前客户端的地址
在这里插入图片描述

server.port=8089

#cas服务端的地址
cas.server-url-prefix=http://localhost:8081/cas
#cas服务端的登录地址
cas.server-login-url=http://localhost:8081/cas/login
#客户端访问地址
cas.client-host-url=http://localhost:8089
#验证的协议
cas.validation-type=CAS3

3.然后在我们的启动类上要加上这个@EnableCasClient注解
在这里插入图片描述
4.接下来就是对CAS过滤器进行配置
首先是配置CASUtil.java文件,这个主要用来获取当前登录用户信息

package com.yjq.programmer.util;

import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.validation.Assertion;

import javax.servlet.http.HttpServletRequest;

/**
 * @author 杨杨吖
 * @QQ 823208782
 * @WX yjqi12345678
 * @create 2023-03-04 9:25
 */
public class CASUtil {

    public static String getLoginNameFromCas(HttpServletRequest request) {
        Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
        if(assertion!= null) {
            AttributePrincipal principal = assertion.getPrincipal();
            return principal.getName();
        } else {
            return null;
        }
    }
}

然后是LoginUserInfoFilter.java文件的配置,这里主要配置自定义的登录用户信息拦截器

package com.yjq.programmer.filter;

import com.alibaba.druid.util.StringUtils;
import com.yjq.programmer.util.CASUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
 * @author 杨杨吖
 * @QQ 823208782
 * @WX yjqi12345678
 * @create 2023-03-04 9:26
 */
public class LoginUserInfoFilter implements Filter {

    Logger logger =  LoggerFactory.getLogger(LoginUserInfoFilter.class);

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request_ = (HttpServletRequest)request;
        String loginName = CASUtil.getLoginNameFromCas(request_);
        if(!StringUtils.isEmpty(loginName)){
            logger.info("访问者 :" +loginName);
            request_.getSession().setAttribute("loginName", loginName);
        }

        chain.doFilter(request, response);
    }
}

最后就是配置我们的CAS过滤器CASFilterConfig.java文件了

package com.yjq.programmer.config;

import com.yjq.programmer.filter.LoginUserInfoFilter;
import org.jasig.cas.client.authentication.AuthenticationFilter;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.jasig.cas.client.util.HttpServletRequestWrapperFilter;
import org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;

/**
 * @author 杨杨吖
 * @QQ 823208782
 * @WX yjqi12345678
 * @create 2023-03-04 9:00
 */
@Configuration
public class CASFilterConfig {

    @Value("${cas.server-url-prefix}")
    private String CAS_URL;
    @Value("${cas.client-host-url}")
    private String APP_URL;

    /**
     * 配置监听器
     * @return
     */
    @Bean
    public ServletListenerRegistrationBean servletListenerRegistrationBean(){
        ServletListenerRegistrationBean  listenerRegistrationBean = new ServletListenerRegistrationBean();
        listenerRegistrationBean.setListener(new SingleSignOutHttpSessionListener());
        listenerRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return listenerRegistrationBean;
    }

    /**
     * 单点登录退出
     * @return
     */
    @Bean
    public FilterRegistrationBean singleSignOutFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new SingleSignOutFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.addInitParameter("casServerUrlPrefix", CAS_URL );
        registrationBean.setName("CAS Single Sign Out Filter");
        registrationBean.setOrder(2);
        return registrationBean;
    }

    /**
     * 单点登录认证
     * @return
     */
    @Bean
    public FilterRegistrationBean AuthenticationFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new AuthenticationFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setName("CAS Filter");
        registrationBean.addInitParameter("casServerLoginUrl",CAS_URL);
        registrationBean.addInitParameter("serverName", APP_URL );
        registrationBean.setOrder(3);
        return registrationBean;
    }

    /**
     * 单点登录校验
     * @return
     */
    @Bean
    public FilterRegistrationBean cas30ProxyReceivingTicketValidationFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new Cas30ProxyReceivingTicketValidationFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setName("CAS Validation Filter");
        registrationBean.addInitParameter("casServerUrlPrefix", CAS_URL );
        registrationBean.addInitParameter("serverName", APP_URL );
        registrationBean.setOrder(4);
        return registrationBean;
    }

    /**
     * 单点登录请求包装
     * @return
     */
    @Bean
    public FilterRegistrationBean httpServletRequestWrapperFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new HttpServletRequestWrapperFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setName("CAS HttpServletRequest Wrapper Filter");
        registrationBean.setOrder(5);
        return registrationBean;
    }

    /**
     * 获取当前登录用户信息
     * @return
     */
    @Bean
    public FilterRegistrationBean getLoginUserInfoFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new LoginUserInfoFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setName("loginUserInfoFilter");
        registrationBean.setOrder(6);
        return registrationBean;
    }
}

5.然后就是写我们的测试文件,来测试下我们单点登录和登出了
TestController.java文件的代码

package com.yjq.programmer.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;

/**
 * @author 杨杨吖
 * @QQ 823208782
 * @WX yjqi12345678
 * @create 2023-03-02 20:19
 */
@Controller
public class TestController {

    @GetMapping("/hello")
    @ResponseBody
    public String hello() {
        return "word";
    }

    //登出
    @RequestMapping("/logout")
    public String logout(HttpSession session){
        session.invalidate();
        return "redirect:http://localhost:8081/cas/logout";
    }
}

运行我们客户端的SpringBoot的项目,当我们输入http://localhost:8089/hello时候,它会自动跳到我们服务端的登录界面

当我们输入完账号密码登录后,再输入http://localhost:8089/hello时候就能正常访问内容了
在这里插入图片描述
当我们输入http://localhost:8089/logout时候,可以发现能正常退出,再输入http://localhost:8089/hello时候需要重新登录了
在这里插入图片描述

六、结尾

完整的配套代码资料获取请关注公众号:杨杨吖知识库,回复关键词:配套代码资料

以上就是SpringBoot+CAS整合服务端和客户端实现SSO单点登录与登出快速入门上手的所有步骤啦,感谢大家浏览我的博客~

  • 23
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
单点登录(Single Sign-On,简称SSO)是一种身份验证技术,可以让用户只需一次登录,就可以访问多个应用程序。在实际开发中,我们可以使用Spring Boot、JWT和Redis来实现单点登录功能。 下面是实现单点登录的步骤: 1. 创建Spring Boot项目并引入所需依赖:spring-boot-starter-web、spring-boot-starter-data-redis和jjwt。 2. 创建一个User实体类,包含用户名和密码等信息。 3. 创建一个UserService,实现对用户信息的操作,包括注册、登录等。 4. 引入JWT依赖后,我们需要创建一个JWTUtil类,实现token的生成和解析。 5. 创建一个LoginController,用于处理用户的登录请求。在登录成功后,生成token并将其存储到Redis中。 6. 创建一个AuthController,用于验证用户的token是否有效。在验证成功后,可以获取用户信息并返回。 7. 在需要进行单点登录验证的应用程序中,只需要在请求中携带token,并调用AuthController进行验证即可。 具体实现细节可以参考以下代码示例: User实体类: ```java public class User { private String username; private String password; // 省略setter和getter方法 } ``` UserService接口: ```java public interface UserService { void register(User user); String login(String username, String password); } ``` UserService实现类: ```java @Service public class UserServiceImpl implements UserService { @Autowired private RedisTemplate<String, String> redisTemplate; @Override public void register(User user) { // 省略用户注册逻辑 } @Override public String login(String username, String password) { // 省略用户登录逻辑 // 登录成功后生成token并存储到Redis中 String token = JWTUtil.generateToken(username); redisTemplate.opsForValue().set(username, token, 30, TimeUnit.MINUTES); return token; } } ``` JWTUtil类: ```java public class JWTUtil { private static final String SECRET_KEY = "my_secret_key"; private static final long EXPIRATION_TIME = 3600000; public static String generateToken(String username) { return Jwts.builder() .setSubject(username) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } public static String getUsernameFromToken(String token) { return Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody() .getSubject(); } } ``` LoginController: ```java @RestController public class LoginController { @Autowired private UserService userService; @PostMapping("/login") public ResponseEntity<String> login(@RequestBody User user) { String token = userService.login(user.getUsername(), user.getPassword()); return ResponseEntity.ok(token); } } ``` AuthController: ```java @RestController public class AuthController { @Autowired private RedisTemplate<String, String> redisTemplate; @GetMapping("/auth") public ResponseEntity<User> auth(@RequestHeader("Authorization") String token) { String username = JWTUtil.getUsernameFromToken(token); if (StringUtils.isEmpty(username)) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } String redisToken = redisTemplate.opsForValue().get(username); if (!token.equals(redisToken)) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } User user = new User(); user.setUsername(username); return ResponseEntity.ok(user); } } ``` 在请求中携带token的示例: ```java @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); restTemplate.setInterceptors(Collections.singletonList((request, body, execution) -> { String token = // 从Redis中获取token request.getHeaders().add("Authorization", token); return execution.execute(request, body); })); return restTemplate; } } ``` 以上就是使用Spring Boot、JWT和Redis实现单点登录的步骤和示例代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这里是杨杨吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值