zoukankan      html  css  js  c++  java
  • shiro学习(五、springboot+shiro+mybatis+thymeleaf)


    入门shiro(感觉成功了)首先感谢狂神,然后我就一本正经的复制代码了

    项目结构

    运行效果

     

     

     数据库


    <dependencies>
            <!-- thymeleaf-shiro整合包 -->
            <dependency>
                <groupId>com.github.theborakompanioni</groupId>
                <artifactId>thymeleaf-extras-shiro</artifactId>
                <version>2.0.0</version>
            </dependency>
    
            <!--快速生成pojo的方法有关的lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.10</version>
            </dependency>
            <!-- 引入 myBatis,这是 MyBatis官方提供的适配 Spring Boot 的,而不是Spring Boot自己的-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.0</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.15</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.12</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/log4j/log4j -->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>
            <!--
                Subject 用户,
                SecurityManager 管理所有用户,
                Realm 连接数据,需要自定义
            -->
            <!--shiro整合spring的包-->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.4.0</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!--thymeleaf模板-->
            <dependency>
                <groupId>org.thymeleaf</groupId>
                <artifactId>thymeleaf-spring5</artifactId>
            </dependency>
            <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-java8time</artifactId>
            </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>
    ShiroConfig.class
     
    @Configuration
    public class ShiroConfig {
        //ShiroFilterFactoryBean   第三步
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            //设置安全管理器
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            /*
                添加shiro的内置过滤器
                anon:无须认证就可以访问
                authc:必须认证了才可以访问
                perms:拥有对某个资源的权限才能访问
                role:拥有某个角色才可以访问
             */
            Map<String, String> filterMap = new LinkedHashMap();
    //        filterMap.put("/user/add","authc");
    //        filterMap.put("/user/update","authc");
            filterMap.put("/user/add","perms[user:add]");
            filterMap.put("/user/update","perms[user:update]");
            filterMap.put("/user/*","authc");
    
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
            //设置跳转到登录页面
            shiroFilterFactoryBean.setLoginUrl("/toLogin");
            //设置到未授权页面
            shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");
    
    
            return shiroFilterFactoryBean;
        }
    
        //DefaultWebSecurityManager  第二步
        @Bean(name = "securityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
            DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
            //关联realm
            securityManager.setRealm(userRealm);
            return securityManager;
        }
        //创建realm 域对象,需要自定义   第一步
        @Bean(name = "userRealm")
        public UserRealm getUserRealm(){
            return new UserRealm();
        }
    
        //shiro 整合thymeleaf
        @Bean
        public ShiroDialect getShiroDialect(){
            return new ShiroDialect();
        }
    }

     UserRealm.class

    public class UserRealm extends AuthorizingRealm {
        @Autowired
        private UserService userService;
        @Override   //授权
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            System.out.println("-----授权了-----AuthorizationInfo");
            SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
    //        info.addStringPermission("user:add");
            //从数据库查权限
            Subject subject = SecurityUtils.getSubject();
            User currentUser = (User) subject.getPrincipal();//其实就是拿认证成功的时候的那个user
            info.addStringPermission(currentUser.getPerms());
    
            return info;
        }
    
        @Override   //认证
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("-----认证了-----AuthenticationInfo");
            UsernamePasswordToken userToken = (UsernamePasswordToken) token;
            //用户名,密码去数据库取
            User user = userService.queryUserByUsername(userToken.getUsername());
            if (user==null){  //没有这个人
                return null;  //其实就是抛出UnknownAccountException异常
            }
            //之后密码认证,shiro   它自己会做
            SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(user,user.getPassword(),"");
            Subject currentSubject = SecurityUtils.getSubject();
            Session session = currentSubject.getSession();
            session.setAttribute("loginUser",user);
            return info;
        }
    }

     MyController.class

    @Controller
    public class MyController {
        @RequestMapping({"/","/index"})
        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";
        }
        @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";
            }
        }
        //没授权
        @RequestMapping("/noauth")
        @ResponseBody
        public String unauthorized(){
            return "没经授权无法进入";
        }
        //退出
        @RequestMapping("/logout")
        public String logout(){
            Subject currentUser = SecurityUtils.getSubject();
            currentUser.logout();
            System.out.println("退出了");
            return "login";
        }
    }

    User.class

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private int id;
        private String username;
        private String password;
        private String perms;
    }

    UserMapper.class

    @Mapper
    @Repository
    public interface UserMapper {
        public User queryUserByUsername(String username);
    }

    UserService.class

    public interface UserService {
        public User queryUserByUsername(String username);
    }

    UserServiceImpl.class

    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
        private UserMapper userMapper;
        @Override
        public User queryUserByUsername(String username) {
            return userMapper.queryUserByUsername(username);
        }
    }

    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.kuang.mapper.UserMapper">
        <select id="queryUserByUsername" parameterType="String" resultType="User">
            select * from user where username=#{username}
        </select>
    </mapper>

    application.properties

    mybatis.type-aliases-package=com.kuang.pojo
    mybatis.mapper-locations=classpath:mapper/*.xml

    application.yml

    spring:
      datasource:
        username: root
        password: root
        #?serverTimezone=UTC解决时区的报错
        url: jdbc:mysql://localhost:3306/shiro?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
        driver-class-name: com.mysql.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
    
        #Spring Boot 默认是不注入这些属性值的,需要自己绑定
        #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 地址: https://mvnrepository.com/artifact/log4j/log4j
        filters: stat,wall,log4j
        maxPoolPreparedStatementPerConnectionSize: 20
        useGlobalDataSourceStat: true
        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

    index.html

    <!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>shiro</title>
    </head>
    <body>
        <h1>首页</h1>
        <div th:if="${session.loginUser==null}">
            <a th:href="@{/toLogin}">登录</a>
        </div>
        <p th:text="${msg}"></p>
        <hr/>
    
        <div shiro:hasPermission="user:add">
            <a th:href="@{/user/add}">add</a>
        </div>
        <div shiro:hasPermission="user:update">
            <a th:href="@{/user/update}">update</a>
        </div>
        <div th:if="${session.loginUser}">
            <p><a th:href="@{/logout}">退出</a></p>
        </div>
    </body>
    </html>

    login.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>shiro登录</title>
    </head>
    <body>
    <div>
        <p th:text="${msg}" style="color: red"></p>
        <form method="get" th:action="@{/login}">
            <p>用户名:<input type="text" name="username"></p>
            <p>密  码:<input type="text" name="password"></p>
            <p><input type="submit" value="登录"></p>
        </form>
    </div>
    </body>
    </html>

    add.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>增加</title>
    </head>
    <body>
    <h2>add</h2>
    </body>
    </html>

    update.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>更新</title>
    </head>
    <body>
    <h2>update</h2>
    </body>
    </html>

    总结一下:首先搭建好环境是关键:springboot--》MVC--》mybatis,然后进行shiro的过滤,认证,授权。。。

    主要理解好

    ShiroConfig
    ShiroFilterFactoryBean
    setFilterChainDefinitionMap()
    DefaultWebSecurityManager
    自定义域 UserRealm 继承 AuthorizingRealm
    AuthorizationInfo      SimpleAuthenticationInfo
    AuthenticationInfo    SimpleAuthorizationInfo
    UsernamePasswordToken
    SecurityUtils
    getSession()
    getSubject()
    getPrincipal()
    AuthenticationToken

    。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  • 相关阅读:
    4270. 【NOIP2015模拟10.27】魔道研究
    4269. 【NOIP2015模拟10.27】挑竹签
    NOIP2015模拟10.28B组
    JZOI5257. 小X的佛光
    4260. 最大子矩阵 (Standard IO)
    1010. 【CQOI2009】叶子的颜色
    【NOIP2015模拟10.22】最小代价
    JZOI 距离 (Standard IO) 题解
    统计和 luogu P2068 树状数组和线段树练手
    2020.7.15模拟赛
  • 原文地址:https://www.cnblogs.com/shiguanzui/p/11913730.html
Copyright © 2011-2022 走看看