0.前言
Shiro簡單來說就是一個做權限鑑定與管理的一個工具。在搭建spring boot 集成Shrio的demo的時候,我們需要做一個前期的準備(demo中有sql文件),demo在這裏
數據庫表:
Maven:
<!--shiro和spring整合-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!--shiro核心包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
1.登錄的controller
/**
* 1.傳統登錄
* 前端發送登錄請求 => 接口部分獲取用戶名密碼 => 程序員在接口部分手動控制
* 2.shiro登錄
* 前端發送登錄請求 => 接口部分獲取用戶名密碼 => 通過subject.login => realm域的認證方法
*/
@RequestMapping(value = "/login")
public String login(String username, String password) {
//構造登錄令牌
try {
/**
* 密碼加密:
* shiro提供的md5加密
* Md5Hash:
* 參數一:加密的內容
* 111111 --- abcd
* 參數二:鹽(加密的混淆字符串)(用戶登錄的用戶名)
* 111111+混淆字符串
* 參數三:加密次數
*
*/
password = new Md5Hash(password, username, 3).toString();
System.out.println(username + "==>" + password);
UsernamePasswordToken upToken = new UsernamePasswordToken(username, password);
//1.獲取subject
Subject subject = SecurityUtils.getSubject();
//獲取session
String sid = (String) subject.getSession().getId();
//2.調用subject進行登錄
subject.login(upToken);
return "登錄成功:" + sid;
} catch (Exception e) {
return "用戶名或密碼錯誤";
}
}
2. 自定義的Realm域
用來做權限的認證和授權,跟數據庫進行交互,獲取相應的權限或者角色信息,controller中使用subject.login(upToken);方法的時候就會執行這裏的一些方法
/**
* 自定義的realm
*/
public class CustomRealm extends AuthorizingRealm {
@Override
public void setName(String name) {
super.setName("customRealm");
}
@Autowired
private UserService userService;
/**
* 授權方法
* 操作的時候,判斷用戶是否具有響應的權限
* 先認證 -- 安全數據
* 再授權 -- 根據安全數據獲取用戶具有的所有操作權限
*
*
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//1.獲取已認證的用戶數據
User user = (User) principalCollection.getPrimaryPrincipal();//得到唯一的安全數據
//2.根據用戶數據獲取用戶的權限信息(所有角色,所有權限)
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Set<String> roles = new HashSet<>();//所有角色
Set<String> perms = new HashSet<>();//所有權限
for (Role role : user.getRoles()) {
roles.add(role.getName());
for (Permission perm : role.getPermissions()) {
perms.add(perm.getCode());
}
}
info.setStringPermissions(perms);
info.setRoles(roles);
return info;
}
/**
* 認證方法
* 參數:傳遞的用戶名密碼
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.獲取登錄的用戶名密碼(token)
UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
String username = upToken.getUsername();
String password = new String( upToken.getPassword());
//2.根據用戶名查詢數據庫
User user = userService.findByName(username);
//3.判斷用戶是否存在或者密碼是否一致
if(user != null && user.getPassword().equals(password)) {
System.out.println("用戶名和密碼正確,登陸成功");
//4.如果一致返回安全數據
//構造方法:安全數據,密碼,realm域名
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
return info;
}
//5.不一致,返回null(拋出異常)
return null;
}
}
3.配置類
@Configuration
public class ShiroConfiguration {
//1.創建realm
@Bean
public CustomRealm getRealm() {
return new CustomRealm();
}
//2.創建安全管理器
@Bean
public SecurityManager getSecurityManager(CustomRealm realm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
//將自定義的會話管理器註冊到安全管理器中
securityManager.setSessionManager(sessionManager());
//將自定義的redis緩存管理器註冊到安全管理器中
securityManager.setCacheManager(cacheManager());
return securityManager;
}
//3.配置shiro的過濾器工廠
/**
* 再web程序中,shiro進行權限控制全部是通過一組過濾器集合進行控制
*
*/
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
//1.創建過濾器工廠
ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
//2.設置安全管理器
filterFactory.setSecurityManager(securityManager);
//3.通用配置(跳轉登錄頁面,爲授權跳轉的頁面)
filterFactory.setLoginUrl("/autherror?code=1");//跳轉url地址
filterFactory.setUnauthorizedUrl("/autherror?code=2");//未授權的url
//4.設置過濾器集合
/**
* 設置所有的過濾器:有順序map
* key = 攔截的url地址
* value = 過濾器類型
*
*/
Map<String,String> filterMap = new LinkedHashMap<>();
filterMap.put("/user/home","anon");//當前請求地址可以匿名訪問
//具有某種權限才能訪問
//使用過濾器的形式配置請求地址的依賴權限
//filterMap.put("/user/home","perms[user-home]"); //不具備指定的權限,跳轉到setUnauthorizedUrl地址
//使用過濾器的形式配置請求地址的依賴角色
//filterMap.put("/user/home","roles[系統管理員]");
filterMap.put("/user/**","authc");//當前請求地址必須認證之後可以訪問
filterFactory.setFilterChainDefinitionMap(filterMap);
return filterFactory;
}
//開啓對shior註解的支持
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}
4.關於demo的說明
demo中使用了redis,用來存儲sessionId,demo是學習這套視頻,大家也可以參考一些