静かな駅 - Java
type: channel
link: https://yellowswimming.cn/category/java/
description: Java
items: Java进阶（不可变集合和Stream流）
items: Shiro安全管理
items: SpringSecurity实现基本认证和授权

Java进阶（不可变集合和Stream流）
type: item
date: 2022-12-28T18:18:00+08:00
description: Java进阶（不可变集合和Stream流） 1. 创建不可变集合的应用场景 如果某个数据不能被修改，把它防御性地拷贝到不可变集合中是个很好的实践 或者当集合对象被不可信的库调用时，不可变形式是安全的 例如，制定游戏规则。 又如，电脑的配置，这些都是不可变集合的应用场景。 1.1 创建不可变集合List List<String> list = List.of("zs", "lisi", "wangwu"); for (String item : list) { System.out.println(item); } list.remove("zs"); 结果如下：只能进行查询，不能进行添加或者删除操作 1.2 创建不可变结合Set Set<String> set = Set.of("zs", "lisi", "wangwu"); for (String item : set) { System.out.println(item); } set.remove("zs"); 结果如下：依然报错是无法修改，而且set集合元素不能重复的规则同样适用 1.3 创建不可变Map Map<String, String> map = Map.of("张三", "重庆", "李四", "成都", "王五", "海南"); Set<String> keySet = map.keySet(); for (String key : keySet) { System.out.println(key+"=="+map.get(key)); } 结果如下，注意1:map依然不能键重复；注意2：Map的of方法最多只能容纳10个键值对 但是我们可以采用另外一个方法，即 如果我们用entry来作为可变形参，就可以解决of方法的参数限制问题。 Map<String, String> map = Map.of("张三", "重庆", "李四", "成都", "王五", "海南"); Set<Map.Entry<String, String>> entries = map.entrySet(); //将entries变成一个数组 Map.Entry[] arr = entries.toArray(new Map.Entry[0]); Map ofEntries = Map.ofEntries(arr); for (Object o : ofEntries.entrySet()) { System.out.println(o); } //不可变map集合 ofEntries.put("111","bbb"); 如果向不可变集合中试图添加数据，则会报错 当然上面的代码过于繁琐，java已经帮我们封装好了。 因此我们可以在map上直接调用copyOf方法,当然结果都是不可修改 Map<String, String> map1 = Map.copyOf(map); map1.put("11","io"); 2. Stream流 一个基本的demo如下，假设有如下两个需要同时满足的需求 获取以‘z’开头的字符串 获取长度为3的字符串 ArrayList<String> list = new ArrayList<>(); list.add("zs"); list.add("zwr"); list.add("lisi"); list.add("wangwu"); list.stream().filter(name->name.startsWith("z")).filter(name->name.length()==3).forEach(name-> System.out.println(name)); 打印结果如下： 我们可以看到采用stream流可以用最少的代码来完成需求。 2.1 Stream流的思想 可以类比如果的流水线，在Stream流的思想中就是层层筛选，最终得到想要的结果 2.1.1 单列集合 ArrayList<Integer> list = new ArrayList<>(); Collections.addAll(list,1,9,3,7,5); list.stream().forEach(s-> System.out.print(s+" ")); 2.1.2 双列集合 在map中是没有stream()方法直接获取流，因此我们可以先将map转化为entry集合，再调用Stream()方法。 HashMap<String, String> map = new HashMap<>(); map.put("111","aaa"); map.put("222","bbb"); map.put("333","ccc"); map.entrySet().stream().fo…

