狂神SpringBoot学习笔记12天-Day 09 SpringBoot 整合Shiro

9、Shiro

1、导入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </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>

    <!--前端交互整合-->
    <dependency>
        <groupId>com.github.theborakompanioni</groupId>
        <artifactId>thymeleaf-extras-shiro</artifactId>
        <version>2.0.0</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.8</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <!--mybatis-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.2.0</version>
    </dependency>

    <!-- shiro-spring -->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.7.1</version>
    </dependency>
</dependencies>

2、application.properties

# 应用名称
spring.application.name=springboot-08-shiro
# 应用服务 WEB 访问端口
server.port=8080
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=root
# THYMELEAF (ThymeleafAutoConfiguration)
# 开启模板缓存(默认值: true )
spring.thymeleaf.cache=false

#整合mybatis
mybatis.type-aliases-package=com.hui.pojo
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

3、后端代码

  • Controller
@Controller
public class ShiroController {
    @RequestMapping({"/", "/index"})
    public String toIndex(Model model) {
        model.addAttribute("msg", "首页");
        return "index";
    }
    @RequestMapping("/user/add")
    public String addUser() {
        return "user/add";
    }

    @RequestMapping("/user/update")
    public String updateUser() {
        return "user/update";
    }
    @RequestMapping("/toLogin")
    public String toLogin() {
        return "login";
    }

    @RequestMapping("/login")
    public String login(String username, String password, Model model) {
        // 获取用户
        Subject user = SecurityUtils.getSubject();
        // 封装参数,获取token
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        // 验证登录
        try {
            // 执行登录操作,跨类调用
            user.login(token);
            model.addAttribute("msg", "成功登录");
            return "index";
        } catch (UnknownAccountException uae) {
            model.addAttribute("msg", "用户名错误");
            return "login";
        } catch (IncorrectCredentialsException ice) {
            model.addAttribute("msg", "用户密码错误");
            return "login";
        }
    }


    @RequestMapping("/noAuth")
    @ResponseBody
    public String noAuth() {
        return "未授权,无法访问";
    }
}
  • ShiroConfig(shiro配置)

    @Configuration
    public class ShiroConfig {
    
        // 3 获取ShiroBean
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(
                @Qualifier("getDefaultWebSecurityManager") WebSecurityManager securityManager
        ) {
            ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
            // 设置安全管理器
            bean.setSecurityManager(securityManager);
            // 添加shiro的内置过滤器
            /*
                anon: 无需认证就可以登录
                authc:必须认证才能登录
                user: 必须拥有“记住我”这个功能
                perms:拥有对某个资源的权限才能访问
                role:拥有某个角色才能访问
             */
            LinkedHashMap<String, String> map = new LinkedHashMap<>();
            // 权限授权,访问url需要权限,支持通配符
            map.put("/user/add", "perms[user:add]");
            map.put("/user/update", "perms[user:update]");
            bean.setFilterChainDefinitionMap(map);
            // 设置登录url映射
            bean.setLoginUrl("/toLogin");
            // 设置未授权的请求
            bean.setUnauthorizedUrl("/noAuth");
            return bean;
        }
    
    
        // 2 获取安全管理器
        @Bean(name = "getDefaultWebSecurityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(
                @Qualifier("userRealm") UserRealm userRealm) {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            // 直接userRealm()传参也可以,这里演示Spring指定自动注入
            securityManager.setRealm(userRealm);
            return securityManager;
        }
    
        // 1 创建realm对象,需要自定义另一个类
        @Bean(name = "userRealm")
        public UserRealm userRealm() {
            return new UserRealm();
        }
    }
    
    
  • UserRealm(认证授权)

    public class UserRealm extends AuthorizingRealm {
    //  Subject 用户
    //  SecurityManager 管理所有用户
    //  Realm 连接数据
    
        @Autowired
        private UserServiceImpl userService;
    
    //  授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            // 进入被拦截的url,就会进这个info
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            // 授权应该从数据库查出权限字段
            // info.addStringPermission("user:add");
            // 从 new SimpleAuthenticationInfo(queryUser, queryUser.getPwd(), "");传递过来第一个参数user最为subject
            Subject subject = SecurityUtils.getSubject();
            User currentUser = (User) subject.getPrincipal();
            // 从数据库中获取验证权限
            simpleAuthorizationInfo.addStringPermission(currentUser.getPerms());
            return simpleAuthorizationInfo;
        }
    
    
    //    认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            // 模拟数据库中查出用户名、密码
            UsernamePasswordToken userToken = (UsernamePasswordToken) token;
            User user = userService.queryUserByName(userToken.getUsername());
            // 验证用户名
            if (user == null) {
                // 用户名不正确,就抛出UnknownAccountException
                return null;
            }
            Subject currentSubject = SecurityUtils.getSubject();
            Session session = currentSubject.getSession();
            session.setAttribute("loginUser", user);
            // 密码验证,shiro完成,不需要用户判断.直接返回
            return new SimpleAuthenticationInfo(user, user.getPwd(), "");
    
    
        }
    }
    
    
  • UserMapper(mapper)

    @Repository
    @Mapper
    public interface UserMapper {
        User queryUserByName(String name);
    }
    
  • UserMapper.xml(整合mybatis)

    <?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.hui.mapper.UserMapper">
        <select id="queryUserByName" parameterType="String" resultType="User">
            select *
            from mybatis.user
            where name = #{name}
        </select>
    </mapper>
    
  • User(pojo)

    @AllArgsConstructor
    @Data
    @NoArgsConstructor
    public class User {
        private int id;
        private String name;
        private String pwd;
        private String perms;
    }
    
  • UserService(Service)

    public interface UserService {
        User queryUserByName(String name);
    }
    
  • UserServiceImpl(Service)

    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
        UserMapper userMapper;
    
        public UserServiceImpl(UserMapper userMapper) {
            this.userMapper = userMapper;
        }
    
        @Override
        public User queryUserByName(String name) {
            return userMapper.queryUserByName(name);
        }
    }
    

4、前端页面

  • index.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org"
          xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"
          xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>首页</h1>
    <div th:text="${msg}"></div>
    
    <!--/*@thymesVar id="loginUser" type=""*/-->
    <!--<div th:if="${session.loginUser ==null}">-->
        <!--<a th:href="@{/toLogin}">登录</a>-->
    <!--</div>-->
    
    <div shiro:hasPermission="add">
        <a th:href="@{/user/add}">add</a>
    </div>
    <div shiro:hasPermission="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>
    <hr>
    <p th:text="${msg}" style="color: red"></p>
    <form th:action="@{/login}">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password">
        <br>
        <input type="submit" name="提交">
    </form>
    </body>
    </html>
    
    
  • add.html(user包)

    <h1>add</h1>
    
  • update.html(user包)

    <h1>update</h1>
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值