单点登录(SSO)的实现与应用

在现代企业级应用开发中,用户通常需要访问多个不同的系统和应用。为了提高用户体验和安全性,单点登录(Single Sign-On,SSO)技术应运而生。单点登录允许用户在一次登录后,无需再次输入用户名和密码即可访问多个相关的系统和应用。本文将深入探讨 Java 单点登录的实现原理、技术选型以及实际应用案例。

一、引言

随着企业信息化的不断发展,企业内部的应用系统越来越多。用户在使用这些系统时,需要分别登录每个系统,这不仅繁琐,而且容易出现密码管理混乱、安全性低等问题。单点登录技术可以有效地解决这些问题,提高用户体验和系统的安全性。

二、单点登录的概念与原理

(一)单点登录的定义

单点登录是一种用户认证和授权机制,它允许用户在一次登录后,无需再次输入用户名和密码即可访问多个相关的系统和应用。单点登录系统通常由一个认证中心和多个应用系统组成。用户在认证中心进行登录,认证中心验证用户的身份后,颁发一个令牌(token)给用户。用户在访问其他应用系统时,将令牌传递给应用系统,应用系统通过与认证中心进行通信,验证令牌的有效性,从而确定用户的身份。

(二)单点登录的原理

  1. 用户访问应用系统
    • 用户在浏览器中输入应用系统的 URL,发起访问请求。
  2. 应用系统重定向到认证中心
    • 应用系统发现用户未登录,将用户重定向到认证中心的登录页面。
  3. 用户在认证中心登录
    • 用户在认证中心的登录页面输入用户名和密码,提交登录请求。
  4. 认证中心验证用户身份
    • 认证中心接收到用户的登录请求后,验证用户的身份。如果用户身份验证通过,认证中心颁发一个令牌给用户,并将用户重定向回应用系统。
  5. 应用系统验证令牌
    • 应用系统接收到用户的请求后,从请求中获取令牌。应用系统通过与认证中心进行通信,验证令牌的有效性。如果令牌有效,应用系统确定用户的身份,并为用户提供服务。
  6. 用户访问其他应用系统
    • 用户在访问其他应用系统时,无需再次输入用户名和密码。其他应用系统通过读取用户的令牌,与认证中心进行通信,验证令牌的有效性,从而确定用户的身份。

三、Java 单点登录的技术选型

(一)常见的单点登录技术

  1. CAS(Central Authentication Service)
    • CAS 是一个开源的单点登录框架,它由耶鲁大学开发。CAS 支持多种认证方式,如用户名 / 密码、数字证书、LDAP 等。CAS 具有高可用性、可扩展性和安全性等优点,被广泛应用于企业级应用开发中。
  2. SAML(Security Assertion Markup Language)
    • SAML 是一种基于 XML 的开放标准,用于在不同的安全域之间交换认证和授权信息。SAML 支持多种认证方式,如用户名 / 密码、数字证书、OAuth 等。SAML 具有跨平台、跨语言和安全性高等优点,被广泛应用于企业级应用开发中。
  3. OAuth(Open Authorization)
    • OAuth 是一种开放标准,用于授权第三方应用访问用户在某个服务提供商上的资源。OAuth 支持多种认证方式,如用户名 / 密码、数字证书、OAuth 2.0 等。OAuth 具有简单、安全和可扩展性等优点,被广泛应用于互联网应用开发中。

