springboot/mybatis/shiro/redis整合
阿新 • • 發佈:2018-12-01
github克隆原始碼:https://github.com/Lu-dashuai/shiro
1.目標:
1.認證攔截:
- 未登陸的使用者都不能訪問後臺頁面,訪問的結果是跳轉到登陸頁面。
2.許可權認證:
-
學生只能訪問學生應該訪問的頁面。老師也同樣。
-
表結構
-
專案結構
-
注意:
- 這裡我只有使用者表。其他表沒有建立。角色是自己模擬的。
- 專案中與Emp有關的都可以刪除,那些是測試框架的。
2.操作:
1.整合springboot、mybatis、redis、thyemleaf
- 我已將在github上上傳了一個springboot、mybatis、redis、thyemleaf,整合版的乾淨框架。可以直接克隆到本地。具體克隆步驟:
https://blog.csdn.net/weixin_43067223/article/details/84632586 - 框架github地址:https://github.com/Lu-dashuai/springboot-mybatis-redis.git
- 直接克隆到本地就ok。
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 :宣告為配置類;
- 在類中寫三個方法,分別:
- 建立ShiroFilterFactoryBean;
- 設定安全管理器
- 新增shiro的過濾器
- 被攔截後跳轉登陸頁面
- 未授權跳轉頁面
- 建立DefaultWebSecurityManager;
- 關聯realm
- 建立Realm;
||
||
\ . /
- 建立ShiroFilterFactoryBean;
以上三個方法分別加上註解 @Bean;
- 在目錄下建立一個UserRealm類,繼承AuthorizingRealm
- 實現兩個方法:
- doGetAuthorizationInfo:執行授權邏輯。
- 獲取當前登陸的使用者
- 通過使用者名稱查當前使用者
- 獲取當前的許可權字元
- 設定只有是這個字元才可以訪問
- doGetAuthenticationInfo::執行認證邏輯。
- 編寫shiro判斷邏輯,判斷使用者名稱密碼是否正確
- doGetAuthorizationInfo:執行授權邏輯。
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中的邏輯
- 獲取前臺頁面登陸的賬號和密碼
- 獲取subject
- 封裝使用者資料
- 執行登陸方法
- 登陸成功,跳到歡迎頁面
- 使用者名稱不存在的異常
- 使用者名稱和密碼錯誤
/**
* 跳轉歡迎頁面
* @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";
}
}