1. 程式人生 > >springboot/mybatis/shiro/redis整合

springboot/mybatis/shiro/redis整合

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