shiro報錯 org.apache.shiro.UnavailableSecurityManagerException
阿新 • • 發佈:2019-01-05
自己照著教程搭springboot+mybatis+shiro前後端分離的一個框架。碰到了問題,幾天了,很困惑,煩請知道的朋友給點建議
org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an invalid application configuration.
網上搜了兩圈答案無果。
執行這句話就報錯。getSubject();
shiroconfig的配置
package com.rdhl.dds.config; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.mgt.SessionManager; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.aspectj.lang.annotation.Before; import org.crazycake.shiro.RedisCacheManager; import org.crazycake.shiro.RedisManager; import org.crazycake.shiro.RedisSessionDAO; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.HandlerExceptionResolver; import java.util.LinkedHashMap; import java.util.Map; /** * Created by Administrator on 2017/12/11. */ @Configuration public class ShiroConfig { @Bean public ShiroFilterFactoryBean shirFilter(@Qualifier("securityManager")SecurityManager securityManager) { System.out.println("ShiroConfiguration.shirFilter()-------------------------------"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); //注意過濾器配置順序 不能顛倒 //配置退出 過濾器,其中的具體的退出程式碼Shiro已經替我們實現了,登出後跳轉配置的loginUrl filterChainDefinitionMap.put("/logout", "logout"); // // 配置不會被攔截的連結 順序判斷 filterChainDefinitionMap.put("/druid/**", "anon"); filterChainDefinitionMap.put("/static/**", "anon"); // filterChainDefinitionMap.put("/ajaxLogin", "anon"); filterChainDefinitionMap.put("/login", "anon"); // filterChainDefinitionMap.put("/**", "authc"); filterChainDefinitionMap.put("/**", "anon"); //配置shiro預設登入介面地址,前後端分離中登入介面跳轉應由前端路由控制,後臺僅返回json資料 shiroFilterFactoryBean.setLoginUrl("/unauth"); // 登入成功後要跳轉的連結 // shiroFilterFactoryBean.setSuccessUrl("/index"); //未授權介面; // shiroFilterFactoryBean.setUnauthorizedUrl("/403"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public SecurityManager securityManager(@Qualifier("myShiroRealm") MyShiroRealm myShiroRealm) { System.out.println("securityManager 執行----------------------"); DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm); // 自定義session管理 使用redis securityManager.setSessionManager(sessionManager()); // 自定義快取實現 使用redis // securityManager.setCacheManager(cacheManager()); return securityManager; } /** * 憑證匹配器 * (由於我們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了 * ) * * @return */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");//雜湊演算法:這裡使用MD5演算法; hashedCredentialsMatcher.setHashIterations(2);//雜湊的次數,比如雜湊兩次,相當於 md5(md5("")); return hashedCredentialsMatcher; } @Bean public MyShiroRealm myShiroRealm() { MyShiroRealm myShiroRealm = new MyShiroRealm(); // myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return myShiroRealm; } //自定義sessionManager @Bean public SessionManager sessionManager() { MySessionManager mySessionManager = new MySessionManager(); mySessionManager.setSessionDAO(redisSessionDAO()); return mySessionManager; } /** * 配置shiro redisManager * <p> * 使用的是shiro-redis開源外掛 * * @return */ @ConfigurationProperties(prefix = "redis.shiro") public RedisManager redisManager() { return new RedisManager(); } /** * cacheManager 快取 redis實現 * <p> * 使用的是shiro-redis開源外掛 * * @return */ @Bean public RedisCacheManager cacheManager() { RedisCacheManager redisCacheManager = new RedisCacheManager(); redisCacheManager.setRedisManager(redisManager()); return redisCacheManager; } /** * RedisSessionDAO shiro sessionDao層的實現 通過redis * <p> * 使用的是shiro-redis開源外掛 */ @Bean public RedisSessionDAO redisSessionDAO() { RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); redisSessionDAO.setRedisManager(redisManager()); // Custom your redis key prefix for session management, if you doesn't define this parameter, // shiro-redis will use 'shiro_redis_session:' as default prefix // redisSessionDAO.setKeyPrefix(""); return redisSessionDAO; } /** * 開啟shiro aop註解支援. * 使用代理方式;所以需要開啟程式碼支援; * * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager")SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } /** * 註冊全域性異常處理 * @return */ @Bean(name = "exceptionHandler") public HandlerExceptionResolver handlerExceptionResolver() { return new MyExceptionHandler(); } }
myshirorealm配置
package com.rdhl.dds.config; import com.rdhl.dds.main.entity.Dictoper; import com.rdhl.dds.system.entity.SRoleInfo; import com.rdhl.dds.main.service.DictoperService; import com.rdhl.dds.system.service.SRoleInfoService; 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.session.Session; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.List; /** * Created by Administrator on 2017/12/11. * 自定義許可權匹配和賬號密碼匹配 */ @Component(value="shiroRealm") public class MyShiroRealm extends AuthorizingRealm { @Resource private SRoleInfoService sysRoleService; @Resource private DictoperService dictoperService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("doGetAuthorizationInfo-------------------------------"); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); Dictoper userInfo = (Dictoper) principals.getPrimaryPrincipal(); try { List<SRoleInfo> roles = sysRoleService.findRoleById(userInfo.getRoleId()); //給使用者加角色 for (SRoleInfo role : roles) { authorizationInfo.addRole(role.getRoleName()); } List<String> sysPermissions = dictoperService.getStringPermissionsByUser(userInfo.getOperid()); authorizationInfo.addStringPermissions(sysPermissions); } catch (Exception e) { e.printStackTrace(); } return authorizationInfo; } /*主要是用來進行身份認證的,也就是說驗證使用者輸入的賬號和密碼是否正確。*/ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("doGetAuthorizationInfo name ----------------------"); //獲取使用者的輸入的賬號. String userName = (String) token.getPrincipal();//使用者名稱 String password = new String((char[])token.getCredentials()); //得到密碼 if(null != userName && null != password){ return new SimpleAuthenticationInfo(userName, password, getName()); }else{ return null; } } /** * 將一些資料放到ShiroSession中,以便於其它地方使用 * @see 比如Controller,使用時直接用HttpSession.getAttribute(key)就可以取到 */ private void setSession(Object key, Object value){ Subject currentUser = SecurityUtils.getSubject(); if(null != currentUser){ Session session = currentUser.getSession(); System.out.println("Session預設超時時間為[" + session.getTimeout() + "]毫秒"); if(null != session){ session.setAttribute(key, value); } } } }
一隻穿雲箭,請求支援啊