zoukankan      html  css  js  c++  java
  • springboot_shiro

    1、Shiro简介

    1.1、什么是shiro?


    1.2、shiro功能?

    image

    • Authentication: 身份认证、登录,验证用户是不是拥有相应的身份;
    • Authorization: 授权,即权限验证,验证某个已认证用户是否拥有某个权限,即判断用户是否进行什么操作,如:验证某个用户是否拥有某个角色,或者细粒度的验证某个用户对某个资源是否具有某个权限!
    • Session Management: 会话管理,即用户登录就是第一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通的JavaSE环境,也可以是Web环境;
    • Cryptography: 加密,保护数据的安全性,如密码加密存储到数据库中,而不是明文存储;
    • Web Support: Web支持,可以非常容易的集成到Web环境中;
    • Caching: 缓存,比如用户登录后,其用户信息,拥有的角色、权限不必每次去查,这样可以提高效率
    • Concurrency: Shiro支持多线程应用的并发验证,即,如在一个线程中开启另一个线程,能把权限自动的传播过去
    • Testing: 提供测试
    • Run As: 允许一个用户假装另一个用户的身份去访问
    • Remember Me: 记住我,这是非常常见的功能,即一次登录后,下次再来的话就不用登录

    2、Shiro简单使用


    1.导入依赖
    2.配置文件
    3.HelloWorld

    SpringSecurity~都有

    Subject currentUser = SecurityUtils.getSubject();
    Session session = currentUser.getSession();
    currentUser.isAuthenticated()
    currentUser.getPrincipal()
    currentUser.hasRole("schwartz")
    currentUser.isPermitted("lightsaber:wield")
    currentUser.logout();
    

    3、Springboot-Shiro整合

    • 依赖
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.7.1</version>
    </dependency>
    
    • 自定义Realm类
    //自定义的UserRealm
    public class UserRealm extends AuthorizingRealm {
        //授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            System.out.println("授权:doGetAuthorizationInfo");
            return null;
        }
    
        //认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            System.out.println("认证:doGetAuthenticationInfo");
            return null;
        }
    }
    
    • 创建config(自定义ShiroConfig)
    import java.util.LinkedHashMap;
    
    @Configuration
    public class ShiroConfig {
    
        //第三步:ShiroFilterFactoryBean
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
            ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
            //关联 DefaultWebSecurityManager,设置安全管理器
            bean.setSecurityManager(defaultWebSecurityManager);
            //添加shiro的内置过滤器
            /*
             * anon:无需认证就可以访问
             * authc:必须认证了才能访问
             * user:必须拥有“记住我”功能才能使用
             * perms:拥有对某个资源的权限才能访问
             * role:拥有某个角色权限才能访问
             * */
            
            return bean;
        }
    
        //第二步:DefaultWebSecurityManager
        @Bean
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            //关联realm
            securityManager.setRealm(userRealm);
            return securityManager;
        }
    
        //第一步:创建realm对象
        @Bean
        public UserRealm userRealm() {
            return new UserRealm();
        }
    }
    

    4、Springboot-Shiro进行拦截

    在自定义ShiroConfig中:

    //第三步:ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //关联 DefaultWebSecurityManager,设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);
        //添加shiro的内置过滤器
        /*
         * anon:无需认证就可以访问
         * authc:必须认证了才能访问
         * user:必须拥有“记住我”功能才能使用
         * perms:拥有对某个资源的权限才能访问
         * role:拥有某个角色权限才能访问
         * */
    //        Map<String,String> filterMap = new HashMap<>();
    //        filterMap.put("/user/add","authc");
    //        filterMap.put("/user/update","authc");
        //通配符拦截
        Map<String,String> filterMap = new HashMap<>();
        filterMap.put("/user/*","authc");
        bean.setFilterChainDefinitionMap(filterMap);
    
        //设置登录的请求
        bean.setLoginUrl("/toLogin");
        return bean;
    }
    

    自定义MyController的页面跳转

    @Controller
    public class MyController {
    
        @RequestMapping({"/","/index","/index.html"})
        public String toIndex(Model model){
            model.addAttribute("msg","hello,Shiro");
            return "index";
        }
    
        @RequestMapping("/user/add")
        public String add(){
            return "/user/add";
        }
    
        @RequestMapping("/user/update")
        public String update(){
            return "/user/update";
        }
    
        @RequestMapping("/toLogin")
        public String toLogin(){
            return "login";
        }
    }
    

    静态资源目录:
    image

    3、Springboot-Shiro用户认证

    • 编写一个简单的登录页面
    <p th:text="${msg}" style="color: red"></p>
    <form th:action="@{/login}">
        <p>用户名<input type="text" name="username"/></p>
        <p>密码<input type="password" name="password"/></p>
        <button type="submit">登录</button>
    </form>
    
    • MyController中进行逻辑
    @RequestMapping("/login")
    public String login(String username, String password, Model model){
        //获取当前的用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户的登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try{
            //登录成功
            subject.login(token);   //执行登录的方法
            return "index";
        }catch (UnknownAccountException e){
            model.addAttribute("msg","用户名错误");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("msg","密码错误");
            return "login";
        }
    }
    
    • 在自定义的UserRealm进行用户名和密码的匹配验证
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("认证:doGetAuthenticationInfo");
    
        //用户名,密码,数据库中取
        String name = "root";
        String password = "123456";
    
        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
        if (!userToken.getUsername().equals(name)){
            return null;    //抛出异常  UnknownAccountException
        }
        //密码认证
        return new SimpleAuthenticationInfo("",password,"");
    }
    

    image
    image

    3、Springboot-Shiro整合Mybatis

    • 导入相关依赖
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.4</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
    <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.6</version>
    </dependency>
    
    • pojo层
      image
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private int id;
        private String userName;
        private String passWord;
        private String realName;
    }
    
    • yaml配置文件
    spring:
      datasource:
        username: root
        password: 123456
        #    url: jdbc:mysql://localhost:3306/springboot_mybatis?serverTimezone=GMT&useUnicode=true&characterEncoding=utf8&useSSL=false
        #    失去问题
        url: jdbc:mysql://localhost:3306/springboot_mybatis?serverTimezone=GMT
        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
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 1 FROM DUAL
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
    
        #配置监控统计拦截器filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
        #如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
        #则导入log4j依赖即可,Maven
        filters: stat,wall,log4j
        maxPoolPreparedStatementPerConnectionSize: 20
        userGlobalDataSourceStat: true
        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
    
    • UserMapper接口
    @Mapper
    @Repository
    public interface UserMapper {
    
        public User queryUserByName(String name);
    }
    
    • service层

      • UserService接口
      public interface UserService {
          public User queryUserByName(String name);
      }
      
      • UserService接口实现
      @Service
      public class UserServiceImpl implements UserService{
      
          @Autowired
          UserMapper userMapper;
      
          @Override
          public User queryUserByName(String name) {
              return userMapper.queryUserByName(name);
          }
      }
      
    • UserMapper.xml
      image

    <?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="edu.dj.mapper.UserMapper">
    	<select id="queryUserByName" parameterType="String" resultType="User">
    		select * from springboot_mybatis.user where userName = #{name}
    	</select>
    </mapper>
    
    • application.properties配置文件绑定
    # 绑定数据
    mybatis.type-aliases-package=edu.dj.pojo
    mybatis.mapper-locations=classpath:mapper/*.xml
    
    • UserRealm中数据认证
      image
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("认证:doGetAuthenticationInfo");
    
        //用户名,密码,数据库中取
        //String name = "root";
        //String password = "123456";
    
        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
        //连接真实数据库
        User user = userService.queryUserByName(userToken.getUsername());
    
        if (user == null){  //没有这个人
            return null;       //UnknownAccountException
        }
    
        //密码认证,shiro做
        return new SimpleAuthenticationInfo("",user.getPassWord(),"");
    }
    

    5、Springboot-Shiro进行授权

    • 添加认证
      getShiroFilterFactoryBean中添加,对/user/add/user/update的路径进行控制
    //授权
    filterMap.put("/user/add", "perms[user:add]");
    filterMap.put("/user/update", "perms[user:update]");
    
    • 自定义未经授权的跳转页面
    //设置未经授权的页面跳转
    bean.setUnauthorizedUrl("/unauthorized");
    
    @RequestMapping("/unauthorized")
    @ResponseBody
    public String unauthorized(){
        return "未经授权";
    }
    
    • 根据数据库的真实数据进行授权
      image
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("授权:doGetAuthorizationInfo");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //info.addStringPermission("user:add");
        //拿到当前用户的权限
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User) subject.getPrincipal();
        System.out.println(subject.getPrincipal());
        //设置当前用户的权限
        info.addStringPermission(currentUser.getPerms());
        return info;
    }
    

    getPrincipal()从数据库中获得基本数据:

    User(id=3, userName=DJ, passWord=123456, realName=DingJie, perms=user:update)
    

    6、shiro整合thymeleaf

    • 依赖
    <dependency>
      <groupId>com.github.theborakompanioni</groupId>
      <artifactId>thymeleaf-extras-shiro</artifactId>
      <version>2.0.0</version>
    </dependency>
    
    • 在自定义的ShiroConfig中加入ShiroDialect
    //整合ShiroDialect:用于整合shiro和thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
    
  • 相关阅读:
    Docker制作tomcat镜像,发布镜像
    DockerFile
    Docker容器数据卷
    Docker镜像
    Docker部署nginx,tomcat,es,可视化
    java 使用 poi 更新 ppt 中图表的数据
    require.js与IDEA的配合
    html中require.config 缓存问题
    mongodb 更新嵌套数组的值
    java poi ppt 接口的基本操作
  • 原文地址:https://www.cnblogs.com/jsit-dj-it/p/15014772.html
Copyright © 2011-2022 走看看