springboot实现简单的单点登录

2023-11-03

思路

  1. 用户登录去校验用户信息,校验成功后将登录后的信息持久化,并返回一个系统可识别的信息串
  2. 用户每次访问接口将参数和信息串一起访问,然后通过拦截进行对信息串统一识别认证

实践

用户登录

通过用户名和密码验证是否登录成功,我这里是用accessToken作为系统可识别的信息串,持久化你可以存入数据库,也可以放在redis,但是经常要验证accessToken,建议放在redis中好一点。

 @ApiOperation("登录")
    @PostMapping("login")
    @AuthLogin(needLogin = false)
    public RestResponse<User> login(String username,String password){
        return RestResponse.ok(userService.login(username,password));
    }
@Override
   public UserVO login(String username, String password) {
   	User user = new User() ;
   	user.setUsername(username);
   	user.setPassword(password);
   	QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(user);
   	User users = this.getOne(userQueryWrapper);
   	if(users == null ){
   		throw new BusinessException("用户名或者密码错误");
   	}
   	//生成accessToken
   	String token = tokenService.createToken(users.getId());
   	users.setAccessToken(token);
   	//登录成功后返回用户信息和accessToken
   	return users.of();
   }

accessToken拦截和验证

accessToken拦截是通过拦截器进行拦截,其中包括哪些接口需要拦截,这里也会用到自定义注解,识别和使用,其次也会增加一些拦截器。
1.创建拦截器

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //全局登录拦截请求
        registry.addInterceptor(new AuthLoginIntercept()).addPathPatterns("/**")
                .excludePathPatterns("/file/**")
                .excludePathPatterns("/login/**")
                .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**")
                .excludePathPatterns("/druid/**");

    }

    /**
     * 上传文件外部访问拦截
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/file/**")
                .addResourceLocations("file:"+BaseUploadPath);
    }


}

2.自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Documented
@Inherited
public @interface AuthLogin {

    /**
     *是否需要登录
     * 默认:需要登录
     */
    boolean needLogin() default true ;

}

3.拦截器实现方法

@Service
public class AuthLoginIntercept extends HandlerInterceptorAdapter {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            //拦截所有的请求方法,是否需要登录
            AuthLogin authLoginMethod = handlerMethod.getMethod().getAnnotation(AuthLogin.class);
            if(authLoginMethod != null && !authLoginMethod.needLogin()){
                return true;
            }
            //拦截整个模块,是否需要登录
            AuthLogin authLoginClass = handlerMethod.getBeanType().getAnnotation(AuthLogin.class);
            if(authLoginClass != null && !authLoginClass.needLogin()){
                return true;
            }
            //验证token信息
            this.validAuth();
        }
        return true;
    }


    /**
     * 验证token信息
     */
    private void validAuth(){
        String token = RequestUtil.getToken();
        TokenService tokenService = SpringUtil.getBean(TokenService.class);
        //验证token是否符合条件
        tokenService.validateToken(token);
    }
}

4.验证token

@Override
	public UserVO validateToken(String accessToken) {
		//通过解析token
		UserVO user = getUser(accessToken);
		//更新用户当前的最新信息
		User updateUser = new User();
		updateUser.setId(user.getId());
		updateUser.setLastLoginTime(new Date());
		userService.update(updateUser);
		return user;
	}

通过token获取用户信息

/**
	 * 获取用户信息
	 * @param accessToken
	 * @return
	 * @throws BusinessException
	 */
	public UserVO getUser(String accessToken)throws BusinessException {
		//验证token是否正确
		boolean validToken = validToken(accessToken);
		if(validToken){
		//解密token信息
			UserVO user = decodeUser(accessToken);
			validUser(user);
			return user;
		}
		return null;
	}

验证token的合法性

/**
	 * 校验token信息
	 * @param accessToken 认证
	 * @return
	 * @throws BusinessException
	 */
	public boolean validToken(String accessToken) throws BusinessException{
		if(StrUtil.isBlank(accessToken)){
			throw new BusinessException(Login.getCode(),NotLogin.getCode(),NotLogin.getMsg());
		}
		boolean keyExists = redisService.isKeyExists(AccessToken.getKey(), accessToken);
		if(!keyExists) {
			throw new BusinessException(Login.getCode(),TokenLose.getCode(), TokenLose.getMsg());
		}
		return true;

	}

我这里是用的base64加密用户信息

/**
	 * 解密用户信息
	 * @param accessToken
	 * @return
	 */
	public UserVO decodeUser(String accessToken){
		String userString= (String) redisService.get(AccessToken.getKey(), accessToken);
		String userJson = Base64.decodeStr(userString);
		return JSONObject.parseObject(userJson,UserVO.class);
	}

maven Jar包依赖

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

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
  <!-- 缓存依赖 -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-redis</artifactId>
          <scope>compile</scope>
      </dependency>
 <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>${fastjson.version}</version>
      </dependency>
  <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-aop</artifactId>
      </dependency>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springboot实现简单的单点登录 的相关文章

