博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
springboot入门_shiro
阅读量:5274 次
发布时间:2019-06-14

本文共 8987 字,大约阅读时间需要 29 分钟。

shiro是apache的一款开元安全框架,可以进行用户身份的认证,授权,session管理,加密等。相对于springsecurity来说比较简单,容易理解和使用。下来我们实现在springboot项目中使用shiro框架。

我们使用RBAC(基于角色的访问控制)来设计角色权限关系,有3个实体:用户,角色,权限,在RBAC中用户拥有某一种角色,角色拥有一个或者多个资源,所以表结构设计如下:

1 用户信息 2   DROP TABLE IF EXISTS `user_info`; 3   CREATE TABLE `user_info` ( 4     `id` int(11) NOT NULL AUTO_INCREMENT, 5     `username` varchar(50) DEFAULT NULL, 6     `password` varchar(32) DEFAULT NULL, 7     `email` varchar(50) DEFAULT NULL, 8     `usertype` char(1) DEFAULT NULL, 9     PRIMARY KEY (`id`)10  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;11  12  角色信息13  DROP TABLE IF EXISTS `role_info`;14  CREATE TABLE `role_info` (15    `id` int(11) NOT NULL AUTO_INCREMENT,16    `rolename` varchar(50) DEFAULT NULL,17    `roledesc` varchar(100) DEFAULT NULL,18    PRIMARY KEY (`id`)19  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;20  21  用户角色关系22  DROP TABLE IF EXISTS `user_role`;23  CREATE TABLE `user_role` (24    `id` int(11) NOT NULL AUTO_INCREMENT,25    `userid` int(11) NOT NULL,26    `roleid` int(11) NOT NULL,27    PRIMARY KEY (`id`)28  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;29  30  资源(权限)信息31  DROP TABLE IF EXISTS `resource_info`;32  CREATE TABLE `resource_info` (33    `id` int(11) NOT NULL AUTO_INCREMENT,34    `resourceName` varchar(50) NOT NULL,35    `resourceUrl` varchar(50) NOT NULL,36    `resourceType` char(1) NOT NULL COMMENT '1-菜单;2-按钮',37    `resourcePid` int(11) DEFAULT NULL COMMENT '上级,按钮上级为菜单',38    PRIMARY KEY (`id`)39  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;40  41  角色资源关系42  DROP TABLE IF EXISTS `role_resource`;43  CREATE TABLE `role_resource` (44    `id` int(11) NOT NULL AUTO_INCREMENT,45    `roleId` int(11) NOT NULL,46    `resourceId` int(11) NOT NULL,47    PRIMARY KEY (`id`)48  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

下来实现springboot项目与shiro的整合,创建springboot项目并使用mybatis做数据库访问,不清楚springboot整合mybatis的朋友可以看我之前的笔记,我们假设已经有了项目,这里只说整合shiro。

1 在pom文件中添加对shiro的依赖

org.apache.shiro
shiro-spring
1.4.0

2 创建shiro配置信息类,完成配置

1 @Configuration  2 public class ShiroConfig {  3       4     /**  5      * shiro 过滤器  6      * @param securityManager  7      * @return  8      */  9     @Bean 10     public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){ 11         ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); 12         shiroFilter.setSecurityManager(securityManager); 13         shiroFilter.setLoginUrl("/login");//登录失败后默认跳转到登录地址去 14         shiroFilter.setSuccessUrl("/main");//登录成功后跳转地址 15          16         /** 17          * 过滤器链, 从前往后 顺序判断 18          */ 19         Map
filterChain = new LinkedHashMap
(); 20 //记住我或者认证登录通过可以访问 21 filterChain.put("/main", "user"); 22 23 filterChain.put("/js/**", "anon");//设置静态资源可以匿名访问 24 filterChain.put("/logout", "logout");//logout shiro已经做了实现 25 filterChain.put("/login", "anon");//可匿名访问 26 27 filterChain.put("/**", "authc");// 除了上边配置的路径及资源外,其他访问都需要认证,此项必须放在最后 28 shiroFilter.setFilterChainDefinitionMap(filterChain); 29 30 shiroFilter.setUnauthorizedUrl("/unAuthPage");//没有授权的页面 31 return shiroFilter; 32 } 33 34 /** 35 * 安全管理器 36 * @return 37 */ 38 @Bean 39 public DefaultWebSecurityManager securityManager(){ 40 DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 41 securityManager.setRealm(getShiroRealm());//自定义realm 42 securityManager.setRememberMeManager(rememberMeManager());//记住我管理器 43 return securityManager; 44 } 45 46 /** 47 * 自定义的realm 48 * @return 49 */ 50 @Bean 51 public ShiroRealm getShiroRealm(){ 52 ShiroRealm shiroRealm = new ShiroRealm(); 53 shiroRealm.setCredentialsMatcher(credentialsMatcher());//凭证匹配器 54 return shiroRealm; 55 } 56 57 /** 58 * 凭证匹配器 (密码的校验交给了shiro的SimpleAuthenticationInfo处理) 59 * @return 60 */ 61 @Bean 62 public HashedCredentialsMatcher credentialsMatcher(){ 63 HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); 64 credentialsMatcher.setHashAlgorithmName("MD5");//散列算法名称,如:md5 65 credentialsMatcher.setHashIterations(2);//散列算法的次数 66 return credentialsMatcher; 67 } 68 69 /** 70 * 记住我管理器 71 * @return 72 */ 73 @Bean 74 public CookieRememberMeManager rememberMeManager(){ 75 CookieRememberMeManager rememberMeManager = new CookieRememberMeManager(); 76 rememberMeManager.setCipherKey(Base64.decode("2AvVhdsgUs0FSA3SDFAdag==")); 77 rememberMeManager.setCookie(cookie()); 78 return rememberMeManager; 79 } 80 81 /** 82 * 记住我 cookie 83 * @return 84 */ 85 @Bean 86 public SimpleCookie cookie(){ 87 SimpleCookie rememberMeCookie = new SimpleCookie("rememberMe"); 88 rememberMeCookie.setHttpOnly(true); 89 rememberMeCookie.setMaxAge(60);//记住我生效时间,单位 秒 90 return rememberMeCookie; 91 } 92 93 /** 94 * shiro生命周期 95 * @return 96 */ 97 @Bean 98 public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { 99 return new LifecycleBeanPostProcessor();100 }101 102 }

2 自定义的realm,实现认证和授权

1 public class ShiroRealm extends AuthorizingRealm { 2      3     @Autowired 4     private UserInfoService userInfoService; 5     @Autowired 6     private UserRoleService userRoleService; 7     @Autowired 8     private ResourceInfoService resourceInfoService; 9 10     /**11      * 授权12      */13     @Override14     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {15         SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();16         Set
permissionsSet = new HashSet
();//用来存放用户所拥有的权限资源17 //当前用户18 UserInfoEntity userInfo = (UserInfoEntity) principals.getPrimaryPrincipal();//如果认证方法中保存的是用户账号,此处获取的是用户的账号,如果存的是用户对象,则此处获取的是用户对象19 //当前用户角色20 UserRole userRole = userRoleService.selectByUserId(userInfo.getId());21 if(userRole != null){22 List
resourceList = resourceInfoService.selectByRoleId(userRole.getRoleId());23 if(resourceList != null && resourceList.size()>0){24 for(int i=0; i

3 登录实现

1 @Controller 2 public class LoginController { 3      4     private static final Logger logger = LogManager.getLogger(LoginController.class); 5      6     @RequestMapping("/login") 7     public String login(){ 8         logger.info("跳转至登录页。。。"); 9         return "login";10     }11     12     @RequestMapping(value="/login",method=RequestMethod.POST)13     @ResponseBody14     public String doLogin(@RequestParam("username") String username, @RequestParam("password") String password, 15             @RequestParam(value = "rememberMeParam", required = false) String rememberMeParam, Map
map){16 UsernamePasswordToken token = new UsernamePasswordToken(username, password);17 18 //记住我19 if("Y".equals(rememberMeParam)){20 token.setRememberMe(true);21 }22 23 Subject subject = SecurityUtils.getSubject();24 try {25 subject.login(token);26 } catch (UnknownAccountException e) {27 //e.printStackTrace();28 logger.info("账号不存在");29 } catch (IncorrectCredentialsException e) {30 //e.printStackTrace();31 logger.info("密码不正确");32 }33 34 if(subject.isAuthenticated()){35 map.put("result", "success");36 logger.info("登录成功。。。");37 }else{38 map.put("result", "faile");39 map.put("msg", "账号或密码错误");40 }41 return JSON.toJSONString(map);42 }43 44 @RequestMapping("/main")45 public String main(Model model){46 Subject subject = SecurityUtils.getSubject();47 UserInfoEntity userInfo = (UserInfoEntity) subject.getPrincipal();48 model.addAttribute("currentUser", userInfo);49 return "main";50 }51 52 @RequestMapping("/unAuthPage")53 public String unAuthPage(){54 return "unAuth";55 }56 57 @RequestMapping("/logout")58 public String logout(){59 Subject subject = SecurityUtils.getSubject();60 subject.logout();61 return "redirect:/login";62 }63 64 }

4 退出 退出功能shiro已经为我做了实现,我们只需要调用Subject的logout()方法即可实现用户退出。

5 测试 

在没有登录的情况下,如果我们访问main方法,会被shiroFilter拦截,并将请求转向loginUrl方法引导用户登录;登录成功后会跳转至successUrl;

在页面上我们使用shiro的标签来做权限过滤,需要在页面引入shiro标签库:<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>,可以在菜单或者按钮上加上权限过滤标签如:

  
用户管理

 

在加载页面时,遇到shiro标签时会去后台查询用户权限信息,如果用户拥有当前标签中name属性指定的权限信息时会加载并显示当前shiro标签包含的页面元素信息,否则不会显示

 

转载于:https://www.cnblogs.com/Allen-Wl/p/9304425.html

你可能感兴趣的文章
Java线程池ThreadPoolExecutor使用和分析
查看>>
Power of Two
查看>>
批量隐藏注释
查看>>
过滤选择器——可见性过滤选择器
查看>>
(数论)数的计算
查看>>
Ueditor富文本编辑器
查看>>
onBlur事件与onfocus事件(js)
查看>>
Struts2之Ognl
查看>>
获取apk的package name 和 Activity
查看>>
Struts2开发基本步骤
查看>>
获取顶级常量、祖先链、私有方法
查看>>
java8新特性练手--从菜鸟教程中
查看>>
数据库连接池的工作原理
查看>>
计算中英混合字符串的自己字节长度
查看>>
《一江春水向东流》——任正非
查看>>
XML编辑器之XMLSpy2005
查看>>
Eclipse代码注释模板
查看>>
标准C++中的string类的用法总结(转)
查看>>
java计算器 图形用户界面 精简版
查看>>
measureChildren作品
查看>>