Spring Boot 整合 Shiro ,兩種方式全總結!

在 Spring Boot 中作權限管理,通常來講,主流的方案是 Spring Security ,可是,僅僅從技術角度來講,也可使用 Shiro。java

今天鬆哥就來和你們聊聊 Spring Boot 整合 Shiro 的話題!git

通常來講,Spring Security 和 Shiro 的比較以下:github

  1. Spring Security 是一個重量級的安全管理框架;Shiro 則是一個輕量級的安全管理框架
  2. Spring Security 概念複雜,配置繁瑣;Shiro 概念簡單、配置簡單
  3. Spring Security 功能強大;Shiro 功能簡單
  4. ...

雖然 Shiro 功能簡單,可是也能知足大部分的業務場景。因此在傳統的 SSM 項目中,通常來講,能夠整合 Shiro。web

在 Spring Boot 中,因爲 Spring Boot 官方提供了大量的很是方便的開箱即用的 Starter ,固然也提供了 Spring Security 的 Starter ,使得在 Spring Boot 中使用 Spring Security 變得更加容易,甚至只須要添加一個依賴就能夠保護全部的接口,因此,若是是 Spring Boot 項目,通常選擇 Spring Security 。spring

這只是一個建議的組合,單純從技術上來講,不管怎麼組合,都是沒有問題的。apache

在 Spring Boot 中整合 Shiro ,有兩種不一樣的方案:後端

  1. 第一種就是原封不動的,將 SSM 整合 Shiro 的配置用 Java 重寫一遍。
  2. 第二種就是使用 Shiro 官方提供的一個 Starter 來配置,可是,這個 Starter 並無簡化多少配置。

原生的整合

  • 建立項目

建立一個 Spring Boot 項目,只須要添加 Web 依賴便可:安全

項目建立成功後,加入 Shiro 相關的依賴,完整的 pom.xml 文件中的依賴以下:cookie

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-web</artifactId>
        <version>1.4.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.4.0</version>
    </dependency>
</dependencies>
  • 建立 Realm

接下來咱們來自定義核心組件 Realm:session

public class MyRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();
        if (!"javaboy".equals(username)) {
            throw new UnknownAccountException("帳戶不存在!");
        }
        return new SimpleAuthenticationInfo(username, "123", getName());
    }
}

在 Realm 中實現簡單的認證操做便可,不作受權,受權的具體寫法和 SSM 中的 Shiro 同樣,不贅述。這裏的認證表示用戶名必須是 javaboy ,用戶密碼必須是 123 ,知足這樣的條件,就能登陸成功!

  • 配置 Shiro

接下來進行 Shiro 的配置:

@Configuration
public class ShiroConfig {
    @Bean
    MyRealm myRealm() {
        return new MyRealm();
    }
    
    @Bean
    SecurityManager securityManager() {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(myRealm());
        return manager;
    }
    
    @Bean
    ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager());
        bean.setLoginUrl("/login");
        bean.setSuccessUrl("/index");
        bean.setUnauthorizedUrl("/unauthorizedurl");
        Map<String, String> map = new LinkedHashMap<>();
        map.put("/doLogin", "anon");
        map.put("/**", "authc");
        bean.setFilterChainDefinitionMap(map);
        return bean;
    }
}

在這裏進行 Shiro 的配置主要配置 3 個 Bean :

  1. 首先須要提供一個 Realm 的實例。
  2. 須要配置一個 SecurityManager,在 SecurityManager 中配置 Realm。
  3. 配置一個 ShiroFilterFactoryBean ,在 ShiroFilterFactoryBean 中指定路徑攔截規則等。
  4. 配置登陸和測試接口。

其中,ShiroFilterFactoryBean 的配置稍微多一些,配置含義以下:

  • setSecurityManager 表示指定 SecurityManager。
  • setLoginUrl 表示指定登陸頁面。
  • setSuccessUrl 表示指定登陸成功頁面。
  • 接下來的 Map 中配置了路徑攔截規則,注意,要有序。

這些東西都配置完成後,接下來配置登陸 Controller:

@RestController
public class LoginController {
    @PostMapping("/doLogin")
    public void doLogin(String username, String password) {
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(new UsernamePasswordToken(username, password));
            System.out.println("登陸成功!");
        } catch (AuthenticationException e) {
            e.printStackTrace();
            System.out.println("登陸失敗!");
        }
    }
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
    @GetMapping("/login")
    public String  login() {
        return "please login!";
    }
}

測試時,首先訪問 /hello 接口,因爲未登陸,因此會自動跳轉到 /login 接口:

而後調用 /doLogin 接口完成登陸:

再次訪問 /hello 接口,就能夠成功訪問了:

使用 Shiro Starter

上面這種配置方式實際上至關於把 SSM 中的 XML 配置拿到 Spring Boot 中用 Java 代碼從新寫了一遍,除了這種方式以外,咱們也能夠直接使用 Shiro 官方提供的 Starter 。

  • 建立工程,和上面的同樣

建立成功後,添加 shiro-spring-boot-web-starter ,這個依賴能夠代替以前的 shiro-webshiro-spring 兩個依賴,pom.xml 文件以下:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring-boot-web-starter</artifactId>
        <version>1.4.0</version>
    </dependency>
</dependencies>
  • 建立 Realm

這裏的 Realm 和前面的同樣,我就再也不贅述。

  • 配置 Shiro 基本信息

接下來在 application.properties 中配置 Shiro 的基本信息:

shiro.sessionManager.sessionIdCookieEnabled=true
shiro.sessionManager.sessionIdUrlRewritingEnabled=true
shiro.unauthorizedUrl=/unauthorizedurl
shiro.web.enabled=true
shiro.successUrl=/index
shiro.loginUrl=/login

配置解釋:

  1. 第一行表示是否容許將sessionId 放到 cookie 中
  2. 第二行表示是否容許將 sessionId 放到 Url 地址攔中
  3. 第三行表示訪問未獲受權的頁面時,默認的跳轉路徑
  4. 第四行表示開啓 shiro
  5. 第五行表示登陸成功的跳轉頁面
  6. 第六行表示登陸頁面
  • 配置 ShiroConfig
@Configuration
public class ShiroConfig {
    @Bean
    MyRealm myRealm() {
        return new MyRealm();
    }
    @Bean
    DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(myRealm());
        return manager;
    }
    @Bean
    ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
        definition.addPathDefinition("/doLogin", "anon");
        definition.addPathDefinition("/**", "authc");
        return definition;
    }
}

這裏的配置和前面的比較像,可是再也不須要 ShiroFilterFactoryBean 實例了,替代它的是 ShiroFilterChainDefinition ,在這裏定義 Shiro 的路徑匹配規則便可。

這裏定義完以後,接下來的登陸接口定義以及測試方法都和前面的一致,我就再也不贅述了。你們能夠參考上文。

總結

本文主要向你們介紹了 Spring Boot 整合 Shiro 的兩種方式,一種是傳統方式的 Java 版,另外一種則是使用 Shiro 官方提供的 Starter,兩種方式,不知道你們有沒有學會呢?

本文案例,我已經上傳到 GitHub ,歡迎你們 star:https://github.com/lenve/javaboy-code-samples

關於本文,有問題歡迎留言討論。

關注公衆號牧碼小子,專一於 Spring Boot+微服務以及先後端分離等全棧技術,按期視頻教程分享,關注後回覆 Java ,領取鬆哥爲你精心準備的 Java 乾貨!

相關文章
相關標籤/搜索