【AI编程】Java程序员如何用Cursor 3小时搞定CAS单点登录前端集成

作者:后端小肥肠

🍇 我写过的文章中的相关代码放到了gitee,地址:xfc-fdw-cloud: 公共解决方案

🍊 有疑问可私信或评论区联系我。

🥑 创作不易未经允许严禁转载。

后端集成CAS单点登录:

【Spring Security系列】10分钟实现 SpringSecurity + CAS 完美单点登录方案_spring-security-cas-CSDN博客

1. 前言

当我在GitHub上看到那个刺眼的Issue------CAS前端集成谁来接?,突然意识到:在云原生和低代码的冲击下,单维度技术栈的生存空间正在急速收缩。作为Java程序员,我曾自豪于Spring生态的精通,却不得不在跨域请求和Cookie存储的迷雾中手足无措。

这种困境想必很多后端开发者都曾遇到:

  • 前端同事请假了,产品经理却要求本周上线
  • 跨域问题排查到凌晨,却发现是前端Cookie配置问题
  • 明明是个小需求,却因为前后端分离变得异常棘手

但这也正是机遇所在:

🔑 用AI工具突破技术边界,一个人就是一个全栈团队

🚀 告别"我 只会后端"的局限 ,拥抱全栈开发的 未来

💡 在技术转型的浪潮中抢占先机,提升个人竞争力

本文将展示如何用Cursor这把技术杠杆

  • 无需系统学习前端技术栈(HTML+CSS+JS、Vue等),轻松完成CAS前端集成
  • 获得"前后端通吃"的全局技术视野
  • 掌握AI辅助编程的实战经验

话不多说,让我们开始这段打破技术边界的旅程...

2. CAS单点登录流程梳理(全栈角度)

CAS单点登录流程一共可以分为三大步骤:

  1. 初始访问流程

当用户首次访问前端应用时(假设url为:http://localhost:8080/onemap),前端会自动发起一个API请求到后端服务。由于用户未登录,这个请求会被 Spring Security 的配置类(SecurityConfig )拦截。接着,认证入口点(AuthenticationEntryPointImpl)会返回401未授权状态码,并在响应头中携带CAS登录地址。前端的 axios 请求拦截器检测到401响应后,会自动将页面重定向到CAS统一认证登录页面,引导用户进行登录。

这就像是一个前台接待员(前端)帮访客(用户)问后台保安(后端)能否进入,保安发现访客没有通行证(未登录),就告诉前台让访客去登记处(CAS)办理通行证。

  1. CAS登录认证流程

当用户在CAS统一认证系统中输入用户名和密码后,CAS服务器会对这些凭证进行验证。验证通过后,CAS服务器会生成一个一次性的服务票据(Service Ticket ,简称ST )。然后,CAS服务器会将用户的浏览器重定向回我们的前端应用系统,同时在URL中附带上这个ST票据(例如:http://localhost:8080/onemap/#/login/cas?ticket=ST-xxx)。

这个过程就像是用户在统一认证中心获得了一张临时通行证,然后被引导回我们的系统入口。

  1. Ticket验证流程

当CAS服务器将用户重定向回前端系统后,前端路由会将请求引导至专门处理CAS登录的组件(CasLogin )。该组件首先从URL中解析出CAS服务器颁发的票据(ticket )。然后,组件会调用后端的验证接口( /login/cas )并携带这个ticket。后端的CAS认证过滤器(CasAuthenticationFilter )会处理这个验证请求,验证ticket的有效性。如果验证通过,后端会创建会话并返回会话标识(JSESSIONID)给前端。最后,前端在确认登录成功后,会自动跳转到系统首页。

这个过程就像是用户拿着临时通行证(ticket)到前台(前端)登记,前台让保安(后端)验证通行证,验证通过后给用户发放正式通行证(JSESSIONID),然后引导用户进入大厅(首页)。

3. AI编程

3.1. AI编程前置工作

在使用AI进行编程之前,我们需要做好充分的准备工作。这个过程可以分为三个关键步骤:

  1. 需求分析与技术储备
  • 深入理解系统功能和业务流程

  • 掌握相关技术栈的基础知识

  • 明确项目的技术边界和实现目标

  1. 前期流程梳理
  • 详细梳理技术流程,以本文为例,需要在前期梳理CAS单点登录认证流程

  • 设计数据流转和状态管理方案

  1. 技术基础要求

虽然我们使用AI来协助开发,但仍需要了解相关基础知识(注意这里只是了解,不是让你花费几个月去拼命学),以本文为例,我们需要了解:

  • 前端基础:HTML、CSS、JavaScript

  • Vue.js基础概念:组件、生命周期、路由

  • 开发环境:Node.js、NPM包管理

  • 网络知识:HTTP协议、Cookie机制

需要强调的是,AI编程不是技术许愿池 ,而是一个强大的协作工具。它需要开发者具备足够的技术认知来进行需求分析、方案评估和问题排查。在本项目中,虽然我们使用AI实现了基于Vue2的CAS单点登录前端集成,但如果没有前端基础知识的支撑,在调试和问题排查阶段将会举步维艰。 (只是我个人实践观点,你不要用网上那些非技术人员一天用Cursor开发了一个App还上线的例子来杠我,杠就是你对)

3.2. Cursor开发实战

  1. 说出你的需求,你想实现什么,让他给出方案(大概率是偏离的),比如我的需求就是基于后端已有代码,采用Vue2来进行CAS单点登录集成。
  2. 把它给出的方案流程在你自己脑子里过一遍,不行的话需要修订:

AI会根据你提供的思路再给一版方案,我这里提示词没控制好,它直接开始写了,大家写的时候注意控制一下,方案没问题再开始写:

  1. 验证AI写的代码,进入前端目录(AI生成代码的目录),运行npm install安装依赖,之后运行npm run serve,先把代码跑起来看看:

我们再把后台启动一下,访问前端url的时候直接跳转到了CAS登录界面:

输入用户名和密码后,跳转到了首页,接口数据拿到了:

到此,单点登录集成完成了。(其实很多调试步骤没有被列出来,流程梳理也很费时间,这里大家自己实践就知道了)

4. 核心代码

4.1. 后端核心代码

虽然之前的文章(blog.csdn.net/c1821359022...)已经包含详尽的后端代码,但对接到前端还需要改一下,具体修改如下:

  1. 后端认证入口点(这里需要改一下,之前是直接重定向到CAS认证界面了,现在要返回401,由前端来跳转到CAS认证界面)
java 复制代码
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
    
    @Value("${cas.server}")
    private String casServerUrl;
    
    @Value("${cas.client}")
    private String casClientUrl;

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                        AuthenticationException authException) throws IOException {
        // 构建CAS登录URL,带上service参数
        String serviceUrl = casClientUrl + "/#/login/cas";
        String casLoginUrl = casServerUrl + "/login?service=" + URLEncoder.encode(serviceUrl, "UTF-8");
        
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setHeader("Location", casLoginUrl);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write("{"message":"未登录或登录已过期"}");
    }
}
  1. 修改SecurityConfig配置
  • 配置自定义authenticationEntryPoint(AuthenticationEntryPointImpl)
