一、什么是 Shiro
Shiro 是一个功能强大和易于使用的Java安全框架,为开发提供一个直观全面的解决方案 的 认证,授权,加密,会话管理等
二、Shiro 功能
· Shiro 主要功能
Authentication:身份认证/登录,验证用户是不是拥有相应的身份;
Authorization:授权,即权限验证,判断某个已经认证过的用户是否拥有某些权限访问某些资源,一般授权会有角色授权和权限授权;
SessionManager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的,web
环境中作用是和 HttpSession 是一样的;
Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
· Shiro 的其他功能
Web Support:Web支持,可以非常容易的集成到Web环境;
Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
Testing:提供测试支持;
Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
三、Shiro 高级概述
Shiro 架构包含三个主要的理念:Subject,SecurityManager 和 Realm
四、Shiro 认证过程
1.首先调用 Subject.login(token) 进行登录,其会自动委托给 Security Manager, 调用之前必须通过 SecurityUtils.setSecurityManager() 设置; 2.SecurityManager 负责真正的身份验证逻辑;它会委托给 Authenticator 进行身份验证; 3.Authenticator 才是真正的身份验证者,Shiro API 中核心的身份认证入口点,此处可以自定义插入自己的实现; 4.Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证, 默认 ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm 身份验证; 5.Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息, 如果没有返回 / 抛出异常表示身份验证失败了。此处可以配置多个 Realm,将按照相应的顺序及策略进行访问。
五、访问拦截
当直接访问其他接口时,进行过滤,使其跳转到指定页面或接口
引入pom依赖
<!-- Shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.7.1</version>
</dependency>
假设Controller层有如下三个接口,分别完成不同的动作
期望达成 -> 访问 aaa/bbb 接口时进行拦截,使其跳转至 tologin 接口
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @author LiuXT
*/
@RestController
@RequestMapping("/testshiro")
public class ShiroController {
@PostMapping("/aaa")
public String aaa(){
return "aaa 完成!";
}
@PostMapping("/bbb")
public String bbb(){
return "bbb 完成!";
}
@RequestMapping("/tologin")
public String toLogin(){
return "当前坐标 -> 登录~";
}
}
有接口之后,开始进行Shiro的配置,在开始配置之前,我们需要自定义一个Realm(继承AuthorizingRealm即可)
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* @author LiuXT
*/
public class LiuRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了 -> 授权");
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了 -> 认证");
return null;
}
}
自定义Realm完成后,开始配置 Shiro,新建 ShiroConfig 类
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author LiuXT
*/
@Configuration
public class ShiroConfig {
//3 ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("SecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//添加 Shiro内置过滤器
/*
* anon: 无需认证即可访问
* authc: 需要认证才能访问
* user: 需要拥有 ‘记住我’ 才能用
* perms: 拥有对某个资源权限才能访问
* role: 拥有某个角色权限才能访问
*/
Map<String,String> map = new LinkedHashMap<>();
//拦截器 ("请求路径",“请求过滤方式 ”)
map.put("/testShiro/aaa","authc");
map.put("/testShiro/bbb","authc");
bean.setFilterChainDefinitionMap(map);
// 设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
//配置 如果被拦截 则跳转到 XXX请求
bean.setLoginUrl("/testShiro/login");
return bean;
}
//2 DefaultWebSecurityManager
@Bean(name = "SecurityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("liuRealm") LiuRealm liuRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 关联 LiuRealm
securityManager.setRealm(liuRealm);
return securityManager;
}
//1 创建 realm对象,自定义 Realm
@Bean
public LiuRealm liuRealm(){
return new LiuRealm();
}
}