Shiro安全管理
type: item
date: 2022-10-22T12:49:00+08:00
description: Shiro 安全管理 1.权限的管理 1.1 什么是权限管理 基本上涉及到用户参与的系统都要进行权限管理，权限管理属于系统安全的范畴，权限管理实现对用户访问系统的控制，按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。 权限管理包括用户身份认证和授权两部分，简称认证授权。对于需要访问控制的资源用户首先经过身份认证，认证通过后用户具有该资源的访问权限方可访问。 1.2 什么是身份认证 身份认证，就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令，看其是否与系统中存储的该用户的用户名和口令一致，来判断用户身份是否正确。对于采用指纹等系统，则出示指纹；对于硬件Key等刷卡系统，则需要刷卡。 1.3 什么是授权 授权，即访问控制，控制谁能访问哪些资源。主体进行身份认证后需要分配权限方可访问系统的资源，对于某些资源没有权限是无法访问的 2.什么是shiro Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications. Shiro 是一个功能强大且易于使用的Java安全框架，它执行身份验证、授权、加密和会话管理。使用Shiro易于理解的API，您可以快速轻松地保护任何应用程序—从最小的移动应用程序到最大的web和企业应用程序。 Shiro是apache旗下一个开源框架，它将软件系统的安全认证相关的功能抽取出来，实现用户身份认证，权限授权、加密、会话管理等功能，组成了一个通用的安全认证框架。 3.shiro的核心架构 3.1 Subject Subject即主体，外部应用与subject进行交互，subject记录了当前操作用户，将用户的概念理解为当前操作的主体，可能是一个通过浏览器请求的用户，也可能是一个运行的程序。 Subject在shiro中是一个接口，接口中定义了很多认证授相关的方法，外部程序通过subject进行认证授，而subject是通过SecurityManager安全管理器进行认证授权 3.2 SecurityManager SecurityManager即安全管理器，对全部的subject进行安全管理，它是shiro的核心，负责对所有的subject进行安全管理。通过SecurityManager可以完成subject的认证、授权等，实质上SecurityManager是通过Authenticator进行认证，通过Authorizer进行授权，通过SessionManager进行会话管理等。 SecurityManager是一个接口，继承了Authenticator, Authorizer, SessionManager这三个接口。 3.3 Authenticator Authenticator即认证器，对用户身份进行认证，Authenticator是一个接口，shiro提供ModularRealmAuthenticator实现类，通过ModularRealmAuthenticator基本上可以满足大多数需求，也可以自定义认证器。 3.4 Authorizer Authorizer即授权器，用户通过认证器认证通过，在访问功能时需要通过授权器判断用户是否有此功能的操作权限。 3.5 Realm Realm即领域，相当于datasource数据源，securityManager进行安全认证需要通过Realm获取用户权限数据，比如：如果用户身份数据在数据库那么realm就需要从数据库获取用户身份信息。 ​ 注意：不要把realm理解成只是从数据源取数据，在realm中还有认证授权校验的相关的代码。 3.6 SessionManager sessionManager即会话管理，shiro框架定义了一套会话管理，它不依赖web容器的session，所以shiro可以使用在非web应用上，也可以将分布式应用的会话集中在一点管理，此特性可使它实现单点登录。 3.7 SessionDAO SessionDAO即会话dao，是对session会话操作的一套接口，比如要将session存储到…

SpringSecurity实现基本认证和授权
type: item
date: 2022-10-17T21:32:13+08:00
description: SpringSecurity实现基本认证和授权 1. 环境准备 1.1 构建springboot框架 本篇博客是基于springboot构建springsecurity,因此需要导入springboot相关的依赖. 由于我用的IDE是IDEA，因此可以直接在IDEA里面构建springboot项目(如果是用其他IDE就需要手动构建项目结构或者在spring官网 在线构建springboot并下载下来). 目前spring官网在这里选择JAVA版本的时候是17和19都有，就是没有18，而博主之前一直用的18:smirk:,所以我在这里也没有更换18到其他版本，就暂时先按照 自己电脑装的版本填就行，后面在pom.xml文件里面指定一下java版本就行。 1.2 导入相关依赖 由于springboot默认是maven项目，因此可以在pom.xml文件里直接导入依赖，就不用手动导入jar包。 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.4</version> <relativePath/> </parent> <groupId>com.yellow</groupId> <artifactId>spring_security</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring_security</name> <description>spring_security</description> <properties> <java.version>18</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> …