# study **Repository Path**: ponylin/study ## Basic Information - **Project Name**: study - **Description**: 个人学习仓库 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2022-10-04 - **Last Updated**: 2024-05-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # study ## 介绍 个人学习仓库 ## 内容 ### spring-study [Spring的奇妙冒险——第一卷:Spring和IoC的初体验](https://blog.csdn.net/JAVA_php_Jack/article/details/122447438) #### spring-xml [使用xml搭建spring项目的学习](https://www.yuque.com/linkai-czkf1/uq1ddn/rw1gqh) ### shiro-study Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. 1. authentication:认证,确认用户身份,用户名密码验证等 2. authorization:授权,对用户访问系统资源的行为做控制,如后台接口、前台页面元素、敏感数据等资源 三个组件: Subject、Shiro SecurityManager、Realm 基础API: ```java Subject user = SecurityUtils.getSubject(); Session session = user.getSession(); // 认证 user.login(token); // 授权 user.hasRole(); user.isPermitted(); user.isAuthenicated(); // 退出 user.logout(); ``` #### shiro-web 基础框架搭建: shiro配置三板斧 ```java @Configuration public class ShiroConfig { //1 Realm 代表系统资源 @Bean public Realm xxRealm(){ return new XxRealm(); } //2 SecurityManager 流程控制 @Bean public DefaultWebSecurityManager mySecurityManager(Realm xxRealm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(xxRealm); return securityManager; } //3 ShiroFilterFactoryBean 请求过滤器 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager mySecurityManager){ ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean(); factoryBean.setSecurityManager(mySecurityManager); return factoryBean; } } ``` ##### 登录验证、授权 创建自定义Realm对象,继承AuthorizingRealm(用于认证和授权的Realm),实现父类的doGetAuthenticationInfo认证方法和doGetAuthorizingInfo授权方法 设置登录页和未经授权页: ```java // 设置登录页 factoryBean.setLoginUrl("/index.html"); // 设置未经授权页 factoryBean.setUnauthorizedUrl("/common/unauthorized"); ``` ##### 控制资源路径的访问权限 方法一:硬编码方式,自行判断权限 方法二:在shiro配置类的请求过滤器中,集中配置权限信息 Ant路径: 1. `?`:匹配一个字符,如`/admin?`将匹配`/admin1`,但是不匹配`/admin`或者`/admin/`; 2. `*`:匹配零个或多个字符串,如`/admin*`将匹配`/admin`、`/admin123`,但不匹配`/admin/1`,即`*`不包含`/`; 3. `**`:匹配路径中的零个或多个路径,如`/admin/**`匹配`/admin/1`或者`/admin/a/b`,但`/admin**`不会匹配`/admin/1`。 默认拦截器: 1. anon:可以匿名访问,也就是不用登录就可以访问 2. authc:需要认证才能使用 3. logout:注销登录 4. roles:角色过滤器,判断当前用户是否指定角色 5. perms:资源过滤器,判断当前用户是否指定资源 ![默认拦截器.png](shiro-study/默认拦截器.png) 错误补充机制: 没有权限就会进入请求过滤器中配置的UnauthorizedUrl资源 方法三:在对应接口上通过注解进行配置: 1. @RequiresAuthentication:需要完成用户登录才可访问 2. @RequiresGuest:未登录用户可以访问,已登录用户无法访问 3. @RequiresRoles:需要对应的就角色 4. @RequiresPermissions:需要对应的资源权限 5. @RequiresUser:需要完成用户登录且完成设置rememberMe功能 错误补充机制: 没有权限就抛出`org.apache.shiro.authz.AuthorizationException`异常 可以使用Spring Boot的全局异常拦截处理:@RestControllerAdvice ##### 密码加密 HashedCredentialsMatcher: 4个属性: 1. String hashAlgorithm:对应Hash接口的实现类 2. int hashIterations:迭代次数 3. boolean hashSalted:过时 4. boolean storedCredentialsHexEncoded:默认为true 加盐加密: 需要在认证返回的认证信息SimpleAuthenticationInfo中指定需要加的盐 ##### 多Realm登录 org.apache.shiro.authc.pam.ModularRealmAuthenticator: ```java protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException { assertRealmsConfigured(); // 可以定义多个Realm完成不同认证功能 Collection realms = getRealms(); if (realms.size() == 1) { return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken); } else { return doMultiRealmAuthentication(realms, authenticationToken); } } ``` 认证策略: AuthenticationStrategy接口 有三个实现类 1. AllSuccessfulStrategy 需要所有Realm认证成功,才能最终认证成功。 2. AtLeastOneSuccessfulStrategy 至少有一个Realm认证成功,才能最终认证成功。 3. FirstSuccessfulStrategy 第一个Realm认证成功后即返回认证成功,不再进行后面的Realm认证。 ##### 其他 1. 记住我功能:`token.setRememberMe(true);`, `securityManager.setRememberMeManager(rememberMeManager);` 管理RememberMe的数据 2. 会话管理: `securityManager.setSessionManager(sessionManager); `实现会话管理 3. 认证缓存: `MemoryConstrainedCacheManager cacheManager = new MemoryConstrainedCacheManager();`,`securityManager.setCacheManager(cacheManager);` 记住我、会话管理以及认证缓存,都可以通过扩展对应的manager接口的方式,实现自己的灵活扩展,比如将信息共享到redis。