springboot+mybatis+shiro的简单应用

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。三个核心组件:Subject, SecurityManager 和 Realms.
Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account) 或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
SecurityManager:它是Shiro框架的核心,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。

  • 1.导入依赖

    <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>
            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
            <!--thymeleaf-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
    
            <!-- druid数据源 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.2.6</version>
            </dependency>
            <!--mysql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <!-- mybatis -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.2.0</version>
            </dependency>
            <!--log4j-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>
    
            <!--shiro-->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring-boot-web-starter</artifactId>
                <version>1.7.1</version>
            </dependency>
    
            <!-- thymeleaf-extras-shiro -->
            <dependency>
                <groupId>com.github.theborakompanioni</groupId>
                <artifactId>thymeleaf-extras-shiro</artifactId>
                <version>2.0.0</version>
            </dependency>
    
        </dependencies>
    
  • 2.application.yaml配置文件

    spring.datasource.username: root
    spring.datasource.password: 123456
    spring.datasource.url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    spring.datasource.driver-class-name: com.mysql.cj.jdbc.Driver
    spring.datasource.type: com.alibaba.druid.pool.DruidDataSource
    
    #druid数据源配置
    spring.datasource.filters: stat,wall,log4j
    spring.datasource.maxPoolPreparedStatementPerConnectionSize: 20
    spring.datasource.useGlobalDataSourceStat: true
    spring.datasource.connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMills=500
    
    # mybatis配置
    mybatis.type-aliases-package: com.lv.pojo
    mybatis.mapper-locations: classpath:mybatis/mapper/*.xml
    
    
    spring.mvc.format.Date: yyyy-MM-dd
    
  • 3.pojo+mapper+service

    pojo:

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private Integer id;
        private String name;
        private String pwd;
        private String perms;  //权限
    }
    

    mapper:

    @Repository
    @Mapper
    public interface UserMapper {
    
        public User queryByName(@Param("name") String name);
    }
    

    UserMapper.xml(resource/mybatis/mapper)

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.lv.mapper.UserMapper">
    
        <!--按名字查询-->
        <select id="queryByName" resultType="User">
            select * from user where name=#{name};
        </select>
    </mapper>
    

    service:

    public interface UserService {
        public User queryByName(String name);
    }
    
    @Service("userServiceImpl")
    public class UserServiceImpl implements UserService{
        @Autowired
        private UserMapper userMapper;
    
        @Override
        public User queryByName(String name) {
            return userMapper.queryByName(name);
        }
    }
    
  • 4.shiro配置类

    UserRealm.java:

    //自定义UserRealm,需继承AuthorizingRealm
    public class UserRealm extends AuthorizingRealm {
    
        @Autowired
        @Qualifier("userServiceImpl")
        private UserServiceImpl userService;
    
        //授权
        @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();
            info.addStringPermission(currentUser.getPerms());
    
            return info;
        }
    
        //认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("执行了=>认证doGetAuthorizationInfo");
    
            //连接数据库
            UsernamePasswordToken userToken = (UsernamePasswordToken) token;
            //用户名验证
            User user = userService.queryByName(userToken.getUsername());
            System.out.println("user===>"+user);
    
            if (user==null){  //没有此人
                return null; //抛出UnknownAccountException异常
            }
            Subject currentSubject = SecurityUtils.getSubject();
            Session session = currentSubject.getSession();
            session.setAttribute("loginUser",user);
    
            //密码认证,有shiro完成
            return new SimpleAuthenticationInfo(user,user.getPwd(),"");
        }
    }
    
    

    ShiroConfig.java

    @Configuration
    public class ShiroConfig {
    
        //3.ShiroFilterFactoryBean,类名不能乱写,否则可能会报错
        @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("MySecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
            ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
            //设置安全管理器
            bean.setSecurityManager(defaultWebSecurityManager);
    
            //添加shiro内置过滤器
            /*
               anon:无需认证就可访问
               authc:必须认证后才可访问
               user:必须拥有记住我功能才能用
               perms:拥有对某个资源的权限才能访问
               role:拥有某个角色的权限才能访问
            * */
            Map<String,String> filterMap=new LinkedHashMap<>();
            filterMap.put("/user/add","perms[user:add]"); //设置访问权限user:add
            filterMap.put("/user/update","perms[user:update]"); //设置访问权限user:update
    
            filterMap.put("/user/*","authc"); //访问需要认证
    
            filterMap.put("/logOut","logout"); //退出系统
    
            bean.setFilterChainDefinitionMap(filterMap);
    
            //设置登录请求
            bean.setLoginUrl("/toLogin");
            //未授权执行此请求
            bean.setUnauthorizedUrl("/unAuthorize");
    
            return bean;
        }
    
        //2.DefaultWebSecurityManager
        @Bean(name = "MySecurityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            //关联UserRealm
            securityManager.setRealm(userRealm);
            return securityManager;
        }
    
        //1.创建realm对象,需要自定义类
        @Bean
        public UserRealm userRealm(){
            UserRealm userRealm = new UserRealm();
            //是否开启md5加密
            //userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
            return userRealm;
        }
        
        //md5加密
        @Bean
        public HashedCredentialsMatcher hashedCredentialsMatcher(){
            HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
            //利用md5进行加密
            hashedCredentialsMatcher.setHashAlgorithmName("md5");
            //加密次数
            hashedCredentialsMatcher.setHashIterations(1024);
            return hashedCredentialsMatcher;
        }
    
        //整合shiro-thymeleaf
        @Bean
        public ShiroDialect getShiroDialect(){
            return new ShiroDialect();
        }
    
    }
    
  • 5.控制器

    @Controller
    public class MyController {
    
        @Autowired
        private UserRealm userRealm;
    
        @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";  //出现异常,返回登录页
            }
    
        }
    
        @GetMapping("/unAuthorize")
        @ResponseBody
        public String UnAuthorize(){
            return "没有访问权限";
        }
    
  • 6.前端页面

    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>$Title$</title>
    </head>
    <body>
    <h1>首页</h1>
    <p th:text="${msg}"></p>
    <div th:if="${session.loginUser==null}">
        <a th:href="@{/toLogin}">前往登录</a>
    </div>
    
    <div th:if="${session.loginUser!=null}">
        <a th:href="@{/logOut}">退出</a>
    </div>
    
    
    <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>
    
    
    </body>
    </html>
    

    login.html

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

(1)未认证时的首页
在这里插入图片描述
(2)认证后的首页,实现不同权限展示不同页面
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值