根据狂神课程学习
如果你是需要设计RBAC(Role Based Access Control)基础系统,需要编写大量用于权限控制的代码时。那么你需要使用Shiro。因为Shiro已经将RBAC系统大量的代码封装好,可以减少我们大量的工作量。
如:页面的显示的HTML控件根据登录用户的权限不同而不同。使用Shiro可以轻松解决。
shiro
1.Authenticator:认证器,管理登陆与登出。
2.Authorizer:授权器,赋予主体权限。
3.Session Manager:session管理器,session管理机制。不借助任何web容器使用session
4.Session Dao:session操作,主要增删改查。
5.Cache Manager:缓存管理器
6.Pluggable Realms(1 or more):shiro与数据库的连接,认证授权校验
7.Cryptography:数据加密,加密算法的实现(SHA、MD5)
8.web Support:对Web项目的支持,Shiro的标签!!
https://github.com/apache/shiro/blob/master/samples/quickstart/
1.导入日志相关依赖
2.配置文件 log4j.properties
3.快速开始,helloworld
获取当前用户对象
Subject currentUser = SecurityUtils.getSubject();通过当前用户拿到session
Session session = currentUser.getSession();用户对象的常用方法:
//判断当前用户是否被认证 currentUser.isAuthenticated() //获得当前用户的一个认证 currentUser.getPrincipal() //当前用户是否拥有xx角色 currentUser.hasRole("schwartz") //已登录用户是否具有某种权限 currentUser.isPermitted("lightsaber:wield")令牌:
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa"); token.setRememberMe(true);//设置记住我功能 currentUser.login(token);//执行登录操作 currentUser.logout();//退出操作1.先新建一个spring boot的web项目,引入thymeleaf依赖,写好controller,搭建好基础环境,确认能跑起来
2.导入jar包
<!--shiro整合spring的包--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency>3.编写配置类
config->ShiroConfig.java
package cn.fzj.config; import org.springframework.context.annotation.Configuration; /** * @author Mike */ @Configuration public class ShiroConfig { //创建realm对象,需要自定义类 //DefaultWebSecurityManager //shiroFilterFactoryBean }config->UserRealm 继承AuthorizingRealm
用户认证:
package cn.fzj.config; 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 Mike * 自定义的realm */ public class UserRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了=>授权doGetAuthorizationInfo"); return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("执行了=>认证doGetAuthorizationInfo"); return null; } }完善ShiroConfig.java
import org.springframework.context.annotation.Configuration; /** * @author Mike */ @Configuration public class ShiroConfig { //1.创建realm对象,需要自定义类 @Bean(name = "userRealm") public UserRealm userRealm(){ return new UserRealm(); } //2.DefaultWebSecurityManager @Bean(name="securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //关联UserRealm securityManager.setRealm(userRealm); return securityManager; } //3.shiroFilterFactoryBean @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); return bean; } }写两个页面,页面跳转的请求,index写两个a标签
@RequestMapping("/user/add") public String add(){ return "user/add"; } @RequestMapping("/user/update") public String update(){ return "user/update"; }修改ShiroConfig.java->getShiroFilterFactoryBean()做测试
//3.shiroFilterFactoryBean @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); //添加shiro的内置过滤器 /* anon:无需认证就可以访问 authc:必须认证了才能访问 user:必须拥有 记住我功能才能用 perms:拥有对某个资源的权限才能访问 role:拥有某个角色权限才能访问 */ Map<String,String> filterMap = new LinkedHashMap<>(); filterMap.put("/user/add","authc"); bean.setFilterChainDefinitionMap(filterMap); return bean; }此时点击页面发现点add会报错,点update可以正常跳转
我们并不像让他报错,想让他跳转到一个登录页面怎么办呢?
这会新建一个login.html
修改ShiroConfig.java->getShiroFilterFactoryBean(),添加这样一句代码
//设置登陆的请求 bean.setLoginUrl("/toLogin");此时点击权限不够的a标签就会跳转到登录页面
那么我们怎么给一个用户给权限呢?也就是
1.导包
2.application.yml
3.application.properties
4.pojo
5.mapper->UserMapper(interface)
6.UserMapper.xml
7.UserService
8.UserServiceImpl
9.测试一下,底层能不能成功运行
修改UserRealm.java
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("执行了=>授权doGetAuthorizationInfo"); UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken; //认证用户名,密码,数据库中取 User user = userService.queryUserByName(userToken.getUsername()); if (user==null){//用户为空,没找到 return null;//会抛出一个异常 } //关于密码的认证由shiro自己做 return new SimpleAuthenticationInfo(user,user.getPwd(),""); }//这里传回user对象,后面在授权时才能通过subject.getPrincipal()拿到user对象shiroConfig.java
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); //添加shiro的内置过滤器 /* anon:无需认证就可以访问 authc:必须认证了才能访问 user:必须拥有 记住我功能才能用 perms:拥有对某个资源的权限才能访问 role:拥有某个角色权限才能访问 */ Map<String,String> filterMap = new LinkedHashMap<>(); //授权,然后用户点击了未授权的请求,会跳转到充值页面 filterMap.put("/user/add","perms[user:add]"); filterMap.put("/user/*","authc"); bean.setFilterChainDefinitionMap(filterMap); //设置登陆的请求 bean.setLoginUrl("/toLogin"); //设置未授权页面 bean.setUnauthorizedUrl("/noAuth"); return bean; }留意put的顺序
修改UserRealm.java
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了=>授权doGetAuthorizationInfo"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addStringPermission("user:add"); return info; }但这样是每有一个用户经过就会赋给他权限,也就是说只要用户登陆了就有权限,没有权限的分级
再次修改UserRealm.java
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了=>授权doGetAuthorizationInfo"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //info.addStringPermission("user:add"); //拿到当前登录的这个对象 Subject subject = SecurityUtils.getSubject(); User currentUser = (User) subject.getPrincipal();//拿到user对象 info.addStringPermission(currentUser.getPerms());//设置当前用户的权限 return info; }修改ShiroConfig.java
//授权,然后用户点击了未授权的请求,会跳转到充值页面 filterMap.put("/user/add","perms[user:add]"); filterMap.put("/user/update","perms[user:update]"); //相当于是确认用户有没有某种权限接下来,我们想让他有什么权限,就在界面上显示什么权限,没有的权限就不显示
1.导入一个整合包
<!--thymeleaf-shiro--> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency>2.再shiroConfig.java中整合
//整合ShiroDialect:用来整合shiro thymeleaf @Bean public ShiroDialect getShiroDialect(){ return new ShiroDialect(); }3.index
<div shiro:hasPermission="user:add"> <a th:href="@{/user/add}">add</a> </div>4.UserRealm.java
Subject currentSubject = SecurityUtils.getSubject(); Session session = currentSubject.getSession(); session.setAttribute("loginUser",user);//这会登陆成功就存到session5.index.html
<div th:if="${session.loginUser==null}"> <a th:href="@{toLogin}">登录</a> </div>GitHub上有完整代码 GitHub仓库地址