(二)Java 单点登录技术的选择

  1. 考虑因素
    • 应用场景:不同的单点登录技术适用于不同的应用场景。例如,CAS 适用于企业内部的应用系统,SAML 适用于跨企业的应用系统,OAuth 适用于互联网应用系统。
    • 技术要求:不同的单点登录技术具有不同的技术要求。例如,CAS 需要部署一个独立的认证中心,SAML 需要支持 XML 和数字签名等技术,OAuth 需要支持 HTTP 和 JSON 等技术。
    • 开发成本:不同的单点登录技术具有不同的开发成本。例如,CAS 是一个开源的框架,开发成本较低;SAML 需要支持 XML 和数字签名等技术,开发成本较高;OAuth 需要支持 HTTP 和 JSON 等技术,开发成本适中。
  2. 技术推荐
    • 对于企业内部的应用系统,推荐使用 CAS 框架。CAS 框架具有高可用性、可扩展性和安全性等优点,并且开发成本较低。
    • 对于跨企业的应用系统,推荐使用 SAML 标准。SAML 标准具有跨平台、跨语言和安全性高等优点,并且被广泛应用于企业级应用开发中。
    • 对于互联网应用系统,推荐使用 OAuth 2.0 标准。OAuth 2.0 标准具有简单、安全和可扩展性等优点,并且被广泛应用于互联网应用开发中。

四、Java 单点登录的实现步骤

(一)搭建认证中心

  1. 选择认证中心框架
    • 根据技术选型的结果,选择一个合适的认证中心框架。如果选择 CAS 框架,可以下载 CAS 服务器的安装包,并进行安装和配置。
  2. 配置认证中心
    • 配置认证中心的数据库、认证方式、用户管理等功能。如果选择 CAS 框架,可以使用默认的数据库配置,也可以使用其他数据库,如 MySQL、Oracle 等。
  3. 启动认证中心
    • 启动认证中心服务器,确保认证中心能够正常运行。如果选择 CAS 框架,可以使用命令行或者图形界面启动 CAS 服务器。

(二)集成应用系统

  1. 添加认证中心依赖
    • 在应用系统的项目中,添加认证中心的依赖库。如果选择 CAS 框架,可以添加 CAS 客户端的依赖库。
  2. 配置应用系统
    • 配置应用系统的认证方式、令牌验证等功能。如果选择 CAS 框架,可以在应用系统的配置文件中添加 CAS 客户端的配置信息。
  3. 实现令牌验证
    • 在应用系统中,实现令牌验证的功能。如果选择 CAS 框架,可以使用 CAS 客户端提供的 API 来验证令牌的有效性。

(三)测试单点登录

  1. 模拟用户登录
    • 在浏览器中输入认证中心的 URL,进行用户登录。如果登录成功,认证中心会颁发一个令牌给用户,并将用户重定向回应用系统。
  2. 访问应用系统
    • 在浏览器中输入应用系统的 URL,应用系统会从请求中获取令牌,并与认证中心进行通信,验证令牌的有效性。如果令牌有效,应用系统会确定用户的身份,并为用户提供服务。
  3. 访问其他应用系统
    • 在浏览器中输入其他应用系统的 URL,其他应用系统会从请求中获取令牌,并与认证中心进行通信,验证令牌的有效性。如果令牌有效,其他应用系统会确定用户的身份,并为用户提供服务。

五、Java 单点登录的示例代码

(一)使用 CAS 框架实现单点登录

  1. 搭建 CAS 服务器
    • 下载 CAS 服务器的安装包,可以从官方网站(CAS Server Documentation Home Page)下载最新版本的 CAS 服务器。
    • 解压安装包,进入安装目录,执行以下命令启动 CAS 服务器:

./bin/startup.sh

  • 打开浏览器,输入http://localhost:8443/cas/login,如果能够看到 CAS 的登录页面,说明 CAS 服务器已经成功启动。

  1. 集成 CAS 客户端到应用系统
    • 在应用系统的项目中,添加 CAS 客户端的依赖库。可以在 Maven 项目的pom.xml文件中添加以下依赖:

<dependency>
    <groupId>org.jasig.cas.client</groupId>
    <artifactId>cas-client-core</artifactId>
    <version>3.5.2</version>
</dependency>

  • 在应用系统的配置文件中,添加 CAS 客户端的配置信息。以下是一个 Spring Boot 项目的application.properties文件中的配置示例:

