Shiro集成web環境[Springboot]-認證與授權
阿新 • • 發佈:2019-01-06
跳轉 anon cache action 過濾器 utf-8 tor def nbsp
Shiro集成web環境[Springboot]--認證與授權
在登錄頁面提交登陸數據後,發起請求也被ShiroFilter攔截,狀態碼為302
<form action="${pageContext.request.contextPath}/user/login" method="post"> Username:<input type="text" name="username"></br> Password:<input type="password" name="password"></br> <input type="submit" value="提交"> </form>
所以,必須將控制器的請求全部設置為匿名資源
@Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String,String> map = new HashMap<>(); //多個過濾器 AnonymousFilter 匿名過濾器 anon // FormAuthenticationFilter 認證過濾器 authc map.put("/**","authc"); map.put("/user/*","anon"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); shiroFilterFactoryBean.setLoginUrl("/main/login.jsp"); return shiroFilterFactoryBean; } @Bean public SecurityManager getSecurityManager(Realm realm){ //web環境下securityManage的實現類為DefaultWebSecurityManager SecurityManager securityManager = new DefaultWebSecurityManager(); ((DefaultWebSecurityManager) securityManager).setRealm(realm); return securityManager; }
再次發起請求,ok 但由於認證未設置 所以沒有成功的跳轉。
開發自定義Realm--認證與授權方法全部實現
public class MyRealm extends AuthorizingRealm { @Autowired private UserMapper userMapper; @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { String principal =(String) authenticationToken.getPrincipal(); User user= new User(); user.setUsername(principal); User user1 = userMapper.selectOne(user); AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(principal,user1.getPassword(),ByteSource.Util.bytes("salt"),this.getName()); return authenticationInfo; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal(); System.out.println("================================"); User user= new User(); user.setUsername(primaryPrincipal); User user1 = userMapper.selectOne(user); if(primaryPrincipal.equals(user1.getUsername())){ SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.addRole("super"); authorizationInfo.addStringPermission("user:delete"); authorizationInfo.addStringPermissions(Arrays.asList("admin:delete","admin:add")); return authorizationInfo; } return null; } }
補充ShiroFilter,將SecurityManager,自定義Realm,CredentialsMatcher,CacheManager全部交由工廠管理:
@Configuration
public class ShiroFilterConf {
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//shiro會對所有資源進行控制,默認不攔截 需要配置
Map<String,String> map = new HashMap<>();
//多個過濾器 AnonymousFilter 匿名過濾器 anon
// FormAuthenticationFilter 認證過濾器 authc
map.put("/**","authc");
map.put("/user/*","anon");
map.put("/index.jsp","anon");
//多個過濾器組成過濾器鏈
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
//設置認證頁面路徑
shiroFilterFactoryBean.setLoginUrl("/main/login.jsp");
return shiroFilterFactoryBean;
}
@Bean
public SecurityManager getSecurityManager(Realm realm,CacheManager cacheManager){
//web環境下securityManage的實現類為DefaultWebSecurityManager
SecurityManager securityManager = new DefaultWebSecurityManager();
((DefaultWebSecurityManager) securityManager).setRealm(realm);
((DefaultWebSecurityManager) securityManager).setCacheManager(cacheManager);
return securityManager;
}
@Bean
public Realm getRealm(CredentialsMatcher credentialsMatcher){
MyRealm myRealm = new MyRealm();
myRealm.setCredentialsMatcher(credentialsMatcher);
return myRealm;
}
@Bean
public CredentialsMatcher getCredentialsMatcher(){
HashedCredentialsMatcher hm = new HashedCredentialsMatcher();
hm.setHashAlgorithmName("MD5");
hm.setHashIterations(1024);
return hm;
}
@Bean
public CacheManager getCacheManager(){
CacheManager cacheManager = new EhCacheManager();
return cacheManager;
}
}
測試index頁面
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" %>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<shiro:authenticated>
hello:<shiro:principal></shiro:principal> <a href="${pageContext.request.contextPath}/user/logout">登出</a>
<ul>
<li>專輯</li>
<li>章節</li>
<li>用戶</li>
<shiro:hasRole name="super">
<li>管理員</li>
<shiro:hasPermission name="admin:delete">
刪
</shiro:hasPermission>
<shiro:hasPermission name="admin:add">
增
</shiro:hasPermission>
<shiro:hasPermission name="admin:update">
改
</shiro:hasPermission>
</shiro:hasRole>
</ul>
</shiro:authenticated>
<shiro:notAuthenticated>
<a href="${pageContext.request.contextPath}/main/login.jsp">你好請登錄</a>
</shiro:notAuthenticated>
</body>
</html>
shiro中相關的標簽
<shiro:principal></shiro:principal> //用戶的身份信息
<shiro:authenticated></shiro:authenticated> //認證成功 執行標簽體的內容
<shiro:notAuthenticated></shiro:notAuthenticated> //未認證 執行標簽體內容
//基於角色的權限管理
<shiro:hasRole name="super"></shiro:hasRole>
<shiro:hasAnyRoles name="admin,super"></shiro:hasAnyRoles>
//基於資源的權限管理
<shiro:hasPermission name="user:delete"></shiro:hasPermission>
緩存問題
如果沒有緩存,一個Permission或者role判斷要查詢三次數據庫-username查主體--主體查角色---角色查權限,這樣對於數據庫的壓力太大,需要設置緩存。而且要註意到,在第一次查詢時shiro就會多個Permission或者Role判斷設置一次緩存,就是說,授權方法doGetAuthorizationInfo只走一次。
ehcache主包必須導入,shiro集成時CacheManager是沒有實現的,主包中才有實現類EhCacheManager
@Bean
public CacheManager getCacheManager(){
CacheManager cacheManager = new EhCacheManager();
return cacheManager;
}
Shiro集成web環境[Springboot]-認證與授權