java 复制代码
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
    .httpBasic().disable()
    .csrf().disable()
    .formLogin().disable()
    .logout().disable()
    .authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests
                           .antMatchers("/login/cas", "/logout/cas").permitAll()
                           .antMatchers("/error").permitAll()
                           .antMatchers("/swagger-ui.html").permitAll()
                           .antMatchers("/swagger-resources/**").permitAll()
                           .antMatchers("/v2/api-docs").permitAll()
                           .antMatchers("/webjars/**").permitAll()
                           .antMatchers("/doc.html").permitAll()
                           .anyRequest().authenticated())
    .exceptionHandling()
    .authenticationEntryPoint(authenticationEntryPoint)
    .and()
    .addFilter(casAuthenticationFilter())
    .addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class)
    .addFilterBefore(casLogoutFilter(), LogoutFilter.class);

    return http.build();
}
  • 修改ServiceProperties配置
java 复制代码
@Bean
    public ServiceProperties serviceProperties() {
        ServiceProperties serviceProperties = new ServiceProperties();
        serviceProperties.setService("http://localhost:8080/onemap/#/login/cas");
        serviceProperties.setAuthenticateAllArtifacts(true);
        return serviceProperties;
    }

setService()设置的URL就是CAS服务器回调的地址,会带上ticket参数,我们需要将其改为前端地址(我的前端地址为http://localhost:8080/onemap)。

  • 修改CasAuthenticationFilter
java 复制代码
@Bean
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
    CasAuthenticationFilter filter = new CasAuthenticationFilter();
    
    // 1. 设置认证管理器
    filter.setAuthenticationManager(authenticationManager());
    
    // 2. 设置处理ticket验证的URL路径
    filter.setFilterProcessesUrl("/login/cas");
    
    // 3. 设置service配置
    filter.setServiceProperties(serviceProperties());
    
    // 4. 认证成功处理器
    filter.setAuthenticationSuccessHandler((request, response, authentication) -> {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().write("{"status":"200","message":"登录成功"}");
    });

    // 5. 认证失败处理器
    filter.setAuthenticationFailureHandler((request, response, exception) -> {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setHeader("Location", casServerUrl + "/login");
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write("{"message":"认证失败"}");
    });

    return filter;
}

