Shiro快速实战

Shiro快速实战

初识Shiro

Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。
三个核心组件:Subject, SecurityManager 和 Realms.

  • Subject :当前操作用户
  • SecurityManager : 管理所用操作用户,shiro框架的核心
  • Realm :充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息


备注:realm可以有一个,或多个,但shiro框架必须有一个realm连接数据

Shiro整合到Spring Boot

技术栈:

  1. Shiro
  2. Spring Boot
  3. MyBatis
  4. Thymeleaf

配置pom.xml

 <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>

前端界面

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>更新</title>
</head>
<body>
<h2>update</h2>
</body>
</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="ss:mm">
    <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>

<!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: #ff0000"></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>

连接数据库

spring:
  thymeleaf:
    cache: false #关闭thymeleaf缓存
  messages:
    basename: i18n.login
  mvc:
    format:
      date: yyyy-MM-dd #设置日期形式
  #配置数据源
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/db?serverTimezone=UTC&useUnicode=ture&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
## Mybatis 配置
mybatis:
  mapper-locations: classpath:/mapper/*.xml #mapper xml 文件地址
  type-aliases-package: com.demo01.pojo #实体类包路径

配置ShiroConfig

配置ShiroConfig原因:
在这里插入图片描述

public class ShiroConfig {
    /**
     * 创建ShiroFilterFactoryBean 3
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //添加Shiro内置过滤器
        /**
         * Shiro内置过滤器,可以实现权限相关的拦截器
         *    常用的过滤器:
         *       anon: 无需认证(登录)可以访问
         *       authc: 必须认证才可以访问
         *       user: 如果使用rememberMe的功能可以直接访问
         *       perms: 该资源必须得到资源权限才可以访问
         *       role: 该资源必须得到角色权限才可以访问
         */
        Map<String,String> filterMap = new LinkedHashMap<String,String>();
        filterMap.put("/emps","authc");
        filterMap.put("/emp","perms[admin]");
        filterMap.put("/emp/*", "perms[admin]");
        filterMap.put("/doctor/*","anon");

        filterMap.put("/delemp/*","perms[admin]");
//        filterMap.put("/users/*","perms[admin]");
        filterMap.put("/user/logout","logout");


        //设置未授权提示界面
        shiroFilterFactoryBean.setUnauthorizedUrl("/error/noAuth");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        return shiroFilterFactoryBean;
    }

    /**
     * 创建DefaultWebSecurityManager 2
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联realm
        securityManager.setRealm(userRealm);
        return securityManager;

    }

    /**
     * 创建Realm1对象
     */
    @Bean(name = "userRealm")
    public UserRealm getRealm(){
        return new UserRealm();
    }
//整合shiro thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }

}

编写Realm类

public class UserRealm extends AuthorizingRealm {
    @Autowired
    UserMapper userMapper;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("授权执行");
        //给资源进行授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前登录用户
        Subject subject = SecurityUtils.getSubject();
        GuestUser guser = (GuestUser) subject.getPrincipal();
        System.out.println("用户信息:" + subject.getPrincipal());
        GuestUser dbguser = userMapper.findById(guser.getId());
        //给用户添加权力
        info.addStringPermission(dbguser.getPerms());
        return info;
    }


    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("认证执行");

        //1.判断用户名
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //获取登录的用户
        GuestUser user = userMapper.findByName(token.getUsername());

        if (user == null) {
            //用户名不存在
            return null;//shiro底层会抛出UnKnowAccountException
        }
        //2.判断密码
        return new SimpleAuthenticationInfo(user, user.getPassword(), "");


    }
}

登录处理

 @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";
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值