springboot/mybatis/shiro/redis整合

版权声明:A_芦瑞华_i_DO.欢迎转载 https://blog.csdn.net/weixin_43067223/article/details/84652847

github克隆源代码:https://github.com/Lu-dashuai/shiro

1.目标:

1.认证拦截:

  • 未登陆的用户都不能访问后台页面,访问的结果是跳转到登陆页面。

2.权限认证:

  • 学生只能访问学生应该访问的页面。老师也同样。

  • 表结构
    在这里插入图片描述

  • 项目结构
    在这里插入图片描述在这里插入图片描述

  • 注意:

  1. 这里我只有用户表。其他表没有创建。角色是自己模拟的。
  2. 项目中与Emp有关的都可以删除,那些是测试框架的。

2.操作:


1.整合springboot、mybatis、redis、thyemleaf


2.将项目spring和shiro的整合依赖导入

  • 此时需要更改pom.xml文件
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.0</version>
</dependency>
  • 依赖已经导入
    在这里插入图片描述

3.编写初步的shiro的配置类

  • 在这之前请先观看所有的.html页面,看好跳转关系。
  • 在java文件夹下新建com.aaa.rent.shiro目录;
  • 在目录下创建一个类ShiroConfig;
  • 给类加注解 @Configration :声明为配置类;
  • 在类中写三个方法,分别:
    1. 创建ShiroFilterFactoryBean;
      • 设置安全管理器
      • 添加shiro的过滤器
      • 被拦截后跳转登陆页面
      • 未授权跳转页面
    2. 创建DefaultWebSecurityManager;
      • 关联realm
    3. 创建Realm;
      ||
      ||
      \ . /

以上三个方法分别加上注解 @Bean;

  • 在目录下创建一个UserRealm类,继承AuthorizingRealm
  • 实现两个方法:
    1. doGetAuthorizationInfo:执行授权逻辑。
      1. 获取当前登陆的用户
      2. 通过用户名查当前用户
      3. 获取当前的权限字符
      4. 设置只有是这个字符才可以访问
    2. doGetAuthenticationInfo::执行认证逻辑。
      1. 编写shiro判断逻辑,判断用户名密码是否正确

ShiroConfig代码

package com.aaa.rent.shiro;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
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.HashMap;
import java.util.Map;

/**
 * className:ShiroConfig
 * discription:
 * author:luRuiHua
 * createTime:2018-11-30 14:36
 * 拦截器作用:如果没登陆或者用户名密码输错,登陆index.html失败,跳转到login.html
 *              如果登陆成功,可以访问index.html
 *              不能直接访问user/student----------student授权
 *                          user/teacher---------teacher授权
 *                          user/index
 *              可以访问user/login
 *                      user/toLogin
 *
 */
@Configuration//配置类
public class ShiroConfig {
    /**
     * 1. 创建ShiroFilterFactoryBean;
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //添加shiro的过滤器
        //shiro的内置过滤器:可以实现权限的相关拦截
        //常用的过滤器:
        //1.anno:无需认证(登陆即可访问)
        //2.authc:必须认证才可以访问
        //3.user:如果使用remanberMe的功能就可以直接访问
        //4.perms:该资源必须得到资源权限才可以访问
        //5.role:该资源必须得到角色权限才可以访问
        Map filterMap = new HashMap();

        //必须登陆才可以访问
        //设置哪些页面必须授权后才可以登陆
        filterMap.put("/user/student","perms[2]");//学生页面
        filterMap.put("/user/teacher","perms[1]");//老师页面
        filterMap.put("/user/index","authc");//首页

        //被拦截后跳转登陆页面
        shiroFilterFactoryBean.setLoginUrl("/user/login ");
        //未授权跳转页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/user/unAuth");




        //将filterMap中的url和相关权限交给shiro框架管理
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

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

        //关联realm
        securityManager.setRealm(userRealm);

        return securityManager;
    }
    /**
     * 3. 创建Realm;
     */
    @Bean(name = "userRealm")
    public UserRealm getRealm() {
        return new UserRealm();
    }
    /**
     * 配置shiroDialect,用于thymeleaf和shiro标签配合使用
     */
    @Bean
    public ShiroDialect getShiroDialect() {
        return new ShiroDialect();
    }
}

UserRealm类

package com.aaa.rent.shiro;

import com.aaa.rent.service.UserService;
import org.apache.shiro.SecurityUtils;
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.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import javax.xml.bind.SchemaOutputResolver;
import java.util.List;
import java.util.Map;

/**
 * className:UserRealm
 * discription:
 * author:luRuiHua
 * createTime:2018-11-30 14:41
 */
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;
    /**
     * 执行授权逻辑
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行授权逻辑");

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前登陆的用户
        Subject subject = SecurityUtils.getSubject();
        //获取用户名
        String userName = subject.getPrincipal()+"";
        //通过用户名查当前用户
        List<Map> maps = userService.selectUserList(userName);
        //获取当前的权限字符
        String roleId = maps.get(0).get("ROLE_ID")+"";
        //设置只有是这个字符才可以访问
        info.addStringPermission(roleId);


        return info;
    }

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

        //编写shiro判断逻辑,判断用户名密码是否正确
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        String username = token.getUsername();
        //1.判断用户名
        List<Map> mapList = userService.selectUserList(token.getUsername());
        if (mapList.size() == 0) {
            return null;
        } else {
            return new SimpleAuthenticationInfo(username, mapList.get(0).get("PASSWORD"),"");
        }
    }
}


5.UserController.java中的逻辑

  1. 获取前台页面登陆的账号和密码
  2. 获取subject
  3. 封装用户数据
  4. 执行登陆方法
  5. 登陆成功,跳到欢迎页面
  6. 用户名不存在的异常
  7. 用户名和密码错误
 /**
     * 跳转欢迎页面
     * @return
     */
    @RequestMapping("/toLogin")
    public String toLogin(String userName, String passWord, Model model) {
        System.out.println("账号是:"+userName);

        //shiro的关键代码,执行认证功能
        //1.获取subject
        Subject subject = SecurityUtils.getSubject();
        //2.封装用户数据
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName, passWord);
        //3.执行登陆方法
        try {
            //登陆成功
            subject.login(usernamePasswordToken);
            model.addAttribute("msg","登陆成功");
            //跳到欢迎页面
            return "back/welcome";
        } catch (UnknownAccountException e) {//用户名不存在的异常
            model.addAttribute("msg","用户名不存在");
            return "login";
        } catch (IncorrectCredentialsException e) {//用户名不存在的异常
            model.addAttribute("msg","用户名和密码错误");
            return "login";
        }
    }

猜你喜欢

转载自blog.csdn.net/weixin_43067223/article/details/84652847