随机推荐

  • PyCharm单独安装PyKDL

    用于在Ubuntu下Pycharm独立使用PyKDL 不需要ros 使用Pycharm的安装器安装的PyKDL是不能使用的 引用会报错 1 把安装器安装的给卸载掉 2 去GitHub下载代码 Git下载 还有一个类似的代码hrl kdl 不
  • 服务器任务管理器详细信息,服务器任务管理器数字进程

    服务器任务管理器数字进程 内容精选 换一换 针对Windows 2012操作系统 由于安装应用系统会用到 net framework 3 5 而2012自带的 net framework 4 5版本需要卸载 但是卸载之后可能会遇到黑屏 无法
  • mysql按照一个字段分组查询_SQL如何查询一张表的所有字段并按其中一个字段进行分组...

    展开全部 1 创建测试表 create table test group cols id number value varchar2 20 remark varchar2 20 2 插入测试数据 insert into test group
  • java命令大全

    转载地址 http www cnblogs com langtianya p 4208135 html JAVA命令大全 1 java exe 运行java程序 这个相信每一位用Java的人知道了 2 javac exe 编译的Java程序
  • QT-如何使用智能指针

    QT框架提供了三种智能指针 QSharedPointer QWeakPointer和QScopedPointer 这些智能指针可以有效地管理QT对象的内存 避免内存泄漏的问题 同时还能提高代码的可读性和可维护性 QSharedPointer
  • stata的一些操作命令

    一 面板数据填充 面板数据填充 设置好第一年和最后一年 然后用如下命令 sort id year 然后按照id和year排序 xtset id year 设定面板样本和时间变量 ssc install tsfill replace 安装时间
  • 时下火热的 NFT 究竟有什么用?

    如今 NFT 正在以一股十分火热的趋势开始席卷全球 无论是个人还是企业 都开始关注起了这个由区块链技术所衍生出来的全新数字生态 我国为了防止 NFT出现投机 炒作等风险 对于 NFT 二级市场有着严格的监管和限制 使得整个市场并不如国外那般
  • AndroidKiller介绍与使用

    往期推荐 什么是虚拟机 虚拟机有那几种 APK安装流程及详细步骤 APK打包流程 APK文件结构 Android开发之数据储存 APK属于压缩文件 不可以通过直接解压的方式来获取明文内容 需要借助AndroidKiller这类的第三方的工具
  • 关卡9-面向对象三大特征

    封装概述 是面向对象三大特征之一 封装 继承 多态 是面向对象编程语言对客观世界的模拟 客观世界里成员变量都是隐藏在对象内部的 外界是无法直接操作的 封装原则 将类的某些信息隐藏在类内部 不允许外部程序直接访问 而是通过该类提供的方法来实现
  • 毫米波与太赫兹:使用matlab RF propagation进行电波仿真可视化

    使用Matlab RF propagation 工具箱进行电波传播的仿真和可视化显示 并对结果进行分析 仿真场景自定义 天线参数自定义 频率选择移动通信典型频段 或未来移动通信规划频段 课程设计报告参考标准学术期刊论文格式 设计代码1如下
  • 宽带服务器盒信号灯红色闪烁,宽带出现光信号灯是红色是怎么回事

    大家好 我是时间财富网智能客服时间君 上述问题将由我为大家进行解答 如光信号灯变红色或者闪烁 说明接收不到光纤信号 通常是由于存在以下几种情况导致 1 光猫光接口有问题 需要更换光猫 2 室内尾纤连接光猫接头松脱 把接头插好即可恢复 3 室
  • 使用 Ccrypt 在 Linux 中加密/解密文件

    Ccrypt 是一个用于数据加密和解密的命令行工具 Ccrypt 基于 Rijndael 密码 与 AES 标准中使用的密码相同 另一方面 在 AES 标准中 使用 128 位块大小 而 ccrypt 使用 256 位块大小 Ccrypt
  • new运算符

    define CRT SECURE ND WARNINGS include
  • 第4章 BP神经网络

    BP神经网络 1 BP神经网络介绍及发展背景 从前面介绍的感知器学习规则来看 其权值的调整 取决于期望输出与实际输出之差 Delta w i eta t y x i 但是对于各个隐藏层的节点来说 不存在已知的期望输出 因而该学习规则不能用于
  • 打印3的倍数的数

    写一个代码打印1 100之间所有3的倍数的数字 解题思路 1 3的倍数一定能够被3整除 因此i 3 0表达式成立时 则i一定是3的倍数 2 要输出1 100之间的3的倍数 那只需要从1 100循环100次即可 每次拿到i之后 用i 3 0检
  • ECharts可视化图标库 (事件与行为)

    ECharts中的事件与行为 日常开发中用到echarts 一般是用来展示数据 很少在图表上添加一些事件监听函数 但是没用过不代表没有 比如鼠标悬浮之后的高亮样式和鼠标悬浮后显示的tootip 这都属于默认的鼠标悬浮事件 除此之外 如果想要
  • 国王骑士金币问题

    本文以模拟算法的两种方式解题 同时附录递归算法 不建议使用 国王发放金币给骑士 按天数发 天数n 1 2 3 4 5 6 7 8 每天的金币k 1 2 2 3 3 3 4 4 分组模拟 IO 输入天数n 输出金币总数res 循环 按天数执行
  • js详细笔记

    第一天 1 SSR Setver side Render ASP JSP PHP CSR Client side Render2016年 2 js的引入
  • PT100温度采集电路设计

    PT100是正温度系数的热敏电阻 顾名思义 随着温度的升高 电阻的阻值变大 相反 如果随着温度的升高 电阻的阻值变小 就是负温度系数的热敏电阻 之所以叫做PT100 是因为在0度时其阻值为100欧姆 PT100之所以应用很广泛 不仅仅是因为
  • springboot实现简单的单点登录

    思路 用户登录去校验用户信息 校验成功后将登录后的信息持久化 并返回一个系统可识别的信息串 用户每次访问接口将参数和信息串一起访问 然后通过拦截进行对信息串统一识别认证 实践 用户登录 通过用户名和密码验证是否登录成功 我这里是用acces