cas.server-url-prefix=https://localhost:8443/cas
cas.server-login-url=https://localhost:8443/cas/login
cas.client-host-url=http://localhost:8080

  • 在应用系统的代码中,添加 CAS 客户端的过滤器,用于拦截用户的请求,并将用户重定向到 CAS 服务器进行登录。以下是一个 Spring Boot 项目的WebSecurityConfig类中的配置示例:

import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
               .authorizeRequests()
               .antMatchers("/login", "/logout").permitAll()
               .anyRequest().authenticated()
               .and()
               .addFilter(casAuthenticationFilter())
               .addFilterBefore(logoutFilter(), CasAuthenticationFilter.class)
               .addFilterBefore(singleSignOutFilter(), LogoutFilter.class);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(casAuthenticationProvider());
    }

    @Bean
    public CasAuthenticationProvider casAuthenticationProvider() {
        CasAuthenticationProvider provider = new CasAuthenticationProvider();
        provider.setAuthenticationUserDetailsService(userDetailsService);
        provider.setServiceProperties(serviceProperties());
        provider.setTicketValidator(cas20ProxyTicketValidator());
        provider.setKey("casAuthenticationProviderKey");
        return provider;
    }

    @Bean
    public Cas20ProxyTicketValidator cas20ProxyTicketValidator() {
        return new Cas20ProxyTicketValidator("https://localhost:8443/cas");
    }

    @Bean
    public ServiceProperties serviceProperties() {
        ServiceProperties properties = new ServiceProperties();
        properties.setService("http://localhost:8080/login/cas");
        properties.setAuthenticateAllArtifacts(true);
        return properties;
    }

    @Bean
    public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
        CasAuthenticationFilter filter = new CasAuthenticationFilter();
        filter.setAuthenticationManager(authenticationManager());
        return filter;
    }

    @Bean
    public LogoutFilter logoutFilter() {
        LogoutFilter logoutFilter = new LogoutFilter("https://localhost:8443/cas/logout", new SecurityContextLogoutHandler());
        logoutFilter.setFilterProcessesUrl("/logout/cas");
        return logoutFilter;
    }

    @Bean
    public SingleSignOutFilter singleSignOutFilter() {
        return new SingleSignOutFilter();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return new ProviderManager(casAuthenticationProvider());
    }
}

  1. 测试单点登录
    • 在浏览器中输入应用系统的 URL,应用系统会自动重定向到 CAS 服务器的登录页面。输入用户名和密码进行登录,如果登录成功,CAS 服务器会颁发一个令牌给用户,并将用户重定向回应用系统。应用系统会从请求中获取令牌,并与 CAS 服务器进行通信,验证令牌的有效性。如果令牌有效,应用系统会确定用户的身份,并为用户提供服务。

(二)使用 SAML 标准实现单点登录

  1. 搭建 SAML 身份提供商(IdP)
    • 下载一个 SAML 身份提供商的软件,如 Shibboleth、OpenAM 等。
    • 安装和配置 SAML 身份提供商,包括设置用户数据库、认证方式、属性映射等功能。
    • 启动 SAML 身份提供商服务器,确保身份提供商能够正常运行。
  2. 集成 SAML 服务提供商(SP)到应用系统
    • 在应用系统的项目中,添加 SAML 服务提供商的依赖库。可以使用开源的 SAML 库,如 Spring SAML、OpenSAML 等。
    • 配置应用系统的 SAML 服务提供商,包括设置身份提供商的 URL、证书、属性映射等功能。
    • 在应用系统的代码中,实现 SAML 身份验证的逻辑,包括处理 SAML 响应、验证签名、提取用户信息等功能。
  3. 测试单点登录
    • 在浏览器中输入应用系统的 URL,应用系统会自动重定向到 SAML 身份提供商的登录页面。输入用户名和密码进行登录,如果登录成功,身份提供商会颁发一个 SAML 响应给用户,并将用户重定向回应用系统。应用系统会从请求中获取 SAML 响应,并与身份提供商进行通信,验证 SAML 响应的有效性。如果 SAML 响应有效,应用系统会确定用户的身份,并为用户提供服务。

