springboot整合shiro-简单入门实战


参考了https://www.bilibili.com/video/BV1ct411x7CN

初始准备及配置

  • 创建springboot项目
  • 导入依赖列表
		<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.3.2</version>
        </dependency>

		<!--MyBatis相关依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.37</version>
        </dependency>
        <!--springboot-MyBatis启动器-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

shiro核心API

图片来自https://www.bilibili.com/video/BV1ct411x7CN?p=5
在这里插入图片描述

创建配置类

config文件

package com.example.shiro.config;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * shiro配置类
 */
@Configuration
public class ShiroConfig {
    /**
     * 创建ShiroFilterFactoryBean
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getSecurityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //添加shiro内置过滤器
        Map<String, String> filterMap = new LinkedHashMap<String, String>();
//        filterMap.put("/add", "authc");
//        filterMap.put("/update", "authc");
        //授权过滤器,要放在最上面,否则会失效
        filterMap.put("/add", "perms[user:add]");
        filterMap.put("/", "anon");
        //放行login
        filterMap.put("/login", "anon");
        filterMap.put("/*", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        //设置过滤后跳转的页面
        shiroFilterFactoryBean.setLoginUrl("/toLogin");
        //设置未授权提示页面,这里因为已经是用户验证过了,所以不必在过滤器中再放行一次
        shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");
        return shiroFilterFactoryBean;
    }

    /**
     * 创建DefaultWebSecurityManager
     * @param userRealm
     * @return
     */
    @Bean
    public DefaultWebSecurityManager getSecurityManager(@Qualifier("getRealm") UserRealm userRealm){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //关联Realm
        defaultWebSecurityManager.setRealm(userRealm);
        return defaultWebSecurityManager;
    }
    /**
     * 创建realm
     * @return
     */
    @Bean
    public UserRealm getRealm(){
        return new UserRealm();
    }
}

自定义UserRealm

package com.example.shiro.config;

import com.example.shiro.domain.User;
import com.example.shiro.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

public class UserRealm extends AuthorizingRealm {
    /**
     * 执行授权逻辑
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //给资源授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        //添加资源的授权字符串,认证中perms指定的
        info.addStringPermission("user:add");
        return info;
    }

    //注入业务
    @Autowired
    private UserService userService;

    /**
     * 执行认证逻辑
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        User user = userService.findByUName(token.getUsername());
        if(user == null){
            return null; //这里return null,shiro底层就会抛出UnknownAccountException
        }
        //判断密码
        return new SimpleAuthenticationInfo("", user.getPassword(), ""); //第二个是数据库中密码,第三个是realmName
    }
}

配置类中常用内置过滤器分析

参考了https://github.com/YUbuntu0109/YUbuntu0109.github.io/blob/HexoBackup/source/_posts/Shiro%E7%9A%84%E6%8B%A6%E6%88%AA%E5%99%A8%E6%9C%BA%E5%88%B6.md

  • anon : 匿名拦截器,即不需要登录即可访问。类似于filterMap.put("/", "anon");将/的请求放行。
  • authc : 表示需要认证(登录)才能使用,类似于filterMap.put("/*", "authc");将所有请求进行拦截。
  • user : 用户拦截器,用户已经身份验证/记住我的登录。
  • perms : 权限授权拦截器,验证用户是否拥有资源权限。
  • roles : 角色授权拦截器,验证用户是否拥有资源角色。

用户认证的简单逻辑

  1. 获取subject
  2. 封装用户数据
  3. 执行登录方法
    subject.login会去调用UserRealm中的doGetAuthenticationInfo方法进行认证,需要在里面编写认证逻辑。

连接mybatis

配置相关依赖

见初始配置中mybatis相关依赖部分

配置application.properties

spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/student
spring.datasource.username = root
spring.datasource.password = 123456

spring.datasource.type = com.alibaba.druid.pool.DruidDataSource

mybatis.type-aliases-package=com.example.domain

所用到的其他类和页面

  • UserController
package com.example.shiro.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class UserController {
    @GetMapping("add")
    public String add(){
        return "/user/add.html";
    }

    @GetMapping("update")
    public String update(){
        return "/user/update.html";
    }

    @GetMapping("toLogin")
    public String toLogin(){
        return "/login.html";
    }

    /**
     * 登录逻辑处理
     */
    @PostMapping("/login")
    public String login(String name, String pwd, Model model){
        //1.获取subject
        Subject subject = SecurityUtils.getSubject();
        //2.封装用户数据
        UsernamePasswordToken token = new UsernamePasswordToken(name, pwd);
        //3.执行登陆方法
        try {
            subject.login(token);
            //登陆成功
            return "redirect:/";
        }
        catch (UnknownAccountException e){
            //登陆失败: 用户名不存在
            model.addAttribute("msg", "用户名不存在");
            return "login";
        }
        catch (IncorrectCredentialsException e){
            //登陆失败: 密码错误
            model.addAttribute("msg", "密码错误");
            return "login";
        }
    }
}


  • 静态页面结构

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值