zoukankan      html  css  js  c++  java
  • SpringBoot整合Shiro (二)

    Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。相比较Spring Security,shiro有小巧、简单、易上手等的优点。所以很多框架都在使用shiro。

    Shiro包含了三个核心组件:Subject, SecurityManager 和 Realms。

    • Subject 代表了当前用户的安全操作。
    • SecurityManager 则管理所有用户的安全操作。它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
    • Realm 充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。

    下面通过示例来演示SpringBoot如何来整合Shiro

    1、创建项目ShiroDemo 
    这里写图片描述

    2、配置POM,添加SpringBoot以及Shiro依赖

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
      </properties>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.3.5.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
      <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.25</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>0.2.23</version>
        </dependency>
        <!-- shiro权限控制框架 -->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.3.2</version>
            </dependency>
      </dependencies>

    3、编写MyShiroRealm类,实现AuthorizingRealm接口

    public class MyShiroRealm extends AuthorizingRealm {
    
        /**
         * 授权用户权限
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(
                PrincipalCollection principals) {
            //获取用户
            User user = (User)SecurityUtils.getSubject().getPrincipal();
            SimpleAuthorizationInfo info =  new SimpleAuthorizationInfo();
            //获取用户角色
            Set<String> roleSet = new HashSet<String>();
            roleSet.add("100002");
            info.setRoles(roleSet);
    
            //获取用户权限
            Set<String> permissionSet = new HashSet<String>();
            permissionSet.add("权限添加");
            permissionSet.add("权限删除");
            info.setStringPermissions(permissionSet);
    
    
            return info;
        }
    
        /**
         * 验证用户身份
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(
                AuthenticationToken authcToken) throws AuthenticationException {
    
            UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
            String username = token.getUsername();
            String password = String.valueOf(token.getPassword());
    
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("nickname", username);
            //密码进行加密处理  明文为  password+name
            String paw = password+username;
            String pawDES = MyDES.encryptBasedDes(paw);
            map.put("pswd", pawDES);
    
            User user = new User();
            user.setId("112222");
            user.setUsername(username);
            user.setPassword(pawDES);
    
    
            return new SimpleAuthenticationInfo(user, password, getName());
        }
    
    }

    4、实现ShiroConfiguration

    @Configuration
    public class ShiroConfiguration {
    
        /**
         * ShiroFilterFactoryBean 处理拦截资源文件问题。
         * 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在
         * 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
         *
         * Filter Chain定义说明 1、一个URL可以配置多个Filter,使用逗号分隔 2、当设置多个过滤器时,全部验证通过,才视为通过
         * 3、部分过滤器可指定参数,如perms,roles
         *
         */
        @Bean
        public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    
            // 必须设置 SecurityManager
            shiroFilterFactoryBean.setSecurityManager(securityManager);
    
            // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
            shiroFilterFactoryBean.setLoginUrl("/login");
            // 登录成功后要跳转的链接
            shiroFilterFactoryBean.setSuccessUrl("/index");
            // 未授权界面;
            shiroFilterFactoryBean.setUnauthorizedUrl("/403");
    
            //自定义拦截器
            Map<String, Filter> filtersMap = new LinkedHashMap<String, Filter>();
            //限制同一帐号同时在线的个数。
            //filtersMap.put("kickout", kickoutSessionControlFilter());
            shiroFilterFactoryBean.setFilters(filtersMap);
    
            // 权限控制map.
            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
            // 配置不会被拦截的链接 顺序判断
            // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
            // 从数据库获取动态的权限
            // filterChainDefinitionMap.put("/add", "perms[权限添加]");
            // <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
            // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
            //logout这个拦截器是shiro已经实现好了的。
            // 从数据库获取
            /*List<SysPermissionInit> list = sysPermissionInitService.selectAll();
    
            for (SysPermissionInit sysPermissionInit : list) {
                filterChainDefinitionMap.put(sysPermissionInit.getUrl(),
                        sysPermissionInit.getPermissionInit());
            }*/
    
            shiroFilterFactoryBean
                    .setFilterChainDefinitionMap(filterChainDefinitionMap);
            return shiroFilterFactoryBean;
        }
    
        @Bean
        public SecurityManager securityManager() {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            // 设置realm.
            securityManager.setRealm(myShiroRealm());
            // 自定义缓存实现 使用redis
            //securityManager.setCacheManager(cacheManager());
            // 自定义session管理 使用redis
            //securityManager.setSessionManager(sessionManager());
            //注入记住我管理器;
            securityManager.setRememberMeManager(rememberMeManager());
            return securityManager;
        }
    
        public MyShiroRealm myShiroRealm(){
            return new MyShiroRealm();
        }
    
        /**
         * cookie对象;
         * @return
         */
        public SimpleCookie rememberMeCookie(){
           //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
           SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
           //<!-- 记住我cookie生效时间30天 ,单位秒;-->
           simpleCookie.setMaxAge(2592000);
           return simpleCookie;
        }
    
        /**
         * cookie管理对象;记住我功能
         * @return
         */
        public CookieRememberMeManager rememberMeManager(){
           CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
           cookieRememberMeManager.setCookie(rememberMeCookie());
           //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
           cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));
           return cookieRememberMeManager;
        }
    
    }

    5、编写LoginController类测试Shiro

    @RestController
    public class LoginController {
    
        @RequestMapping(value="/login",method=RequestMethod.POST)
        public String login(String username, String password,String vcode,Boolean rememberMe){
            System.out.println(username);
            UsernamePasswordToken token = new UsernamePasswordToken(username, password,rememberMe);
            SecurityUtils.getSubject().login(token);
    
            return "loginSuccess";
        }
    
        @RequestMapping(value="/index",method=RequestMethod.GET)
        public String home(){
            Subject subject = SecurityUtils.getSubject();
            User principal = (User)subject.getPrincipal();
    
            return "Home";
        }
    
    }

  • 相关阅读:
    最新 蓝鲸人java校招面经 (含整理过的面试题大全)
    最新 上海轻轻java校招面经 (含整理过的面试题大全)
    最新 苏州朗动java校招面经 (含整理过的面试题大全)
    最新 医渡云java校招面经 (含整理过的面试题大全)
    变量的自动类型转换和强制类型转换(day01_10)
    java的数据类型(day01_09)
    常用的dos命令操作(day01_03)
    1.镜像-虚拟光驱-光驱
    Spring基于配置文件的方式来配置AOP
    Spring-AOP(切面的优先级&&&重用切点表达式)
  • 原文地址:https://www.cnblogs.com/ncy1/p/9478865.html
Copyright © 2011-2022 走看看