当前位置: 首页 > news >正文

【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"));}@Overridepublic 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 {@Resourceprivate AuthenticationService authenticationService;@GetMapping(value = "/login")public String login(AuthenticationRequestDto dto, HttpSession session) {UserVo userVo = authenticationService.auth(dto);//用户信息存入sessionsession.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是否在权限范围中*/@Overridepublic 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;//请求的urlString 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 {/*** 视图解析器*/@Beanpublic InternalResourceViewResolver viewResolver(){InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();viewResolver.setPrefix("/static/");  //前缀viewResolver.setSuffix(".jsp");  //后缀return viewResolver;}@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("login");}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new SimpleAuthInterceptor()).addPathPatterns("/r**");   //新加进来的拦截器只针对r打头的接口,否则login接口也会被拦截要求登录}
}

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

在这里插入图片描述

相关文章:

  • php 对接Pangle海外广告平台收益接口Reporting API
  • mysql之基本概念与安装
  • maven手动上传的第三方包 打包项目报错 Could not find xxx in central 解决办法
  • 从零开始写 Docker(七)---实现 mydocker commit 打包容器成镜像
  • 【C语言】指针基础知识(一)
  • Excel使用VLOOKUP函数
  • C# 使用OpenCvSharp4将Bitmap合成为MP4视频的环境
  • Android和IOS Flutter应用开发使用 Provider.of 时,可以使用 listen: false 来避免不必要的重建
  • 算法---二分查找练习-2(寻找旋转排序数组中的最小值)
  • 稀碎从零算法笔记Day22-LeetCode:
  • 【类脑智能】脑网络通信模型分类及量化指标(附思维导图)
  • Spark-Scala语言实战(3)
  • Spring Boot:筑基
  • 【滑动窗口】长度最小的子数组|无重复字符的最长子串|最大连续1的个数 III|将 x 减到 0 的最小操作数
  • EPSON XV4001BC陀螺仪传感器汽车导航系统的应用
  • 【5+】跨webview多页面 触发事件(二)
  • CSS 三角实现
  • FastReport在线报表设计器工作原理
  • HomeBrew常规使用教程
  • input的行数自动增减
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • vue自定义指令实现v-tap插件
  • windows下mongoDB的环境配置
  • 成为一名优秀的Developer的书单
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 解析带emoji和链接的聊天系统消息
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 为视图添加丝滑的水波纹
  • 用 Swift 编写面向协议的视图
  • 【干货分享】dos命令大全
  • 仓管云——企业云erp功能有哪些?
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • ​香农与信息论三大定律
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • $.ajax()方法详解
  • ()、[]、{}、(())、[[]]命令替换
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (zt)最盛行的警世狂言(爆笑)
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (生成器)yield与(迭代器)generator
  • (轉貼) UML中文FAQ (OO) (UML)
  • .NET delegate 委托 、 Event 事件,接口回调
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .net(C#)中String.Format如何使用
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • .net2005怎么读string形的xml,不是xml文件。
  • .NET连接MongoDB数据库实例教程
  • [ C++ ] 继承
  • [].slice.call()将类数组转化为真正的数组