Shiro的核心API
Subject:用户主题(把操作交给SecurityManager)
SecurityManager:安全管理器(关联Realm)
Realm:Shiro连接数据的桥梁
1、整合SpringBoot:
pom导入jar文件:shiro-spring
2、自定义Realm类
编写自己的Realm类,实现授权与认证逻辑,继承AuthorizingRealm
public class AuthRealm extends AuthorizingRealm {
// 授权逻辑
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("授权逻辑");
// 给资源进行授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 添加资源的授权字符串,实际从数据库拿到授权字符串
info.addStringPermissions("edit"); // edit这个字符串必须与用户之前拦截权限时候配置的字符串一致
// 到数据库查询当前登录用户的授权字符串
// 获取当前登录用户
Subject subject=SecurityUtils.getSubject();
User user=subject.getPrincipal(); // 通过getPrincipal拿到的就是下边的认证登录逻辑中的返回时候的第一个参数user
User dbUser=userService.findById(user.getId());
// 往info中添加授权字符串
info.addStringPermissions(dbUser.getPerms()); // perms是用户表中的一列授权字段
return info;
}
// 认证登录逻辑
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("认证登录逻辑");
// 编写验证的逻辑,判断用户名和密码是否正确
// 1.判断用户名,实际都是从数据库获取用户的数据
// String name="wbs";
// String password="000";
UsernamePasswordToken token=(UsernamePasswordToken )token;
User user=userService.findUserByName(token.getUsername());
if(!token.getUsername.equals(name)){
// 用户名不存在
return null; // 会抛出UnknownAccountException
}
// SimpleAuthorizationInfo是AuthenticationInfo 的一个子类
return new SimpleAuthorizationInfo(user,password,"");
}
}
3、编写shiro配置类(关键步骤)
必须的三个步骤:
1、创建ShiroFilterFactoryBean
2、创建DefaultWebSecurityManager
3、创建Realm
下边是最基本的配置,也是必须的配置
@Configuration
public class ShiroConfiguration {
// 创建ShiroFilterFactoryBean
@Bean("shiroFilterFactoryBean ")
public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager")SecurityManager manager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
// 设置安全管理器
bean.setSecurityManager(manager);
/****************添加自己的认证开始****************/
// 添加Shiro内置过滤器
// Shiro内置过滤器,可以实现权限相关的拦截器
// 常用的过滤器:
/*
anon:无需认证(登录),即可访问
authc:必须认证才可以访问
user:如果使用rememberMeMe的功能直接可以访问
perms:该资源必须授予资源权限才可以访问
role:该资源必须得到角色权限才可以访问
*/
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/add", "authc");
filterChainDefinitionMap.put("/index", "authc");
filterChainDefinitionMap.put("/login", "anon"); // login无需验证
filterChainDefinitionMap.put("/user/*","authc"); // 使用通配符,让user下边的所有资源都进行认证
// 授权过滤器
// 当前授权拦截后,Shiro会自动跳转到一个未授权页面,但是这个页面需要自己编写
filterChainDefinitionMap.put("/edit", "perms[edit]");
filterChainDefinitionMap.put("/update", "perms[update]");
// 修改跳转的登录页面
bean.setLoginUrl("/login"); //登录的时候,转向login这个controller,返回某个页面
bean.setSuccessUrl("/index"); // 登录成功,转向index这个controller,返回某个页面
bean.setUnauthorizedUrl("/unauthorized"); // 设置未授权提示页面,转向unauthorized这个controller,返回某个页面
bean.setFilterChainDefinitionMap(filterChainDefinitionMap); // 将自己定义的需要拦截的都加入到拦截器链中
/****************添加自己的认证结束****************/
return bean;
}
// 创建DefaultWebSecurityManager
@Bean("securityManager")
public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm ) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
// 关联Realm
manager.setRealm(authRealm);
return manager;
}
// 创建Realm
@Bean("authRealm")
public AuthRealm authRealm(CredentialMatcher matcher) {
return new AuthRealm ();
}
/*
配置ShiroDialect,用于thymeleaf和shiro的整合
*/
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
}
4、登录逻辑处理
使用Shiro编写认证操作
@RequestMapping("/login")
public String login(String name,String password,Model model) {
// 1.获取subject
Subject subject = SecurityUtils.getSubject();
// 2.接收用户数据
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
// 3.执行登录方法
try {
// 没有异常,代表登录成功
subject.login(token);
User user = (User) subject.getPrincipal();
session.setAttribute("user", user);
return "index";
} catch (UnknownAccountException e) {
// 用户名不存在 登录失败
model.addAttribute("msg","用户名不存在");
return "login";
}catch (IncorrectCredentialsException e) {
// 密码错误 登录失败
model.addAttribute("msg","密码错误");
return "login";
}
return "login";
}
上边基本的程序代码,就是Shiro整合spring,进行简单的权限拦截功能,其中的Service、Controller、Mapper、Domain等实体类自己进行编写,如果是SpringMVC项目,可以参考SpringMVC,这个里面已经配置好了基本的SpringMVC的基本需要的所有配置,可以在这个项目的基础上边进行修改。
thymeleaf和Shiro标签配合使用的过程
1、在pon.xml中导入thymeleaf对Shiro的扩展坐标:thymeleaf-extras-shiro
2、配置ShiroDialect:在上边的ShiroConfig中代码中进行配置getShiroDialect这个方法
前端页面中写法如下:
<div shiro:hasPermission="edit">
进入用户编辑页面
</div>
<div shiro:hasPermission="update">
进入用户更新页面
</div>