怎么做登陆(单点登陆)功能?

article/2025/9/3 19:49:38

登陆是系统最基础的功能之一。这么长时间了,一直在写业务,这个基础功能反而没怎么好好研究,都忘差不多了。今天没事儿就来撸一下。

以目前在接触的一个系统为例,来分析一下登陆该怎么做。

简单上个图(有水印。因为穷所以没开会员)

 

先分析下登陆要做啥

首先,搞清楚要做什么。

登陆了,系统就知道这是谁,他有什么权限,可以给他开放些什么业务功能,他能看到些什么菜单?。。。这是这个功能的目的和存在的意义。

怎么落实?

怎么实现它?用什么实现?

我们的项目是Springboot + Vue前后端分离类型的。

选择用token + redis 实现,权限的话用SpringSecurity来做。

前后端分离避不开的一个问题就是单点登陆,单点登陆咱们有很多实现方式:CAS中央认证、JWT、token等,咱们这种方式其实本身就是基于token的一个单点登陆的实现方案。

单点登陆我们改天整理一篇OAuth2.0的实现方式,今天不搞这个。

上代码

概念这个东西越说越玄。咱们直接上代码吧。

接口:

@PostMapping("/login")
public AjaxResult login(@RequestBody LoginBody loginBody)
{AjaxResult ajax = AjaxResult.success();// 生成令牌//用户名、密码、验证码、uuidString token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),loginBody.getUuid());ajax.put(Constants.TOKEN, token);return ajax;
}
复制代码

用户信息验证交给SpringSecurity

/**
* 登录验证
*/
public String login(String username, String password, String code, String uuid)
{// 验证码开关,顺便说一下,系统配置相关的开关之类都缓存在redis里,系统启动的时候加载进来的。这一块儿的代码就不贴出来了boolean captchaEnabled = configService.selectCaptchaEnabled();if (captchaEnabled){//uuid是验证码的redis key,登陆页加载的时候验证码生成接口返回的validateCaptcha(username, code, uuid);}// 用户验证 -- SpringSecurityAuthentication authentication = null;try{UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);AuthenticationContextHolder.setContext(authenticationToken);// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername。//authentication = authenticationManager.authenticate(authenticationToken);}catch (Exception e){if (e instanceof BadCredentialsException){AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));throw new UserPasswordNotMatchException();}else{AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));throw new ServiceException(e.getMessage());}}finally{AuthenticationContextHolder.clearContext();}AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));LoginUser loginUser = (LoginUser) authentication.getPrincipal();recordLoginInfo(loginUser.getUserId());// 生成tokenreturn tokenService.createToken(loginUser);
}
复制代码

把校验验证码的部分贴出来,看看大概的逻辑(这个代码封装得太碎了。。。没全整出来)

/*** 校验验证码*/
public void validateCaptcha(String username, String code, String uuid)
{//uuid是验证码的redis keyString verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); //String CAPTCHA_CODE_KEY = "captcha_codes:";String captcha = redisCache.getCacheObject(verifyKey);redisCache.deleteObject(verifyKey);if (captcha == null){AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));throw new CaptchaExpireException();}if (!code.equalsIgnoreCase(captcha)){AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));throw new CaptchaException();}
}
复制代码

token生成部分

这里,token

/*** 创建令牌*/
public String createToken(LoginUser loginUser)
{String token = IdUtils.fastUUID();loginUser.setToken(token);setUserAgent(loginUser);refreshToken(loginUser);
​Map<String, Object> claims = new HashMap<>();claims.put(Constants.LOGIN_USER_KEY, token);return createToken(claims);
}
复制代码

刷新token

/*** 刷新令牌*/
public void refreshToken(LoginUser loginUser)
{loginUser.setLoginTime(System.currentTimeMillis());loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);// 根据uuid将loginUser缓存String userKey = getTokenKey(loginUser.getToken());redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
}
复制代码

验证token

