【SpringSecurity】十三、基于Session实现授权认证

文章目录

  • 1、基于session的认证
  • 2、Demo
    • session实现认证
    • session实现授权

1、基于session的认证

在这里插入图片描述
流程:

  • 用户认证成功后,服务端生成用户数据保存在session中
  • 服务端返回给客户端session id (sid),被客户端存到自己的cookie中
  • 客户端下次再请求,就带上sid,服务端校验是否存在对应的session,存在则不要求用户再登录了

2、Demo

基于Session的认证机制由Servlet制定规范,Serlvet容器以实现,HttpSession相关方法:

方法用途
HttpSession getSession(Boolean create)获取当前HttpSession对象
void setAttribute(String name,Object value)向session中存放对象
object getAttribute(String name)从session中获取对象
void removeAttribute(String name);移除session中对象
void invalidate()使HttpSession失效

准备实体类:

@Data
public class AuthenticationRequestDto {
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
}

@Data
@AllArgsConstructor
public class UserVo {

    private String id;
    private String username;
    private String password;
    private String fullname;
    private String mobile;
}

session实现认证

用Map模拟查询数据库,存储用户信息:

@Service
public class AuthenticationServiceImpl implements AuthenticationService {

    private final Map<String, UserVo> userMap = new HashMap<>();

    {
        userMap.put("zhangsan", new UserVo("1010", "zhangsan", "123", "zhangSan", "133443"));
        userMap.put("lisi", new UserVo("1011", "lisi", "456", "liSi", "144553"));
    }

    @Override
    public UserVo auth(AuthenticationRequestDto dto) {

        if (dto == null
                || StringUtils.isEmpty(dto.getUsername())
                || StringUtils.isEmpty(dto.getPassword())) {
            throw new RuntimeException("账户或密码为空");
        }
        //模拟查询数据库
        UserVo vo = getUserVo(dto.getUsername());
        if (null == vo) {
            throw new RuntimeException("用户不存在");
        }
        if (!vo.getPassword().equals(dto.getPassword())) {
            throw new RuntimeException("密码错误");
        }
        return vo;
    }

    public UserVo getUserVo(String username) {
        return userMap.get(username);
    }

}

定义三个接口,登录,服务端保存session,登出,让session失效。以及一个资源接口,查看当前是登录访问资源,还是未登录访问资源

@RestController
public class Controller {

    @Resource
    private AuthenticationService authenticationService;

    @GetMapping(value = "/login")
    public String login(AuthenticationRequestDto dto, HttpSession session) {
        UserVo userVo = authenticationService.auth(dto);
        //用户信息存入session
        session.setAttribute("sid", userVo);
        return userVo.getFullname() + " success login";
    }

    @GetMapping("/logout")
    public String logout(HttpSession session) {
    	//让session失效
        session.invalidate();
        return " success logout";
    }

    @GetMapping("/r1")
    public String resource(HttpSession session) {
        String fullName = null;
        Object result = session.getAttribute("sid");
        if (result != null) {
            fullName = ((UserVo) result).getFullname();
        } else {
            fullName = "no login";
        }
        return fullName + " access resource ... ";
    }

}

测试:

在这里插入图片描述

登录后访问资源接口:

在这里插入图片描述
退出登录后,再访问资源接口:

在这里插入图片描述
在这里插入图片描述

session实现授权

修改实体类,加个权限字段,存储用户权限

@Data
@AllArgsConstructor
public class UserVo {

    private String id;
    private String username;
    private String password;
    private String fullname;
    private String mobile;

    /**
     * 用户权限
     */
    private Set<String> authorities;
}

实例代码块创建用户到map的代码做调整:

{
        Set<String> auth1 = new HashSet<>();
        auth1.add("p1");   //对应/r1这个接口资源
        Set<String> auth2 = new HashSet<>();
        auth2.add("p2");   //对应/r2这个接口资源
        userMap.put("zhangsan", new UserVo("1010", "zhangsan", "123", "zhangSan", "133443", auth1));
        userMap.put("lisi", new UserVo("1011", "lisi", "456", "liSi", "144553", auth2));
    }

加个测试资源接口/r2

@GetMapping("/r2")
    public String resource2(HttpSession session) {
        String fullName = null;
        Object result = session.getAttribute("sid");
        if (result != null) {
            fullName = ((UserVo) result).getFullname();
        } else {
            fullName = "no login";
        }
        return fullName + " access resource ... ";
    }

写拦截器:

@ComponentScan
public class SimpleAuthInterceptor implements HandlerInterceptor {

    /**
     * 校验用户请求的url是否在权限范围中
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		//从http请求中获取session对象,再拿当前HttpSession对象
        Object object = request.getSession().getAttribute("sid");
        //没有认证
        if (object == null) {
            writeContent(response, "请登录");
        }
        UserVo userVo = (UserVo) object;
        //请求的url
        String requestURI = request.getRequestURI();
        assert userVo != null;
        if (userVo.getAuthorities().contains("p1") && requestURI.contains("/r1")) {
            return true;
        }
        if (userVo.getAuthorities().contains("p2") && requestURI.contains("/r2")) {
            return true;
        }
        //拒绝访问
        writeContent(response,"没有权限,拒绝访问");

        return false;
    }

    private void writeContent(HttpServletResponse response, String msg) throws IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print(msg);
        writer.close();
    }
}

拦截器add并放行/login,只测/r**接口

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    /**
     * 视图解析器
     */
    @Bean
    public InternalResourceViewResolver viewResolver(){
       InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
       viewResolver.setPrefix("/static/");  //前缀
       viewResolver.setSuffix(".jsp");  //后缀
       return viewResolver;
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("login");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SimpleAuthInterceptor()).addPathPatterns("/r**");   //新加进来的拦截器只针对r打头的接口,否则login接口也会被拦截要求登录
    }
}

测试,登录zhangsan,其有r1权限,访问r2接口:

在这里插入图片描述

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

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

相关文章

进阶了解C++(5)——搜索二叉树

1. 什么是搜索二叉树&#xff1a; 在之前针对数据结构的文章中&#xff0c;对数、二叉树以及堆进行了介绍&#xff0c;在本部分&#xff0c;将针对二叉搜索树进行介绍。对于二叉搜索树&#xff0c;其于二叉树相比&#xff0c;最大的特点就是结点的排布是存在规则的。在搜索二叉…

seleniumUI自动化实例(登录CSDN页面)

今天分享一个CSDN登录模块的登录场景 1.配置文件 CSDNconf.py&#xff1a; from selenium import webdriver options webdriver.ChromeOptions() options.binary_location r"D:\Program Files\360\360se6\Application\360se.exe" # 360浏览器安装地址 driver w…

Spark 3.5.0 特性速览

介绍 Spark 3系列已经发布了第六版3.5.0&#xff0c;目前最新3.5.1。 使用最广泛的大数据可扩展计算引擎。数以千计的公司&#xff0c;包括 80% 的财富 500 强企业&#xff0c;都在使用 Apache Spark。来自业界和学术界的 2000 多名开源项目贡献者。 Apache Spark 3.5.0 是…

单片机——数电复习(1)

1逻辑门电路的分类 2高电平与低电平的含义 1逻辑门电路的分类 1.1按了逻辑功能分 与门 或门 非门 异或门 与非门 或非门 与或非门 与门&#xff08;全1为1&#xff09;YAB 全为高电平才输出高电平 使用仿真看现象 当只有一个输入只有一个为1时小灯不亮 当输入都为1时 &a…

【RabbitMQ | 第四篇】基于RabbitMQ实现延迟队列

文章目录 4.基于RabbitMQ实现延迟队列4.1延迟队列定义4.2基于DLX&#xff08;死信交换机&#xff09;实现延迟队列4.2.1实现思路4.2.2主要流程4.2.3实战&#xff08;1&#xff09;创建两个消息队列&#xff1a;原始消息队列、死信队列 and 为原始消息队列关联私信交换机&#x…

搜维尔科技:OptiTrack提供了一个通用、精确、灵活和可监控的系统!

MELS集成OptiTrack与最前沿的虚拟生产阶段 在加拿大蒙特利尔&#xff0c;MELS Studios and Postproduction设有20个工作室&#xff0c;以满足各种规模的电影和电视项目的需求。凭借先进的技术设施和专业的技术团队&#xff0c;梅尔斯为电影行业的合作伙伴提供从摄影棚和设备租…

Python分析无人驾驶汽车在桂林市文旅行业推广的问卷

【项目背景】 通过市场调研、文本分析、访谈和问卷调查等方法&#xff0c;探讨&#xff1a; 网民对无人驾驶汽车出行服务的态度。无人驾驶安全员的行业背景。不同人群在旅游时的交通选择偏好。游客及当地居民对桂林市文旅路线的交通满意度。乘客对无人驾驶汽车的满意度。桂林…

