文章目录
springboot 整合shiro
一、shiro是什么?
概念: Apache Shiro 是一个强大且易用的 Java 安全框架
能做什么:Shiro可以帮我们完成 :认证、授权、加密、会话管理、与 Web 集成、缓存等。
主要认识::
Subject(用户):当前的操作用户 获取当前用户Subject currentUser = SecurityUtils.getSubject()
SecurityManager(安全管理器):Shiro的核心,负责与其他组件进行交互,实现 subject 委托的各种功能
Realms(数据源) :Realm会查找相关数据源,充当与安全管理间的桥梁,经过Realm找到数据源进行认证,授权等操作
Authenticator(认证器): 用于认证,从 Realm 数据源取得数据之后进行执行认证流程处理。
Authorizer(授权器):用户访问控制授权,决定用户是否拥有执行指定操作的权限。
SessionManager (会话管理器):支持会话管理
CacheManager (缓存管理器):用于缓存认证授权信息
Cryptography(加密组件):提供了加密解密的工具包
二、与springboot的整合
1.前期准备
数据库5张表:用户表 角色表 权限表 用户与角色的中间表 角色与权限的中间表
创建spring boot项目 导入所需要的依赖 相应的配置文件 shiro thymeleaf mybatis mysql等
页面准备:登录 主页面 等一些界面
2.ShiroConfiger配置类
@Configuration
public class ShiroConfiger {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
//关联默认的web安全管理
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
return shiroFilterFactoryBean;
}
@Bean(name = "defaultWebSecurityManager")
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
//关联realm
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
//绑定
@Bean(name = "userRealm")
public UserRealm userRealm(){
return new UserRealm();
}
}
自定义realm(认证授权)
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
return null;
}
}
3.过滤(拦截)
过滤规则:anon 指定url可以匿名访问 authc 需登录 authcBasic 指定url需要http认证 logout 退出登录url user需要已登录或者记住我才能访问 roles 拥有某个角色才能进入 perms 拥有某个权限才能进入等
@Configuration
public class ShiroConfiger {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
//关联默认的web安全管理
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//过滤
//过滤规则 anon 指定url可以匿名访问 authc 需登录 authcBasic 指定url需要http认证 logout 退出登录url user需要已登录或者记住我才能访问
//roles 拥有某个角色才能进入 perms 拥有某个权限才能进入
Map<String,String> map=new HashMap<>();
map.put("/user/add","perms[/user/add]");
map.put("/user/update","perms[/user/update]");
map.put("/user/index","anon");
map.put("/user/other","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
//设置登录请求
shiroFilterFactoryBean.setLoginUrl("/user/login");
//设置无权限登录地址
shiroFilterFactoryBean.setUnauthorizedUrl("/user/un");
return shiroFilterFactoryBean;
}
@Bean(name = "defaultWebSecurityManager")
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
//关联realm
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
//绑定
@Bean(name = "userRealm")
public UserRealm userRealm(){
return new UserRealm();
}
书写相应的controller进行验证
4.认证
mapper层: public SysUser selectUser(@Param(“userName”) String userName); 查询数据库实现 通过用户名 查询到相应的对象
controller层:
@RequestMapping("/login2")
public String toLogin2(@RequestParam("username") String username, @RequestParam("password") String password, Model model, ServletRequest request){
//获取当前用户 subject==》》表示当前用户
Subject subject = SecurityUtils.getSubject();
//封装用户的信息 成一个UsernamePasswordToken令牌
UsernamePasswordToken token=new UsernamePasswordToken(username,password);
//一个try 两个catch try 无异常执行登录 两catch 找不到账号 密码错误
try {
subject.login(token);
/*HttpServletRequest httpServletRequest= WebUtils.toHttp(request);
HttpSession session=httpServletRequest.getSession();*/
return "index";//未抛出异常 登录成功
}catch (UnknownAccountException unknownAccountException){
//账号未找到异常
model.addAttribute("msg","账号未找到");
return "login";
}catch (IncorrectCredentialsException incorrectCredentialsException){
//密码错误异常
model.addAttribute("msg","密码错误");
return "login";
}
}
自定义realm:
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//执行认证
//当前的令牌 和 controller里面的令牌未同一个令牌
UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken;
//查询数据库
SysUser sysUser = userService.selectUser(usernamePasswordToken.getUsername());
if (sysUser==null){
//用户名查询为空 账号错误 返回为空 controller登录逻辑 抛出空异常
return null;
}
//密码认证shiro来做
return new SimpleAuthenticationInfo(sysUser,sysUser.getUserPassword(),"");
}
5.授权
mapper层: public List selectUrl(@Param(“userName”) String userName); 5表联查 查询出账号所对应能访问的url地址
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取当前用户
Subject subject = SecurityUtils.getSubject();
//获取认证时传递的资源 第一个参数
SysUser principal = (SysUser) subject.getPrincipal();
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
//授权
//获取当前用户的url地址集合
List<String> list = userService.selectUrl(principal.getUserName());
for (int i=0;i<list.size();i++){
info.addStringPermission(list.get(i));
}
return info;
}
6.注销
controller层:调用当前用户的logout方法 Subject subject = SecurityUtils.getSubject(); subject.logout();
7.显示问题(登录 注销同时显示 无权限地址显示等)
shiro配置类:
@Bean
public ShiroDialect shiroDialect(){
return new ShiroDialect();
}
页面整合:
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
登录 注销显示:
controller:
将登录信息保存到session
Session session=subject.getSession();
session.setAttribute("loginUser",token);
注销调用当前对象的logout方法
页面:
<div th:if="${session.loginUser!=null}">
<a href="/user/logout">登出</a>
</div>
<div th:if="${session.loginUser==null}">
<a href="/user/login">登录</a>
</div>
不显示无权限的地址
页面:
<div shiro:hasPermission="/user/add">
<a href="/user/add">add</a>
</div>
<div shiro:hasPermission="/user/update">
<a href="/user/update">update</a>
</div>
<a href="/user/other">other</a>
8.MD5加密
Md5Hash hash = new Md5Hash(“1”,“admin”,3);
参数:需要加密的字符 加盐(一般为用户名) 迭代次数