• springboot03-shiro


    shiro

    官网:https://shiro.apache.org/

    使用shiro需配置如下几个步骤

    //获取当前的用户对象 Session
    Subject currentUser = SecurityUtils.getSubject();
    //判断当前的用户是否被认证~
     currentUser.isAuthenticated()
     currentUser.getPrincipal()
     //test a role:
     currentUser.hasRole("schwartz")
     currentUser.isPermitted("winnebago:drive:eagle5")
     currentUser.logout();
    
    

    案例:

    springboot整合shiro-mybatis

    ​ 1.导入jar包

    <dependencies>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
            <dependency>
                <groupId>org.thymeleaf</groupId>
                <artifactId>thymeleaf-spring5</artifactId>
            </dependency>
            <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-java8time</artifactId>
                <version></version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.5.3</version>
            </dependency>
    
            <dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    			<exclusions>
    				<exclusion>
    					<groupId>org.junit.vintage</groupId>
    					<artifactId>junit-vintage-engine</artifactId>
    				</exclusion>
    			</exclusions>
    		</dependency>
    	</dependencies>
    
    

    ​ 2.编写shiro配置类

    ​ ShiroConfig配置

    package com.mjh.config;
    
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    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;
    
    
    @Configuration
    public class ShiroConfig {
        private static final Logger log = LoggerFactory.getLogger(ShiroFilterFactoryBean.class);
        //ShiroFilterFactoryBean
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    
            // 必须设置 SecurityManager
            shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
    
            /**
             * 添加shiro的内置过滤器
                 * anon:无需认证可以访问
                 * authc:必须认证了才能访问
                 * user:必须拥有记住我功能才能访问
                 * perms:拥有对某资源的权限才能访问
                 * roles:拥有某个角色权限才能访问
             */
            // 拦截器.
            Map<String, String>  map = new LinkedHashMap<String, String>();
    
            map.put("/logout", "logout");
           // map.put("/user/add", "authc");
            map.put("/user/*", "authc");
    
            // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
            shiroFilterFactoryBean.setLoginUrl("/login");
            // 登录成功后要跳转的链接
           // shiroFilterFactoryBean.setSuccessUrl("/index");
            // 未授权界面;
            //shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
    
            shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
            return shiroFilterFactoryBean;
        }
    
        //DefaultWebSecurityManager:2
        @Bean(name = "securityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm)  {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            // 关联设置Userrealm.
            securityManager.setRealm(userRealm);
    
            return securityManager;
        }
    
    
        /**
         * 创建一个realm对象,需要自定义类
         *
         * @return
         */
        @Bean
        public UserRealm userRealm(){
    
            return new UserRealm();
        }
    
    
    }
    
    

    UserRealm配置

    package com.mjh.config;
    
    import com.mjh.pojo.User;
    import com.mjh.service.UserService;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.springframework.beans.factory.annotation.Autowired;
    
    public class UserRealm extends AuthorizingRealm {
        @Autowired
       UserService userService;
    //授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            System.out.println("执行了----->授权doGetAuthorizationInfo");
            return null;
        }
    //认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("执行了------>认证doGetAuthenticationInfo");
    
    
            UsernamePasswordToken usernameToken=(UsernamePasswordToken) token;
          //注入真实的数据
            User user = userService.queryListUser(usernameToken.getUsername());
            if(user==null){
                return null;//UnknownAccountException
            }
            //密码认证 shiro做
            return new SimpleAuthenticationInfo("",user.getPassword(),"" );
        }
    
    
    }
    
    

    3.编写配置文件config文件

    spring:
      datasource:
        username: root
        password: 123456
        url: jdbc:mysql://localhost:3306/17java?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
        driver-class-name: com.mysql.cj.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
    
    #springboot 默认不注入这些属性值,需要自己设置
    #druid  数据源专有配置
        initialSize: 5
        minIdle: 5
        maxActive: 20
        maxWait: 60000
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMills: 300000
        testWhileIdle: true
        testOnBorrow: false
        validationQuery: SELECT 1 FROM DUAL
        poolPreparedStatements: true
    
        #配置监控器拦截的filters,stat:监控统计,log4j:日志记录、wall:防御sql注入
        #如果允许时报错  java.lang.ClassNotFoundException:org.apache.log4j.Priority
        #侧导入log4j依赖即可,maven 地址:https:https://mvnrepository.com/
        filters: stat,wall,log4j
        maxOpenPreparedStatementsPerConnectionSize: 20
        useGlobalDataSourceStat: true
        connectionProperties: druid.stat.mergeSql=true,druid.stat.slowSqlMillis=500
    
    

    4.编写mybatis的配置 pom.xm文件

    首先要先引入依赖包,为了编写pojo文件方便,也导入一下lombok

    <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.1</version>
            </dependncy>
     <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>   
    
    mybatis.type-aliases-package=com.mjh.pojo
    mybatis.mapper-locations=classpath:mapper/*.xml
    
    

    5.之后根据配置文件写pojo,dao层和mapper.xml层

    pojo层
        @Data
        @AllArgsConstructor
        @NoArgsConstructor
        public class User {
            private int id;
            private String name;
            private String password;
        }
    
    
    dao层
        
        package com.mjh.dao;
    
    import com.mjh.pojo.User;
    import org.apache.ibatis.annotations.Mapper;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    
    @Mapper
    @Repository
    public interface UserDao {
       public User queryListUser(String name);
    }
    
    
    UserMapper.xml
       <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.mjh.dao.UserDao">
        <select id="queryUserList" parameterType="String" resultType="User">
            select * from user  where name=#{name}
        </select>
     
        
    

    接下来是service层

    package com.mjh.service;
    
    import com.mjh.pojo.User;
    
    public interface UserService {
        public User queryListUser(String name);
    }
    
    package com.mjh.service;
    
    import com.mjh.dao.UserDao;
    import com.mjh.pojo.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
        private UserDao userDao;
        @Override
        public User queryListUser(String name) {
            return userDao.queryListUser(name);
        }
    }
    

    以上是通过shiro认证的事例,下面在补充一下授权

    在controller层添加方法

     @RequestMapping("/unauthorized")
        @ResponseBody
        public String unauthorized(){
            return "未经授权无法访问此页面";
        }
    }
    

    要使授权生效,就要配置shiroConfig,所以在shiroConfig的getShiroFilterFactoryBean()方法里添加代码

    //授权,正常的情况下,没有授权会跳到不授权页面上
    map.put("/user/add","perms[user:add]"); map.put("/user/update","perms[user:update]"/授权,正常的情况下,没有授权会跳到不授权页面上
    map.put("/user/add","perms[user:add]"); map.put("/user/update","perms[user:update]");
    // 未授权界面;
      shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
    

    我们还可以把权限给用户,把user:add这个权限给用户,在Realm里的doGetAuthorizationInfo方法里添加代码,这样我们刚才给add功能里添加授权方法,现在也可以访问了;

    SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
    info.addStringPermission("user:add");
    return info;
    

    但是这种方式有一个缺点,我们数据库里的用户都可以有这个权限,我们的思路是要对每一个用户都有不同的权限,这样做完全是不行的,就是我们把它写死了,它权限应该在数据库里实现,所以一般数据表里都具有权限这一个perms属性,之后赋予用户不同的权限;之后只需要在realm中添加如下代码即可

        //拿到当前用户权限
        Subject subject= SecurityUtils.getSubject();
        User currentUser= (User) subject.getPrincipal();//拿到User对象
    
        //设置当前用户权限
        info.addStringPermission(currentUser.getPerms());
        return info;
    }
    
    //之后的密码认证变为如下
         //密码认证 shiro做
    return new SimpleAuthenticationInfo(user,user.getPassword(),"" ); 
    

    shiro整合thymeleaf

    1.导入jar包

    <!--shiro-thymeleaf整合-->
            <dependency>
                <groupId>com.github.theborakompanioni</groupId>
                <artifactId>thymeleaf-extras-shiro</artifactId>
                <version>2.0.0</version>
            </dependency>
    

    2.在shiro配置文件中注入整合thymeleaf的shiro方法

    //整合shiroDialect:用来整合shiro thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
    

    3.给前端使用shiro——就是给由于这个权限的用户只显示相应的权限,没有权限访问的功能不显示,还有引入头文件

    <!DOCTYPE html>
    <html lang="en"  xmlns:th="http://www.thymeleaf.org"
    xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <p th:text="${msg}"></p>
    <div shiro:hasPermission="user:add">
        <a th:href="@{/user/add}" >add</a>
    </div>
    <div shiro:hasPermission="user:add">
        <a  th:href="@{/user/update}">update</a>
    </div>
        <a th:href="@{/logout}" >logout</a>
    </body>
    </html>
    

    4.之后还要从session里判断用户是否登录,否则显示登录链接

    先在Realm配置文件中配置session来获取当前用户登录信息

            Subject currentSubject=SecurityUtils.getSubject();
            Session session=currentSubject.getSession();
            session.setAttribute("loginUser",user);
    
    
  • 相关阅读:
    Android资源列表
    GTD资源列表[070826更新] [GTD]
    Table显示滚动条
    html语言中的meta元素
    GridView分页的实现
    图解CSS的padding,margin,border属性
    javascript moveTo() 函数
    IE6 中的最大最小寬度和高度 css 高度 控制(兼容版本)
    enableEventValidation
    window.resizeTo()和window.open()
  • 原文地址:https://www.cnblogs.com/mjjh/p/13274698.html
Copyright © 2020-2023  润新知