策略模式实战

项目推荐最近开发完成的项目中使用到了策略模式&#xff0c;实现多种支付方式&#xff0c;避免了后期支付方式if-else代码的冗余&#xff0c;也有利于后期支付的一个扩展。同时这个项目非常适合于做毕设&#xff0c;想了解这个项目的同学可以联系我QQ&#xff1a;3808898981 前…

【项目管理后台】Vue3+Ts+Sass实战框架搭建一

项目管理后台 建立项目最好是卸载Vetur 新建.env.d.ts文件安装Eslint安装校验忽略文件添加运行脚本 安装prettier新建.prettierrc.json添加规则新建.prettierignore忽略文件 安装配置stylelint新建.stylelintrc.cjs 添加后的运行脚本配置husky配置commitlint配置husky 强制使用…

【十三】【算法分析与设计】二分查找(1)

704. 二分查找 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 示例 1: 输入: nums [-1,0,3,5,9,12], target 9 输出: 4…

HarmonyOS NEXT应用开发之元素超出List区域

介绍 本示例介绍在List组件内实现子组件超出容器边缘的布局样式的实现方法。 List组件clip属性默认为true&#xff0c;超出容器边缘的子组件会按照List的布局范围被裁剪。为此&#xff0c;可以在List组件内部添加一个占位的ListItem&#xff0c;以达到预期的布局效果。List占…

机器学习-05-特征工程

总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍机器学习中特征工程部分。 参考 机器学习之特征工程详解 特征工程&#xff08;Feature Engineering&#xff09; 特征工程是指使用专业的背景知识和技巧处理数据&#xff0c;使得特征能在机器学习算法上发生更好的…

弹幕视频网站|基于JSP技术+ Mysql+Java+ Tomcat的弹幕视频网站设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;ssm&#xff0c;springboot的平台设计与实现项目系统开发资源&#xff08;可…

【重温设计模式】状态模式及其Java示例

状态模式的基本概念 在编程世界的大海中&#xff0c;各种设计模式就如同灯塔&#xff0c;为我们的代码编写指明方向。其中&#xff0c;状态模式是一种行为设计模式&#xff0c;它让你能在一个对象的内部状态改变时改变其行为&#xff0c;使得对象看起来就像改变了其类一样。这…

1949年-2021年历史县级行政区划分布数据 中国行政村边界数据、乡镇街道边界、行政区划边界

数据范围&#xff1a;全国历史年份县级行政区划 数据类型&#xff1a;面状数据&#xff0c;全国各省市县行政区划边界 数据属性&#xff1a;标准行政区划编码 时间属性&#xff1a;1949年-2021年 分辨率&#xff1a;1:2万--1:5万 数据格式&#xff1a;SHP数据&#xff08;…

力扣刷题之17.电话号码的字母组合

仅做学习笔记之用。 题目&#xff1a; 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 1&#xff1a; 输入&#x…

自注意力机制的理解

一、自注意力要解决什么问题 循环神经网络由于信息传递的容量以及梯度消失问题&#xff0c;只能建立短距离依赖关系。为了建立长距离的依赖关系&#xff0c;可以增加网络的层数或者使用全连接网络。但是全连接网络无法处理变长的输入序列&#xff0c;另外&#xff0c;不同的输…

从服务器到云原生:企业IT基础设施的演进之路

随着数字经济的迅猛发展&#xff0c;企业IT数字化转型已成为推动业务创新和提升竞争力的关键。在这一转型过程中&#xff0c;基础设施的建设与升级显得尤为重要。企业需要不断优化和更新他们的基础设施&#xff0c;以适应不断变化的市场需求和技术发展。本文将探讨企业IT数字化…

软件测试 -- Selenium常用API(java)

写在前面 // 如果文章有问题的地方, 欢迎评论区或者私信指正 目录 什么是Selenium 一个简单的用例 元素定位 id定位 xpath定位 name定位 tag name 定位和class name 定位 操作元素 click send_keys submit text getAttribute 1. 获取元素的 class 属性 2. 获取元素…

Linux TCP参数——tcp_allowed_congestion_control

tcp_allowed_congestion_control 设置允许普通进程使用的拥塞控制算法。这个参数的值阈是tcp_available_congestion_control参数的子集。默认值为"reno"加上tcp_congestion_control参数设置的算法。 reno 慢启动阶段&#xff1a;在开始的时候&#xff0c;cwnd按指数…
最新文章