springboot整合shiro
一.数据库这块的准备需要创建五张表
数据库有用户(user)、角色(role)、权限(permission)三个实体,除了实体表以外,为了实现表间用户与角色、角色与权限多对多的表间关系,所以产生了user_role、role_permission两张关系表。在下图中,使用红线将表的外键标记了出来,但为了方便并没有在表中创建外键,我们手动进行维护
再简单介绍下数据库字段,user表中name是用户名,password是密码;role表中name是角色名(如user、vip);permission表中,name是权限名(如会员中心),url是实际的权限字段(user:vip)
对应的sql脚本
/* SQLyog Professional v12.08 (64 bit) MySQL - 5.0.96-community-nt : Database - lastpass ********************************************************************* */ /*!40101 SET NAMES utf8 */; /*!40101 SET SQL_MODE=‘‘*/; /*!40014 SET @@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @@SQL_MODE, SQL_MODE=‘NO_AUTO_VALUE_ON_ZERO‘ */; /*!40111 SET @@SQL_NOTES, SQL_NOTES=0 */; CREATE DATABASE /*!32312 IF NOT EXISTS*/`lastpass` /*!40100 DEFAULT CHARACTER SET utf8 */; USE `lastpass`; /*Table structure for table `permission` */ DROP TABLE IF EXISTS `permission`; CREATE TABLE `permission` ( `id` varchar(255) NOT NULL, `name` varchar(100) default NULL, `url` varchar(100) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*Data for the table `permission` */ insert into `permission`(`id`,`name`,`url`) values (‘1‘,‘用户中心‘,‘user:add‘),(‘2‘,‘会员中心‘,‘user:vip‘); /*Table structure for table `role` */ DROP TABLE IF EXISTS `role`; CREATE TABLE `role` ( `id` varchar(50) NOT NULL, `name` varchar(100) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*Data for the table `role` */ insert into `role`(`id`,`name`) values (‘1‘,‘user‘),(‘2‘,‘vip‘); /*Table structure for table `role_permission` */ DROP TABLE IF EXISTS `role_permission`; CREATE TABLE `role_permission` ( `id` varchar(255) NOT NULL, `role_id` varchar(255) NOT NULL, `permission_id` varchar(255) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*Data for the table `role_permission` */ insert into `role_permission`(`id`,`role_id`,`permission_id`) values (‘1‘,‘1‘,‘1‘),(‘2‘,‘2‘,‘2‘); /*Table structure for table `user` */ DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` varchar(255) NOT NULL, `name` varchar(255) default NULL, `password` varchar(255) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*Data for the table `user` */ insert into `user`(`id`,`name`,`password`) values (‘1‘,‘rhine‘,‘28e5ea71eb6600afb02132dcf27b8e75‘),(‘2‘,‘vip‘,‘01ffb6fc48048d105ba5061f8df5a35e‘); /*Table structure for table `user_role` */ DROP TABLE IF EXISTS `user_role`; CREATE TABLE `user_role` ( `id` varchar(255) NOT NULL, `user_id` varchar(255) NOT NULL, `role_id` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*Data for the table `user_role` */ insert into `user_role`(`id`,`user_id`,`role_id`) values (‘1‘,‘1‘,‘1‘),(‘2‘,‘2‘,‘1‘),(‘3‘,‘2‘,‘2‘); /*!40101 SET _SQL_MODE */; /*!40014 SET _FOREIGN_KEY_CHECKS */; /*!40014 SET _UNIQUE_CHECKS */; /*!40111 SET _SQL_NOTES */;
二.创建springboot项目
1.添加shiro的依赖
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency>
2.创建实体
package com.rhine.blog.po; import java.io.Serializable; /** * @description 权限类 */ public class PermissionBean implements Serializable { private String id; private String name; private String url; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } } package com.rhine.blog.po; import java.io.Serializable; import java.util.HashSet; import java.util.Set; /** * @description 角色类 */ public class RoleBean implements Serializable { private String id; private String name; private Set<PermissionBean> permissions = new HashSet<>(); public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<PermissionBean> getPermissions() { return permissions; } public void setPermissions(Set<PermissionBean> permissions) { this.permissions = permissions; } } package com.rhine.blog.po; import java.io.Serializable; import java.util.HashSet; import java.util.Set; /** * @description 用户类 */ public class UserBean implements Serializable { private String id; private String name; private String password; private Set<RoleBean> roles = new HashSet<>(); public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Set<RoleBean> getRole() { return roles; } public void setRole(Set<RoleBean> roles) { this.roles = roles; } }
3.创建shiro的配置类userRealm和shiroConfig
import com.rhine.blog.po.PermissionBean; import com.rhine.blog.po.RoleBean; import com.rhine.blog.po.UserBean; import com.rhine.blog.service.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.ByteSource; import org.springframework.beans.factory.annotation.Autowired; import java.util.Collection; import java.util.HashSet; import java.util.Set; public class UserRealm extends AuthorizingRealm { @Autowired private UserService userService; /** * 授权 **/ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { Subject subject = SecurityUtils.getSubject(); UserBean user = (UserBean)subject.getPrincipal(); if(user != null){ //用户已经完成登录 给资源进行授权 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 角色与权限字符串集合 Collection<String> rolesCollection = new HashSet<>(); Collection<String> premissionCollection = new HashSet<>(); Set<RoleBean> roles = user.getRole(); for(RoleBean role : roles){ rolesCollection.add(role.getName()); Set<PermissionBean> permissions = role.getPermissions(); for (PermissionBean permission : permissions){ premissionCollection.add(permission.getUrl()); } //添加资源的授权字符串 //这块的需要与shiro类中filterMap.put("/vip/index", "perms[user:vip]") //的保持一致才能起到授权的效果; info.addStringPermissions(premissionCollection); } info.addRoles(rolesCollection); return info; } return null; } /** * 认证 **/ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //获取用户的名字 String userName =(String)authenticationToken.getPrincipal(); //通过用户名获得user对象 UserBean bean = userService.findByName(userName); if(bean == null){ throw new UnknownAccountException(); } ByteSource byteSource = ByteSource.Util.bytes(bean.getName()); // 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(bean, bean.getPassword(),byteSource, bean.getName()); return authenticationInfo; } }
package com.rhine.blog.config; import com.rhine.blog.realm.UserRealm; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; 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; import java.util.LinkedHashMap; import java.util.Map; /** * @author chenyuyu * @description Shiro配置类 * @date Created in 16:07 2018/12/6 * @modified By: */ @Configuration public class ShiroConfig { @Bean("hashedCredentialsMatcher") public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); //指定加密方式为MD5 credentialsMatcher.setHashAlgorithmName("MD5"); //加密次数 credentialsMatcher.setHashIterations(1024); credentialsMatcher.setStoredCredentialsHexEncoded(true); return credentialsMatcher; } @Bean("userRealm") public UserRealm userRealm(@Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher matcher) { UserRealm userRealm = new UserRealm(); userRealm.setCredentialsMatcher(matcher); return userRealm; } @Bean public ShiroFilterFactoryBean shirFilter(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); // 设置 SecurityManager bean.setSecurityManager(securityManager); bean.setSuccessUrl("/main"); // 设置登录跳转页面 bean.setLoginUrl("/toLogin"); // 设置未授权提示页面 bean.setUnauthorizedUrl("/error/unAuth"); /** * Shiro内置过滤器,可以实现拦截器相关的拦截器 * 常用的过滤器: * anon:无需认证(登录)可以访问 * authc:必须认证才可以访问 * user:如果使用rememberMe的功能可以直接访问 * perms:该资源必须得到资源权限才可以访问 * role:该资源必须得到角色权限才可以访问 * * //授权过滤器 //注意:当前授权拦截后,shiro会自动跳转到未授权页面 filterMap.put("/add", "perms[user:add]"); filterMap.put("/update", "perms[user:update]"); * * **/ Map<String, String> filterMap = new LinkedHashMap<>(); filterMap.put("/login","anon"); filterMap.put("/user/index","authc"); //filterMap.put("/vip/index","roles[vip]"); //filterMap.put("/vip/index","roles[user]"); filterMap.put("/druid/**", "anon"); filterMap.put("/static/**","anon"); //filterMap.put("/vip/index", "perms[user:vip]"); filterMap.put("/**","authc"); filterMap.put("/logout", "logout"); bean.setFilterChainDefinitionMap(filterMap); return bean; } /** * 注入 securityManager */ @Bean(name="securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(HashedCredentialsMatcher hashedCredentialsMatcher) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 关联realm. securityManager.setRealm(userRealm(hashedCredentialsMatcher)); return securityManager; } }
认证对应的controller
package com.rhine.blog.controller; 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.stereotype.Controller; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Controller public class MainController { /** * 登录后进入首页 * @param request * @param response * @return */ @RequestMapping("/main") public String index(HttpServletRequest request, HttpServletResponse response){ response.setHeader("root", request.getContextPath()); return "index"; } /** * 进入登陆页面 * @param request * @param response * @return */ @RequestMapping("/toLogin") public String toLogin(HttpServletRequest request, HttpServletResponse response){ response.setHeader("root", request.getContextPath()); return "login"; } /** * 登录访问的页面 * @param request * @param response * @return */ @RequestMapping("/login") public String login(HttpServletRequest request, HttpServletResponse response){ response.setHeader("root", request.getContextPath()); String userName = request.getParameter("username"); String password = request.getParameter("password"); if(!StringUtils.isEmpty(userName)){ // 1.获取Subject Subject subject = SecurityUtils.getSubject(); // 2.封装用户数据 UsernamePasswordToken token = new UsernamePasswordToken(userName, password); // 3.执行登录方法 try{ subject.login(token); //访问UserRealm中doGetAuthenticationInfo方法 return "redirect:/main"; } catch (UnknownAccountException e){ System.out.println("用户名不存在!"); request.setAttribute("msg","用户名不存在!"); } catch (IncorrectCredentialsException e){ System.out.println("密码错误!"); request.setAttribute("msg","密码错误!"); } } return "login"; } /** * 推出登录 * @return */ @RequestMapping("/logout") public String logout(){ Subject subject = SecurityUtils.getSubject(); if (subject != null) { subject.logout(); } return "redirect:/main"; } @RequestMapping("/error/unAuth") public String unAuth(){ return "/error/unAuth"; } }
权限控制对应的controller
package com.rhine.blog.controller; import com.rhine.blog.po.UserBean; import org.apache.shiro.SecurityUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; @Controller public class UserController { @RequestMapping("/user/index") public String add(HttpServletRequest request){ UserBean bean = (UserBean) SecurityUtils.getSubject().getPrincipal(); request.setAttribute("userName", bean.getName()); return "/user/index"; } @RequestMapping("/vip/index") public String update(){ return "/vip/index"; } }
相关推荐
杜鲁门 2020-11-05
luckyxl0 2020-08-16
Dullonjiang 2020-08-09
xclxcl 2020-08-03
zmzmmf 2020-08-03
MicroBoy 2020-08-02
ganjing 2020-08-02
likesyour 2020-08-01
zmzmmf 2020-07-09
MicroBoy 2020-07-05
zzhao 2020-06-26
子云 2020-06-18
visionzheng 2020-06-07
neweastsun 2020-06-04
ErixHao 2020-06-03
GDreams0 2020-06-01
ganjing 2020-05-29
zmzmmf 2020-05-28
nullcy 2020-05-26