Shiro的簡單使用
阿新 • • 發佈:2019-01-02
一、shiro認證
1、請求認證
Subject subject = SecurityUtils.getSubject();// 根據執行環境返回subject
subject.login(token);// 這裡的token一般指的是 UsernamePasswordToken,引數有
// String username, String password, boolean rememberMe, String host ,有多種建構函式
2、通過SecurityManager執行認證
public void login(AuthenticationToken token) throws AuthenticationException {
this.clearRunAsIdentitiesInternal();
Subject subject = this.securityManager.login(this, token);// 呼叫securityManager
String host = null;
PrincipalCollection principals;
if (subject instanceof DelegatingSubject) {
DelegatingSubject delegating = (DelegatingSubject)subject;
principals = delegating.principals;
host = delegating.host;
} else {
principals = subject.getPrincipals();
}// 無論怎麼樣principals = subject.getPrincipals();既使用者名稱
if (principals != null && !principals.isEmpty()) {
this.principals = principals;
this.authenticated = true;
if (token instanceof HostAuthenticationToken) {
host = ((HostAuthenticationToken)token).getHost();
}
if (host != null) {
this.host = host;
}
Session session = subject.getSession(false);
if (session != null) {
this.session = this.decorate(session);
} else {
this.session = null;
}
} else {
String msg = "Principals returned from securityManager.login( token ) returned a null or empty value. This value must be non null and populated with one or more elements.";
throw new IllegalStateException(msg);
}
}
3、SecurityManager通過ModularRealmAuthenticator再通過realm進行認證
在自定義的Realm中完成認證
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//獲取使用者的輸入的賬號.
String username = (String) token.getPrincipal();
User user = userService.selectByUsername(username);
String password = user.getPassword();
if (user == null) throw new UnknownAccountException();
if (0 == user.getEnable()) {
throw new LockedAccountException(); // 帳號鎖定
}
//通過這個進行認證,並返回
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, null, getName());
Session session = SecurityUtils.getSubject().getSession();// 當驗證都通過後,把使用者資訊放在session裡
session.setAttribute("userSession", user);
session.setAttribute("userSessionId", user.getId());
return simpleAuthenticationInfo;
}
4、認證的配置
這些配置在shiro的配置檔案中完成
@Bean
public MyShiroRealm myShiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());// 憑證驗證器
return myShiroRealm;
}
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {// 憑證驗證器
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");//雜湊演算法:這裡使用MD5演算法;
hashedCredentialsMatcher.setHashIterations(1);//雜湊的次數,比如雜湊兩次,相當於 md5(md5(""));
return hashedCredentialsMatcher;
}
二、shiro授權
1、ModularRealmAuthenticator通過realm進行認證
在自定義的Realm中完成授權,將使用者的許可權查出,配置到info中去。
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String username = (String) principalCollection.getPrimaryPrincipal();
User user = userService.selectByUsername(username);
Map<String, Object> map = new HashMap();
map.put("userid", user.getId());
List<Resources> resourcesList = resourcesService.loadUserResources(map);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 許可權資訊物件info
for (Resources resources : resourcesList) {
info.addStringPermission(resources.getResurl()); // 在這裡存放查出的使用者的所有的角色(role)及許可權(permission)
}
return info;
}
2、授權的配置,通過filterChainDefinitionMap在Shiro的攔截器中配置
這些配置在shiro的配置檔案中完成
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setSuccessUrl("/usersPage");// 登入成功跳轉的頁
shiroFilterFactoryBean.setUnauthorizedUrl("/403");// 未授權介面;
Map<String, String> filterChainDefinitionMap = new LinkedHashMap();
filterChainDefinitionMap.put("/logout", "logout");// 配置登出地址,不需要專門去寫控制器
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/font-awesome/**", "anon");// 首先放過一般的靜態資源
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); // 配置所有需要攔截的地址
return shiroFilterFactoryBean;
}
2.1配置規則
// 將需要配置的地址放入map中,規則如下:
/**
anon:例子/admins/**=anon 沒有引數,表示可以匿名使用。
authc:例如/admins/user/**=authc表示需要認證(登入)才能使用,沒有引數
roles(角色):例子/admins/user/**=roles[admin],引數可以寫多個,多個時必須加上引號,
並且引數之間用逗號分割,當有多個引數時,例如admins/user/**=roles["admin,guest"],
每個引數通過才算通過,相當於hasAllRoles()方法。
perms(許可權):例子/admins/user/**=perms[user:add:*],引數可以寫多個,多個時必須加上引號,
並且引數之間用逗號分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],
當有多個引數時必須每個引數都通過才通過,想當於isPermitedAll()方法。
rest:例子/admins/user/**=rest[user],根據請求的方法,相當於/admins/user/**=perms[user:method] ,
其中method為post,get,delete等。
port:例子/admins/user/**=port[8081],當請求的url的埠不是8081是跳轉到
schemal://serverName:8081?queryString,其中schmal是協議http或https等,
serverName是你訪問的host,8081是url配置裡port的埠,queryString是你訪問的url裡的?後面的引數。
authcBasic:例如/admins/user/**=authcBasic沒有引數表示httpBasic認證
ssl:例子/admins/user/**=ssl沒有引數,表示安全的url請求,協議為https
user:例如/admins/user/**=user沒有引數表示必須存在使用者,當登入操作時不做檢查
*/
// 詳情參考shiro.web.filter原始碼
三、shiro結合thymeleaf實現細粒度許可權控制
在shiro的配置檔案中加入
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
html中加入xmlns
<html lang="zh_CN" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
maven依賴
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>1.2.1</version>
</dependency>