Apache Shiro是一個功能強大且易於使用的Java安全框架,它為開發人員提供了一種直觀,全面的身份驗證,授權,加密和會話管理解決方案。下麵是在SpringBoot中使用Shiro進行認證和授權的例子,代碼如下: pom.xml 導入SpringBoot和Shiro依賴: 也可以直接導入Apa ...
Apache Shiro是一個功能強大且易於使用的Java安全框架,它為開發人員提供了一種直觀,全面的身份驗證,授權,加密和會話管理解決方案。下麵是在SpringBoot中使用Shiro進行認證和授權的例子,代碼如下:
pom.xml
導入SpringBoot和Shiro依賴:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.2</version>
</dependency>
</dependencies>
也可以直接導入Apache Shiro提供的starter:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
</dependency>
Shiro配置類
package com.cf.shiro1.config;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
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;
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//設置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//設置未認證(登錄)時,訪問需要認證的資源時跳轉的頁面
shiroFilterFactoryBean.setLoginUrl("/loginPage");
//設置訪問無許可權的資源時跳轉的頁面
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorizedPage");
//指定路徑和過濾器的對應關係
Map<String, String> filterMap = new HashMap<>();
//設置/user/login不需要登錄就能訪問
filterMap.put("/user/login", "anon");
//設置/user/list需要登錄用戶擁有角色user時才能訪問
filterMap.put("/user/list", "roles[user]");
//其他路徑則需要登錄才能訪問
filterMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
@Bean
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("realm") Realm realm) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(realm);
return defaultWebSecurityManager;
}
@Bean
public Realm realm() {
MyRealm realm = new MyRealm();
//使用HashedCredentialsMatcher帶加密的匹配器來替換原先明文密碼匹配器
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//指定加密演算法
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
//指定加密次數
hashedCredentialsMatcher.setHashIterations(3);
realm.setCredentialsMatcher(hashedCredentialsMatcher);
return realm;
}
}
自定義Realm
package com.cf.shiro1.config;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class MyRealm extends AuthorizingRealm {
/**
* 授權
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
Object username = principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setRoles(getRoles(username.toString()));
return simpleAuthorizationInfo;
}
/**
* 認證
*
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
Map<String, Object> userInfo = getUserInfo(username);
if (userInfo == null) {
throw new UnknownAccountException();
}
//鹽值,此處使用用戶名作為鹽
ByteSource salt = ByteSource.Util.bytes(username);
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, userInfo.get("password"), salt, getName());
return authenticationInfo;
}
/**
* 模擬資料庫查詢,通過用戶名獲取用戶信息
*
* @param username
* @return
*/
private Map<String, Object> getUserInfo(String username) {
Map<String, Object> userInfo = null;
if ("zhangsan".equals(username)) {
userInfo = new HashMap<>();
userInfo.put("username", "zhangsan");
//加密演算法,原密碼,鹽值,加密次數
userInfo.put("password", new SimpleHash("MD5", "123456", username, 3));
}
return userInfo;
}
/**
* 模擬查詢資料庫,獲取用戶角色列表
*
* @param username
* @return
*/
private Set<String> getRoles(String username) {
Set<String> roles = new HashSet<>();
roles.add("user");
roles.add("admin");
return roles;
}
}
Controller
package com.cf.shiro1.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
/**
* 登錄
* @param username
* @param password
* @return
*/
@RequestMapping("/login")
public String userLogin(String username, String password) {
String result;
//獲取當前用戶
Subject currentUser = SecurityUtils.getSubject();
//用戶是否已經登錄,未登錄則進行登錄
if (!currentUser.isAuthenticated()) {
//封裝用戶輸入的用戶名和密碼
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
try {
//登錄,進行密碼比對,登錄失敗時將會拋出對應異常
currentUser.login(usernamePasswordToken);
result = "登錄成功";
} catch (UnknownAccountException uae) {
result = "用戶名不存在";
} catch (IncorrectCredentialsException ice) {
result = "密碼錯誤";
} catch (LockedAccountException lae) {
result = "用戶狀態異常";
} catch (AuthenticationException ae) {
result = "登錄失敗,請與管理員聯繫";
}
} else {
result = "您已經登錄成功了";
}
return result;
}
@RequestMapping("/list")
public String userList() {
return "訪問我需要登錄並且需要擁有user角色!";
}
}