/*** 验证令牌*/
public void verifyToken(LoginUser loginUser)
{long expireTime = loginUser.getExpireTime();long currentTime = System.currentTimeMillis();if (expireTime - currentTime <= MILLIS_MINUTE_TEN){refreshToken(loginUser);}
}
复制代码

注意这里返回给前端的token其实用JWT加密了一下,SpringSecurity的过滤器里有进行解析。

另外,鉴权时会刷新token有效期,看下面第二个代码块的注释。

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
{//...无关的代码删了httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
}
复制代码
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
{@Autowiredprivate TokenService tokenService;
​@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws ServletException, IOException{LoginUser loginUser = tokenService.getLoginUser(request);if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())){//刷新token有效期tokenService.verifyToken(loginUser);UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(authenticationToken);}chain.doFilter(request, response);}
}
复制代码

这个登陆方案里用了token + redis,还有JWT,其实用哪一种方案都可以独立实现,并且两种方案都可以用来做单点登陆。

这里JWT只是起到个加密的作用,无它。


http://chatgpt.dhexx.cn/article/TTmHDfvg.shtml

相关文章

SSO单点登陆

1 SSO简介 1.1 什么是SSO 单点登录(SingleSignOn&#xff0c;SSO)&#xff0c;在多个应用系统中&#xff0c;用户只需一次登录就可以访问所有相互信任的应用系统。单点登录常用的协议包括 CAS、OAuth、OpenID Connect、SAML。 例如&#xff1a;百度旗下有很多的产品&#xff…

sso单点登陆实现

多系统实现单点登录方案&#xff1a;SSO 单点登录 一、什么是单点登录SSO&#xff08;Single Sign-On&#xff09; SSO是一种统一认证和授权机制&#xff0c;指访问同一服务器不同应用中的受保护资源的同一用户&#xff0c;只需要登录一次&#xff0c;即通过一个应用中的安全验…

单点登陆和无状态登陆

很多人都听说过单点登陆。今天我们来说说什么是单点登陆和无状态登陆。 传统的项目都是使用session来验证登陆&#xff0c;但是在分布式项目中使用session是不行的。因为每个服务都是一个独立的项目&#xff0c;那么我们将服务拆分&#xff0c;肯定会有一个登陆的模块。如果将用…

windows文件句柄修改

找到如下注册表分支&#xff1a; HKEY_LOCAL_MACHINE – SOFTWARE – – Microsoft – – – Windows NT – – – – CurrentVersion – – – – – Windows 在右侧窗格中可以看到名为“GDIProcessHandleQuota”与“USERProcessHandleQuota”的注册表项; GDIProcessHandleQuo…

Linux 查看文件句柄信息

查看系统的最大文件句柄数和文件句柄的使用者PID ulimit -n查看当前系统的最大句柄数显示如下 ulimit命令详解 ulimit -HSn x设置当前系统的文件句柄数为x 以上命令中&#xff0c;H指定了硬性大小&#xff0c;S指定了软性大小&#xff0c;n表示设定单个进程最大的打开文件句柄…

Windows查看文件句柄

2019独角兽企业重金招聘Python工程师标准>>> 图形界面方式 打开任务管理器 2. 性能tab,点击链接打开资源监视器; 3. 现在cpu tab,关联的句柄后面的输入框可以输入你要搜索的文件路径,可模糊匹配; 命令方式 Windows系统本身并不内置命令查看句…

linux文件句柄数

1、问题阐述&#xff1a; too many open files&#xff1a;顾名思义即打开过多文件数。 不过这里的files不单是文件的意思&#xff0c;也包括打开的通讯链接(比如socket)&#xff0c;正在监听的端口等等&#xff0c;所以有时候也可以叫做句柄(handle)&#xff0c;这个错误通常…

windows 查看打开的文件句柄

经常当我们删除文件时&#xff0c;有时会提示【操作无法完成&#xff0c;因为文件已在另一个程序中打开&#xff0c;请关闭该文件并重试】&#xff0c; 这个时候可以资源监控器进行查看运行的进程打开的句柄列表。 具体结果如下显示&#xff1a;

Linux下文件句柄

Too many open files 如果Java打开文件的时候&#xff0c;没有关闭IO流&#xff0c;那么打开到一定数量&#xff0c;在Linux下就会抛出Too many open files的异常。 public static class HoldIOTask implements Runnable {Overridepublic void run() {int count0;try {while(t…

【Linux】文件句柄说明

Linux 文件句柄说明 Linux中所有的事物或资源都是以文件的形式存在&#xff0c;比如消息、共享内存、连接等&#xff0c;句柄可以理解为指向这些文件的指针。 对于这些句柄&#xff0c;Linux是有数量限制的&#xff0c;单个进程默认可以打开的句柄数上限&#xff0c;可以用以…

windows 文件句柄查询

windows经常出现删除/剪切文件时提示文件被占用的问题 打开任务管理器&#xff0c; 选择“性能”选项卡 2. 打开资源管理器&#xff0c; 在关联句柄查询框中输入关键字&#xff0c;过滤查询&#xff0c;然后右键选中对应项&#xff0c;结束任务即可释放句柄

文件句柄

一、文件句柄是什么&#xff1f; 对象在内存中是经常来回移动的&#xff0c;如何快速定位找到这个对象呢&#xff1f; 句柄说&#xff1a; “我来帮你找” windows系统给出的方案 1.进程创建时&#xff0c;windows系统为进程构造了一个句柄表 2.当该进程希望获得一个内核对…

linux开关机命令

shutdown -h now/或者是具体的时间hh:mm&#xff1b; 关机; -h:关机。&#xff1b;-r&#xff1a; 重启 &#xff1b;-c&#xff1a; 取消前一个关机命令。一般就只用shutdown这个命令&#xff1b;halt&#xff0c;poweroff&#xff0c;init 0 关机&#xff1b;init 6&#xff…

Linux命令之关机命令

shutdown命令可以用来进行关闭系统&#xff0c;并且在关机以前传送讯息给所有使用者正在执行的程序&#xff0c;shutdown 也可以用来重开机使用者权限&#xff1a;管理员用户 语法如下&#xff1a; shutdown [-t seconds] [-rkhncfF] time [message] 参数说明&#xff1a; …

Linux 关机 命令

一、正确的关机方法 如果直接按下电源开关&#xff0c;数据有可能中断。若不正常关机&#xff0c;则有可能造成文件系统的损毁。因此&#xff0c;正常关机情况下&#xff0c;应注意以下&#xff1a; 1&#xff09;查看系统的使用状态 查看目前有谁在线&#xff0c;使用“who…

部署图详解

部署图 一、部署图概要 ​ 部署图用于静态建模&#xff0c;是表示运行时过程节点结构、构件实例及其对象结构的图。如果含有依赖关系的构件实例放置在不同节点上&#xff0c;部署视图可以展示出执行过程中的瓶颈。部署图的两种表现形式&#xff1a;实例层部署图和描述层部署图…

EA_画部署图

EA_画部署图 新建部署图增加个性化图标画一个范围Boundary 新建部署图 右键–>添加图 增加个性化图标 右键图标–>外观–>选择可替代图像 选择自定义的图标 画一个范围Boundary

UML-----构件图与部署图

构件图和部署图这两个图都属于实现图。它是用来描述实现方面的信息。构件图用来显示一组构件之间的组织及依赖关系&#xff1b;而部署图则用来描述系统硬件的物理拓扑结构以及在此结构神执行的软件。 构件图 构件图是从软件结构的角度来描述一个系统的主要功能&#xff0c;如子…

移动端UML图应用之UML结构图——包图、部署图和组件图

系列文章目录 移动端UML图应用之UML图简述 移动端UML图应用之UML行为图——用例图、活动图和状态机图 移动端UML图应用之UML交互图——顺序图和通信图 移动端UML图应用之UML结构图——包图、部署图和组件图 移动端UML图应用之UML结构图——类图 文章目录 系列文章目录一、包图…

【UML建模】(7) UML建模之部署图

您好&#xff0c;我是码农飞哥&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通 ❤️ 2. Python爬虫专栏&#xf…