1. 程式人生 > >Springboot整合shiro錯誤記錄

Springboot整合shiro錯誤記錄

搞了一天,遇到大大小小的問題,參考了無數前輩的資料,最後貌似走通了。教程就不放了,放兩個我遇到的問題

package com.xxx.config;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
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;

@Configuration
public class ShiroConfiguration {
	//將自己的驗證方式加入容器
	@Bean
    public MyRealm myRealm() {
        MyRealm myRealm = new MyRealm();
        return myRealm;
    }
	/**
     * ShiroFilterFactoryBean 處理攔截資原始檔問題。
     * 注意:單獨一個ShiroFilterFactoryBean配置是或報錯的,以為在
     * 初始化ShiroFilterFactoryBean的時候需要注入:SecurityManager
     *
        Filter Chain定義說明
       1、一個URL可以配置多個Filter,使用逗號分隔
       2、當設定多個過濾器時,全部驗證通過,才視為通過
       3、部分過濾器可指定引數,如perms,roles
     *
     */
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager){
       System.err.println("ShiroConfiguration.shirFilter()");
       ShiroFilterFactoryBean shiroFilterFactoryBean  = new ShiroFilterFactoryBean();
        // 必須設定 SecurityManager 
       shiroFilterFactoryBean.setSecurityManager(securityManager);
       /**
        * 	anon:所有url都都可以匿名訪問;
  			authc: 需要認證才能進行訪問;
  			user:配置記住我或認證通過可以訪問;
        */
		// 攔截器.
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
		// 配置退出過濾器,其中的具體的退出程式碼Shiro已經替我們實現了
		filterChainDefinitionMap.put("/logout", "logout");
		// 防止登入成功之後下載favicon.ico
		filterChainDefinitionMap.put("/favicon.ico", "anon");
		filterChainDefinitionMap.put("/static/**", "anon");
		// <!-- 過濾鏈定義,從上向下順序執行,一般將 /**放在最為下邊 -->:這是一個坑呢,一不小心程式碼就不好使了;
		// <!-- authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問-->
		filterChainDefinitionMap.put("/**", "authc");
		// 如果不設定預設會自動尋找Web工程根目錄下的"/login.jsp"頁面
		shiroFilterFactoryBean.setLoginUrl("/login");
		// 登入成功後要跳轉的連結
		shiroFilterFactoryBean.setSuccessUrl("/index");
		// 未授權介面;
		shiroFilterFactoryBean.setUnauthorizedUrl("/403");

		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}
   
    @Bean
    public SecurityManager securityManager(){
       DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
       return securityManager;
    }
    //加入註解的使用,不加入這個註解不生效
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}

報錯資訊如下:

Configuration error:  No realms have been configured!  One or more realms must be present to execute an authentication attempt.

說明realm沒有配置成功.因為我是拷貝的程式碼,而且我拷貝的程式碼裡似乎漏掉了往securityManager新增realm的程式碼,所以報錯。

以為加上@bean這個註解之後,會反射自己拿之類的,所以我以為這個@bean並沒有起作用。所以自以為是的new了一個放進securityManager裡。

然後又報錯了,Spring注入Service失敗,又翻閱了些資料講到了shiro的執行比spring更高或者更前面。最後找到解決方案是realm注入的方式錯誤導致,不知道以bean的方式是否在spring載入後再注入。可能大概是吧...

最後貼一個正常的程式碼:這樣訪問一切正常

   @Bean
    public SecurityManager securityManager(@Qualifier("myRealm")MyRealm myRealm){
       DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
       securityManager.setRealm(myRealm);
       return securityManager;
    }