六、Java 单点登录的应用场景

(一)企业内部应用系统集成

  1. 企业内部通常有多个不同的应用系统,如办公自动化系统、人力资源管理系统、财务管理系统等。用户在使用这些系统时,需要分别登录每个系统,这不仅繁琐,而且容易出现密码管理混乱、安全性低等问题。通过使用单点登录技术,可以实现用户在一次登录后,无需再次输入用户名和密码即可访问多个相关的应用系统。
  2. 例如,一个企业内部有一个办公自动化系统和一个人力资源管理系统。用户在办公自动化系统中登录后,可以直接访问人力资源管理系统,无需再次输入用户名和密码。这样可以提高用户体验,减少密码管理的工作量,提高系统的安全性。

(二)跨企业应用系统集成

  1. 在企业之间的合作中,通常需要集成多个不同的应用系统,如供应链管理系统、客户关系管理系统等。通过使用单点登录技术,可以实现用户在一次登录后,无需再次输入用户名和密码即可访问多个相关的跨企业应用系统。
  2. 例如,一个企业和它的供应商之间需要集成供应链管理系统。用户在企业的内部系统中登录后,可以直接访问供应商的供应链管理系统,无需再次输入用户名和密码。这样可以提高合作效率,减少密码管理的工作量,提高系统的安全性。

(三)互联网应用系统集成

  1. 在互联网应用中,用户通常需要访问多个不同的网站和应用。通过使用单点登录技术,可以实现用户在一次登录后,无需再次输入用户名和密码即可访问多个相关的互联网应用系统。
  2. 例如,一个用户在一个社交网站上登录后,可以直接访问其他相关的互联网应用系统,如在线购物网站、在线支付系统等。这样可以提高用户体验,减少密码管理的工作量,提高系统的安全性。

七、Java 单点登录的优势与挑战

(一)优势

  1. 提高用户体验
    • 用户只需在一个地方登录,即可访问多个相关的系统和应用,无需重复输入用户名和密码,提高了用户的使用便利性。
  2. 简化密码管理
    • 用户只需记住一个用户名和密码,即可访问多个系统和应用,减少了密码管理的工作量,降低了密码遗忘和泄露的风险。
  3. 提高系统安全性
    • 单点登录系统通常采用更加严格的认证和授权机制,如多因素认证、数字证书等,提高了系统的安全性。
  4. 便于系统集成
    • 单点登录系统可以方便地与其他系统和应用进行集成,实现用户的统一认证和授权,提高了系统的集成性和可扩展性。

(二)挑战

  1. 技术复杂性
    • 单点登录系统涉及到多个技术领域,如认证、授权、加密、安全协议等,技术复杂性较高,需要专业的技术人员进行设计和开发。
  2. 安全性风险
    • 单点登录系统一旦被攻击,可能会导致多个系统和应用的用户信息泄露,安全性风险较高。因此,需要采取更加严格的安全措施,如加密通信、数字签名、多因素认证等,确保系统的安全性。
  3. 用户管理复杂性
    • 单点登录系统需要对多个系统和应用的用户进行统一管理,用户管理复杂性较高。需要建立一个统一的用户数据库,实现用户的创建、修改、删除、授权等功能,确保用户信息的一致性和准确性。

八、结论

Java 单点登录技术是一种非常重要的用户认证和授权机制,它可以有效地提高用户体验、简化密码管理、提高系统安全性和便于系统集成。在实际应用中,我们可以根据不同的应用场景选择合适的单点登录技术,并进行合理的设计和开发。同时,我们也需要注意单点登录系统的安全性风险和用户管理复杂性,采取相应的安全措施和管理策略,确保系统的稳定运行和用户信息的安全。希望本文对大家了解和应用 Java 单点登录技术有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/900866.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Pyramidal Flow使用指南:快手、北大、北邮,开源可免费商用视频生成模型,快速上手教程

