zoukankan      html  css  js  c++  java
  • 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 @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
    /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
    /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
    /*!40111 SET @OLD_SQL_NOTES=@@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=@OLD_SQL_MODE */;
    /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
    /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
    /*!40111 SET SQL_NOTES=@OLD_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());
                    }
                   //添加资源的授权字符串 这块欣慰shiroConfig配置文件中添加了需要授权的过滤器,所有需要保持一致
                   //这块的需要与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";
        }
    }
    
    小蘑菇
  • 相关阅读:
    使用批处理文件(.bat)启动Java程序
    VARCHAR2(%n)和VARCHAR2(%n char)区别
    Truncate Table
    Ext4之杂七杂八
    Oracle导表
    关于hibernate的session.createSQLQuery(sql)直接调用底层SQL后,返回结果集的问题
    Ext4真是难(展开表格行,显示图表)
    Hadoop学习笔记【入门】
    魅蓝note 做Android真机调试
    11-java学习笔记-反射
  • 原文地址:https://www.cnblogs.com/wang66a/p/12069307.html
Copyright © 2011-2022 走看看