1. 程式人生 > 程式設計 >解決springboot+shiro 許可權攔截失效的問題

解決springboot+shiro 許可權攔截失效的問題

最近因為專案需要,接觸了shiro。新手入門

發現許可權攔截失效,

一直以為是以為授權和DB的問題

研究了一個下午,終於發現了問題所在

解決springboot+shiro 許可權攔截失效的問題

我的訪問路徑沒有寫前面的斜槓!!,而DB中的資源路徑是可以省略的,崩潰了吧

但是問題來了,為什麼在其他地方可以忽略掉前面的小斜槓呢?

經過幾分鐘的搗鼓發現,在springboot中,不論是thymeleaf的模板也好(我用的thymeleaf),還是後端程式碼也好,底層會自動補全這個斜槓

問題解決!!

補充知識:SpringBoot整合shiro的一個完整的小案例

SpringBoot整合配置版的shiro很簡單,邏輯清

首先在pom.xml的配置如下,shiro使用快取ehcache

    <dependency>
      <groupId>net.sf.ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>2.10.4</version>
    </dependency>
    <!-- shiro spring. -->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.2.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>1.2.2</version>
    </dependency>
    <!-- shiro ehcache -->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-ehcache</artifactId>
      <version>1.2.2</version>
    </dependency>

接著配置shiro

@Configuration
public class ShiroConfig {

  @Bean 
  public ShiroFilterFactoryBean shirFilter(DefaultWebSecurityManager securityManager) { 

    ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); 
    // 必須設定 SecurityManager 
    shiroFilter.setSecurityManager(securityManager); 
    // 攔截器 
    Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>(); 
    // 設定login URL 
    shiroFilter.setLoginUrl("/login"); 
    // 登入成功後要跳轉的連結 
    shiroFilter.setSuccessUrl("/main"); 
    filterChainDefinitionMap.put("/webjars/**","anon");
    filterChainDefinitionMap.put("/druid/**","anon");
    //靜態資源的處理
    filterChainDefinitionMap.put("/js/**","anon");
    filterChainDefinitionMap.put("/css/**","anon");
    filterChainDefinitionMap.put("/asserts/**","anon");
    filterChainDefinitionMap.put("/fonts/**","anon");
    filterChainDefinitionMap.put("/images/**","anon");

    // 退出系統的過濾器 
    filterChainDefinitionMap.put("/logout","logout");
    filterChainDefinitionMap.put("/login","anon"); 

    filterChainDefinitionMap.put("/kaptcha","anon");

    filterChainDefinitionMap.put("/**","authc"); 
    shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap); 
    return shiroFilter; 
  } 

  @Bean 
  public HashedCredentialsMatcher hashedCredentialsMatcher() { 
    HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); 
    hashedCredentialsMatcher.setHashAlgorithmName("MD5");
    hashedCredentialsMatcher.setHashIterations(1024);
    return hashedCredentialsMatcher; 
  } 

  @Bean
  public ShiroRealm shiroRealm(HashedCredentialsMatcher hashedCredentialsMatcher) {
    ShiroRealm shiroRealm = new ShiroRealm();
    shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher);
    return shiroRealm;
  }
  //shiro使用快取ehcachae
  @Bean
  public EhCacheManager ehCacheManager() {
    EhCacheManager ehCacheManager = new EhCacheManager();
    ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
    return ehCacheManager;

  }

  @Bean("sessionManager")
  public SessionManager sessionManager(){
    DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
    sessionManager.setSessionValidationSchedulerEnabled(true);
    sessionManager.setSessionIdCookieEnabled(true);
    return sessionManager;
  }

  @Bean("securityManager")
  public DefaultWebSecurityManager securityManager(ShiroRealm shiroRealm,SessionManager sessionManager) {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(shiroRealm);
    securityManager.setSessionManager(sessionManager);

    return securityManager;
  }

  @Bean("lifecycleBeanPostProcessor")
  public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
  }

  @Bean
  public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
    proxyCreator.setProxyTargetClass(true);
    return proxyCreator;
  }

  @Bean
  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
    advisor.setSecurityManager(securityManager);
    return advisor;
  }
}

在配置中提到的realm如下配置

public class ShiroRealm extends AuthorizingRealm {
  @Autowired
  private UserService userService;

  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    UsernamePasswordToken upToken = (UsernamePasswordToken) token;
    // 取出表單使用者名稱
    String username = upToken.getUsername();
    // 查詢是否有該使用者
    if (userService.getByName(username) == null) {
      throw new UnknownAccountException("使用者不存在!");
    }
    // 靠使用者名稱從資料庫查詢該使用者的全部資訊
    User user = userService.getByName(username);
    // 傳入:使用者名稱,加密後的密碼,鹽值,該realm的名字,加密演算法和加密次數在已經在配置檔案中指定
    SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,user.getPassword(),ByteSource.Util.bytes(username),getName());
    return info;
  }

  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    // 1. 從 PrincipalCollection 中來獲取登入使用者的資訊
    Object principal = principals.getPrimaryPrincipal();
    // 2. 利用登入的使用者的資訊來..當前使用者的角色或許可權(可能需要查詢資料庫)
    Set<String> roles = new HashSet<String>();
    roles.add("user");
    if ("admin".equals(principal)) {
      roles.add("admin");
    }
    // 3. 建立 SimpleAuthorizationInfo,並設定其 reles 屬性
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
    // 4. 返回 SimpleAuthorizationInfo 物件.
    return info;
  }
}

由於我做的平臺只有一個管理員就不寫註冊了,這時手動算出一個admin使用者的密碼

  public static void main(String[] args) {

    Object result = new SimpleHash("MD5","123456",ByteSource.Util.bytes("admin"),1024);
    System.out.println(result);
  }

最後寫登入的Controller

@Controller
public class LoginController {
  // 處理登入邏輯
  @PostMapping("/login")
  public String login(String username,String password,String kaptcha,HttpSession session,Map<String,Object> map) {
    Subject currentUser = SecurityUtils.getSubject();
    if (!currentUser.isAuthenticated()) {
      // 把使用者名稱和密碼封裝為 UsernamePasswordToken 物件
      UsernamePasswordToken token = new UsernamePasswordToken(username,password);
      // 設定為rememberme
      token.setRememberMe(true);
      try {
        // 執行登入.
        currentUser.login(token);
      }
      // 所有認證時異常的父類
      catch (AuthenticationException ae) {
        map.put("password","輸入的使用者名稱或密碼錯誤");
        log.info("登入失敗: " + ae.getMessage());
        return "login";
      }
    }
    if (!session.getAttribute("code").equals(kaptcha)) {
      map.put("kaptcha","輸入的驗證碼錯誤");
      return "login";
    }

    session.setAttribute("loginUser","user");
    return "main";
  }
}

以上這篇解決springboot+shiro 許可權攔截失效的問題就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。