什么是 Pyramidal Flow&#xff1f; Pyramidal Flow 是由快手科技、北京大学和北京邮电大学联合推出的开源视频生成模型&#xff0c;它是完全开源的&#xff0c;发布在 MIT 许可证下&#xff0c;允许商业使用、修改和再分发。该模型能够通过文本描述生成最高10秒、分辨率为128…

铜业机器人剥片 - SNK施努卡

SNK施努卡有色行业电解车间铜业机器人剥片 铜业机器人剥片技术是针对传统人工剥片效率低下、工作环境恶劣及生产质量不稳定的痛点而发展起来的自动化解决方案。 面临人工剥片的诸多挑战&#xff0c;包括低效率、工作环境差、人员流动大以及产品质量控制不精确等问题。 人工剥片…

Idea基于JRbel实现项目热部署修改Java、Xml文件无需重启项目

Idea基于JRbel实现项目热部署修改Java、Xml文件无需重启项目 1.JRbel服务安装2.JRbel插件安装3.JRbel配置 1.JRbel服务安装 直接装插件的话&#xff0c;需要用到一个服务地址&#xff0c;服务下载链接&#xff1a;&#xff08;现在没时间搞&#xff0c;会尽快加上&#xff09;…

合合信息亮相PRCV大会,探讨生成式AI时代的内容安全与系统构建加速

一、前言 在人工智能技术的飞速发展下&#xff0c;生成式AI已经成为推动社会进步的重要力量。然而&#xff0c;随着技术的不断进步&#xff0c;内容安全问题也日益凸显。如何确保在享受AI带来的便利的同时&#xff0c;保障信息的真实性和安全性&#xff0c;已经成为整个行业待解…

Jmeter自动化实战

前言 由于系统业务流程很复杂,在不同的阶段需要不同的数据,且数据无法重复使用,每次造新的数据特别繁琐,故想着能不能使用jmeter一键造数据 创建录制模板 录制模板参考 首先创建一个录制模板 因为会有各种请求头,cookies,签名,认证信息等原因,导致手动复制粘贴的的全面导致接…

Flutter TextField和Button组件开发登录页面案例

In this section, we’ll go through building a basic login screen using the Button and TextField widgets. We’ll follow a step-bystep approach, allowing you to code along and understand each part of the process. Let’s get started! 在本节中&#xff0c;我们…

NVIDIA发布Nemotron-70B-Instruct,超越GPT-4o和Claude 3.5的AI模型

一、Nemotron-70B-Instruct 是什么 Nemotron-70B-Instruct 是由 NVIDIA 基于 Meta 的 Llama 3.1-70B 模型开发的先进大语言模型&#xff08;LLM&#xff09;。该模型采用了新颖的神经架构搜索&#xff08;Neural Architecture Search&#xff0c;NAS&#xff09;方法和知识蒸馏…

【华为HCIP实战课程二十】OSPF特殊区域NSSA配置详解,网络工程师

一、NSSA&#xff08;Not So Stubby Area&#xff09;区域 在NSSA区域内可以拥有ASBR&#xff0c;并且重分发进入OSPF的路由是以7类LSA形式存在&#xff0c;该类型的LSA只能存在于NSSA区域内不接收5类LSA&#xff0c;ABR过滤外部进入该区域的4 5类LSA&#xff0c;可以引入外部…

题解 力扣 LeetCode 739 每日温度 C++

题目传送门&#xff1a; 739. 每日温度 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/daily-temperatures/description/ 思路&#xff1a; 就是单调栈的思路&#xff0c;具体见代码 不知道单调栈的&#xff0c;可以看我的这篇文章&#xff1a; 数…

web3对象如何连接以太网络节点