CAS认证过滤器(CasAuthenticationFilter ),用于处理CAS服务器回调时的ticket 验证。它设置了认证管理器来处理认证逻辑,指定/login/cas作为处理ticket验证的URL路径,并注入service配置来指定CAS回调地址。同时配置了两个关键的处理器:认证成功时返回200状态码和成功消息,并自动设置JSESSIONID;认证失败时返回401状态码,并在响应头中设置CAS登录地址以便前端重新发起登录。

4.2. 前端核心代码

  1. 前端拦截请求器
js 复制代码
// utils/request.js
service.interceptors.response.use(
  response => response,
  error => {
    if (error.response?.status === 401) {
      window.location.href = error.response.headers.location;
      return;
    }
    Message.error(error.message);
    return Promise.reject(error);
  }
)

这段代码是前端的axios响应拦截器配置,主要用于统一处理后端接口响应。当接口请求成功时直接返回响应数据;当请求失败时,会检查是否是401未授权错误(表示用户未登录),如果是401则从响应头中获取CAS登录地址并进行页面跳转,否则显示错误消息并将Promise 设为rejected状态。

  1. 前端CAS回调处理
js 复制代码
// views/login/CasLogin.vue
export default {
  methods: {
    getTicketFromUrl() {
      const url = window.location.href;
      const hashIndex = url.indexOf('#');
      const queryString = hashIndex > -1 ? url.substring(0, hashIndex) : url;
      const urlParams = new URLSearchParams(queryString.split('?')[1]);
      return urlParams.get('ticket');
    },
    async handleLogin() {
      try {
        const ticket = this.getTicketFromUrl();
        const response = await validateTicket(ticket);
        if (response.status === 200) {
          this.$router.push('/');
        }
      } catch (error) {
        this.error = error.message;
      }
    }
  }
}

这段代码是CAS登录回调处理组件的核心方法,主要完成两个任务:getTicketFromUrl 方法负责从URL中解析CAS服务器回调时携带的ticket参数(处理类似http://localhost:8080/onemap/#/login/cas?ticket=ST-xxx 这样的URL);handleLogin方法则负责调用后端接口验证这个ticket的有效性,如果验证成功(返回200状态码)就跳转到系统首页,验证失败则显示错误信息。

5. 源码获取

关注gzh后端小肥肠,点击底部【资源】菜单就能获取前端源码,后端源码已经很详尽,不再提供。

6. 结语

这次CAS集成的实战,远不止实现一个功能这么简单。它证明了:在AI工具的加持下,后端程序员完全能驾驭前端关键模块

🎯 技术成长启示

1️⃣ AI不是万能的,但懂AI的程序员是万能的

2️⃣ 技术边界正在消失,全栈思维是必备技能

3️⃣学会用AI工具,让你的能力突破天际

📚你的下一步行动:

1️⃣ 立即下载源码

2️⃣ 参考往期《【Spring Security系列】10分钟实现 SpringSecurity + CAS 完美单点登录方案》,构建高可用认证体系

3️⃣ 安装Cursor,用我的方法尝试一下AI编程(你会回来谢我)

如果本文对你有帮助,请动动你发财的小手点点关注,小肥肠将持续分享更多AI干货文章~

相关推荐
用户6000718191025 分钟前
【翻译】简化 TSRX
前端
luckdewei30 分钟前
那个用 passlib 做认证的新同事,上线第一天就把用户密码写进了日志
后端
IT乐手1 小时前
佛德角逼平西班牙,国足还有啥借口?
前端
ping某2 小时前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
JustHappy2 小时前
我汇总了身边朋友的经历才发现,其实第一份实习是最难找的......
前端·后端·面试
uhakadotcom2 小时前
在python 的 工程化架构中 ,什么是 薄包装器层?
后端·面试·github
星栈2 小时前
Dioxus 的响应式系统:`Signal`、`Memo`、`Effect` 和异步状态到底该怎么分工
前端·前端框架
yingyima2 小时前
Java 正则表达式:比你想象的更强大
前端
yuanyxh5 小时前
macOS 应用 - 纯对话生成
前端·macos·ai编程
大家的林语冰5 小时前
ES5 凉凉,Babel 8 正式发布,默认不再编译为 ES5 和 CJS......
前端·javascript·前端工程化