• spring+mybatis+shiro实战实现权限验证


    数据库准备

    一般要做权限验证需要五张表 user,user_role,role,role_permission,permission分别对应用户,角色,权限以及两个关联表,用户绑定角色,而权限只和角色有关,例如:

    用户1-----角色1----person:query,person:update,person:delete,person:add

    用户2-----角色2---person:query

    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    DROP TABLE IF EXISTS `permission`;
    CREATE TABLE `permission`  (
      `perid` int(11) NOT NULL AUTO_INCREMENT,
      `pername` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `percode` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      PRIMARY KEY (`perid`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of permission
    -- ----------------------------
    INSERT INTO `permission` VALUES (1, '用户查询', 'person:query');
    INSERT INTO `permission` VALUES (2, '用户添加', 'person:add');
    INSERT INTO `permission` VALUES (3, '用户修改', 'person:update');
    INSERT INTO `permission` VALUES (4, '用户删除', 'person:delete');
    INSERT INTO `permission` VALUES (5, '导出用户', 'person:export');
    
    -- ----------------------------
    -- Table structure for role
    -- ----------------------------
    DROP TABLE IF EXISTS `role`;
    CREATE TABLE `role`  (
      `roleid` int(11) NOT NULL AUTO_INCREMENT,
      `rolename` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      PRIMARY KEY (`roleid`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of role
    -- ----------------------------
    INSERT INTO `role` VALUES (1, '超级管理员');
    INSERT INTO `role` VALUES (2, 'CEO');
    INSERT INTO `role` VALUES (3, '保安');
    
    -- ----------------------------
    -- Table structure for role_permission
    -- ----------------------------
    DROP TABLE IF EXISTS `role_permission`;
    CREATE TABLE `role_permission`  (
      `perid` int(255) NULL DEFAULT NULL,
      `roleid` int(11) NULL DEFAULT NULL
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of role_permission
    -- ----------------------------
    INSERT INTO `role_permission` VALUES (1, 1);
    INSERT INTO `role_permission` VALUES (2, 1);
    INSERT INTO `role_permission` VALUES (3, 1);
    INSERT INTO `role_permission` VALUES (4, 1);
    INSERT INTO `role_permission` VALUES (1, 2);
    INSERT INTO `role_permission` VALUES (2, 2);
    INSERT INTO `role_permission` VALUES (3, 2);
    INSERT INTO `role_permission` VALUES (1, 3);
    INSERT INTO `role_permission` VALUES (5, 3);
    
    -- ----------------------------
    -- Table structure for user
    -- ----------------------------
    DROP TABLE IF EXISTS `user`;
    CREATE TABLE `user`  (
      `userid` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `userpwd` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `sex` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      PRIMARY KEY (`userid`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of user
    -- ----------------------------
    INSERT INTO `user` VALUES (1, 'zhangsan', '639ffb0cbcca39d4fff8348844b1974e', '男', '武汉');
    INSERT INTO `user` VALUES (2, 'lisi', '0d303fa8e2e2ca98555f23a731a58dd9', '女', '北京');
    INSERT INTO `user` VALUES (3, 'wangwu', '473c41db9af5cc0d90e7adfd2b6d9180', '女', '成都');
    
    -- ----------------------------
    -- Table structure for user_role
    -- ----------------------------
    DROP TABLE IF EXISTS `user_role`;
    CREATE TABLE `user_role`  (
      `userid` int(11) NULL DEFAULT NULL,
      `roleid` int(11) NULL DEFAULT NULL
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of user_role
    -- ----------------------------
    INSERT INTO `user_role` VALUES (1, 1);
    INSERT INTO `user_role` VALUES (2, 2);
    INSERT INTO `user_role` VALUES (3, 3);
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    

    shiro的spring配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
    	<!-- 声明凭证匹配器 -->
    	<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
    		<property name="hashAlgorithmName" value="md5"></property>
    		<property name="hashIterations" value="2"></property>
    	</bean>
    
    	<!-- 声明userRealm -->
    	<bean id="userRealm" class="com.sxt.realm.UserRealm">
    		<!-- 注入凭证匹配器 -->
    		<property name="credentialsMatcher" ref="credentialsMatcher"></property>
    	</bean>
    
    	<!-- 配置SecurityManager -->
    	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    		<!-- 注入realm -->
    		<property name="realm" ref="userRealm"></property>	
    	</bean>
    	
    	<!-- 配置shiro的过滤器  这里面的id必须和web.xml里面的配置一样 -->
    	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" >
    		<!-- 注入安全管理器 -->
    		<property name="securityManager" ref="securityManager"></property>
    		<!-- 注入未登陆的跳转页面 默认的是webapp/login.jsp-->
    		<property name="loginUrl" value="/index.jsp"></property>
    		<!-- 注入未授权的访问页面 -->
    		<property name="unauthorizedUrl" value="/unauthorized.jsp"></property>
    		<!-- 配置过滤器链 -->
    		<property name="filterChainDefinitions">
    			<value>
    				<!-- 放行index.jsp -->
    				/index.jsp*=anon  
    				<!-- 放行跳转到登陆页面的路径 -->
    				/login/toLogin*=anon
    				<!-- 放行登陆的请求 -->
    				/login/login*=anon
    				<!-- 设置登出的路径 -->
    				/login/logout*=logout
    				<!-- 设置其它路径全部拦截 -->   
    				/**=authc 
    			</value>
    		</property>
    		
    	</bean>
    
    </beans>
    
    

    其他的配置文件,就不写了,和普通的spring项目差不多,然后创建三个service,三个Mapper文件

       #查询用户名是否存在
     select * from user where username=#{username}
        #根据用户id查询对应的角色
     SELECT t1.* FROM role t1 INNER JOIN `user_role` t2 ON t1.roleid = t2.roleid WHERE t2.userid =#{userid}
     	#根据用户id查询对应的权限
     SELECT t1.* FROM
    	permission t1
    	INNER JOIN `user_role` t2
    	INNER JOIN role_permission t3 ON t2.roleid = t3.roleid
    	AND t1.perid = t3.perid
    WHERE
    	t2.userid =#{userid}
    

    创建ActivierUser

    方便封装

    public class ActivierUser {
    
    	private User user;
    	private List<String> roles;
    	private List<String> permissions;
        
    	public ActivierUser() {
    	}
    	public ActivierUser(User user, List<String> roles, List<String> permissions) {
    		super();
    		this.user = user;
    		this.roles = roles;
    		this.permissions = permissions;
    	}
    	public User getUser() {
    		return user;
    	}
    	public void setUser(User user) {
    		this.user = user;
    	}
    	public List<String> getRoles() {
    		return roles;
    	}
    	public void setRoles(List<String> roles) {
    		this.roles = roles;
    	}
    	public List<String> getPermissions() {
    		return permissions;
    	}
    	public void setPermissions(List<String> permissions) {
    		this.permissions = permissions;
    	}
    
    }
    
    

    创建自定义的UserRealm

    public class UserRealm extends AuthorizingRealm {
    
    	@Autowired
    	private UserService userService;
    	@Autowired
    	private RoleService roleService;
    	@Autowired
    	private PermissionService  permissionService;
    
    	@Override
    	public String getName() {
    		return this.getClass().getSimpleName();
    	}
    
    	/*
    	*
    	* 授权
    	* */
    	@Override
    	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    		ActivierUser activierUser = (ActivierUser) principalCollection.getPrimaryPrincipal();
    
    		List<String> permissions = activierUser.getPermissions();
    		List<String> roles = activierUser.getRoles();
    		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    		if (roles != null && roles.size()>0){
    
    			info.addRoles(roles);
    		}
    		if (permissions != null && permissions.size()>0){
    
    			info.addStringPermissions(permissions);
    		}
    		return info;
    	}
    	/*
    	* 认证
    	* */
    	@Override
    	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    
    		//拿到用户名
    		String username = token.getPrincipal().toString();
    		//查询用户名是否存在
    		User user = userService.queryUserByName(username);
    		if(user == null){
    			return null;
    		}
    		//查询角色和权限
    		List<Role> roleList = roleService.queryRoleList(user.getUserid().toString());
    		ArrayList<String> roles = new ArrayList<>();
    		for (Role role : roleList) {
    			roles.add(role.getRolename());
    		}
    
    		ArrayList<String> permissions = new ArrayList<>();
    
    		List<Permission> permissionList = permissionService.queryPermissionByUserId(user.getUserid().toString());
    		for (Permission permission : permissionList) {
    			permissions.add(permission.getPercode());
    		}
    		//盐
    		ByteSource salt = ByteSource.Util.bytes(user.getUsername() + user.getAddress());
    		ActivierUser activierUser = new ActivierUser(user,roles,permissions);
    		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(activierUser,user.getUserpwd(),salt,this.getName());
    		return info;
    	}
    }
    
    

    Controller层

    LoginController.java

    @RequestMapping("login")
    @Controller
    public class  LoginController {
    
    	/**
    	 * 跳转到登陆页面
    	 */
    	@RequestMapping("toLogin")
    	public String toLogin() {
    		return "login";
    	}
    
    
    	/**
    	 * 做登陆
    	 */
    	@RequestMapping("login")
    	public String login(String username,String pwd,
                            HttpSession session,Model model) throws Exception {
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(username, pwd);
            try {
                subject.login(token);
                ActivierUser activierUser = (ActivierUser) subject.getPrincipal();
                session.setAttribute("user",activierUser.getUser());
                return "redirect:/login/toUserManager.action";
            }catch (IncorrectCredentialsException e) {
                System.err.println("密码不正确");
                model.addAttribute("error", "密码不正确");
            } catch (UnknownAccountException e) {
                System.err.println("用户名不存在");
                model.addAttribute("error", "用户名不存在");
            }
            return "redirect:/login.jsp";
        }
        
    	@RequestMapping("/toUserManager")
        public String toUserManager() {
            return "list";
        }
    }
    
    

    权限控制标签

    <shiro:hasPermission name="person:query">
    		<h1><a href="user/query.action">查询用户</a></h1>
    	</shiro:hasPermission>
    	<shiro:hasPermission name="person:add">
    	<h1><a href="user/add.action">添加用户</a></h1>
    	</shiro:hasPermission>
    	<shiro:hasPermission name="person:update">
    	<h1><a href="user/update.action">修改用户</a></h1>
    	</shiro:hasPermission>
    	<shiro:hasPermission name="person:delete">
    	<h1><a href="user/delete.action">删除用户</a></h1>
    	</shiro:hasPermission>
    	<shiro:hasPermission name="person:export">
    	<h1><a href="user/export.action">导出用户</a></h1>
    	</shiro:hasPermission>
    
  • 相关阅读:
    Centos 7.9 部署可道云
    shell简单检查URL
    TIME_WAIT和CLOSE_WAIT状态过多的分析与解决
    win10 关闭自动更新
    Python3 按backspace问题 ^H
    CentOS7设置笔记本合盖不休眠
    centos7 /boot/分区处理
    if __name__ == '__main__'
    在Linux中了解TCP包装器(/etc/hosts.allow&/etc/hosts.deny)
    华为路由器端口映射
  • 原文地址:https://www.cnblogs.com/blackmlik/p/12767203.html
Copyright © 2020-2023  润新知