实例化web3对象 当我们实例化web3对象&#xff0c;我们一般开始用本地址&#xff0c;如下 import Web3 from web3 var web3 new Web3(Web3.givenProvider || ws://localhost:5173)我们要和以太网进行交互&#xff0c;所以我们要将’ws://localhost:5173’的本地地址换成以太…

【Linux学习】(6)编译器gcc/g++

前言 本节重点&#xff1a;掌握gcc/g编译器的使用&#xff0c;并了解其过程&#xff0c;原理 一、Linux编译器-gcc/g使用 1. gcc/g的基本使用 在前面我们学习了vim&#xff0c;知道如何在Linux中编写代码。但又是如何编译代码的&#xff1f;——在Linux中我们编译代码使用的是…

UDP(用户数据报协议)端口监控

随着网络的扩展&#xff0c;确保高效的设备通信对于优化网络功能变得越来越重要。在这个过程中&#xff0c;端口发挥着重要作用&#xff0c;它是实现外部设备集成的物理连接器。通过实现数据的无缝传输和交互&#xff0c;端口为网络基础设施的顺畅运行提供了保障。端口使数据通…

Linux中安装配置SQLite3,并实现C语言与SQLite3的交互。

前言 SQLite 是一个软件库&#xff0c;实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是在世界上最广泛部署的 SQL 数据库引擎。本次实验介绍在Linux上实现C语言和SQLite3的交互&#xff0c;利用C语言编写相关语句&#xff0c;连接数据库、操作数…

【数据结构初阶】二叉树---堆

二叉树-堆的实现 一、树的概念&#xff08;什么是树&#xff09;二、二叉树的概念及结构2.1 二叉树的概念2.2 二叉树的性质2.3 二叉树存储结构 三、二叉树的顺序结构3.1 堆的概念及结构3.2 堆的向下调整算法3.3堆的创建 四、堆的代码实现4.1 堆的初始化4.2 堆的销毁4.3 堆的插入…

如何从iconfont中获取字体图标并应用到微信小程序中去?

下面我们一一个微信小程序的登录界面的制作为例来说明&#xff0c;如何从iconfont中获取字体图标是如何应用到微信小程序中去的。首先我们看效果。 这里所有的图标&#xff0c;都是从iconfont中以字体的形式来加载的&#xff0c;也就是说&#xff0c;我们自始至终没有使用一张…

jenkins 自动化部署Springboot 项目

一、安装docker 1.更新yum命令 yum -y update2.查看机器有残留的docker服务&#xff0c;有就卸载干净 查看docker 服务 rpm -qa |grep docker卸载docker sudo yum remove docker-ce docker-ce-cli containerd.io sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/contai…

linux下的进程等待(wait、waitpid)

目录 引言 进程等待的必要性 见见猪跑&#xff1a;是什么 怎么办 多个子进程时 阻塞等待 非阻塞轮询 参数一&#xff1a; 参数二 进程等待的原理 进程退出相关的宏 第三个参数option&#xff08;设置等待的方式&#xff09; 引言 在Linux操作系统中&#xff0c;进程…

Jmeter实际应用

环境准备 JDK1.8Jmeter 5.6.3 下载地址Jmeter 插件 下载地址 放到lib/ext下 常用命令 # 启动 sh jmeter# 集群模式下启动节点&#xff0c;不启动用不了集群 sh jmeter-server#生成ssl需要的证书, 这里会要求输入个密码&#xff0c;是要在jmeter中用的 keytool -import -ali…

Claude Financial Data Analyst:基于Claude的金融数据分析工具!免费开源!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;专注于分享AI全维度知识&#xff0c;包括但不限于AI科普&#xff0c;AI工…

基于SSM+小程序的垃圾分类管理系统(垃圾2)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM小程序的垃圾分类管理系统实现了管理员及用户。 1、管理员功能结构图&#xff0c;管理员功能有个人中心&#xff0c;管理员管理&#xff0c;基础数据管理、论坛管理、垃圾信息管理…