Java後端避坑——Spring Boot整合Shiro

陳小北發表於2019-04-17

Shiro 是一個比較常用的安全認證框架,簡單又實用。在Spring Boot中整合Shiro有兩種方式:

  • 1.將傳統的SSM+Shiro中的配置用Java實現
  • 2.使用Shiro官方提供的自動化配置依賴
    本文選擇實用第二種方式進行整合,但是在使用Postman進行測試的時候卻出現瞭如下錯誤:

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.

注:執行環境為:IntelliJ IDEA 2018.1.1
  • Postman 錯誤提示如下

Java後端避坑——Spring Boot整合Shiro
在網上找了各種教程尋找解決的辦法,大部分都說是過濾器的問題,要在web.xml中新增 DelegatingFilterProxy。但本文的整合是在Spring Boot環境中進行測試的,並未使用web.xml檔案,如果加上web.xml檔案會顯得整個工程不倫不類的。因此果斷捨棄這種解決方法。那應該怎麼解決呢? 後面經過向同事請教,才知道使用Shiro官方提供的自動化配置需要使用以下這種依賴

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-web-starter</artifactId>
    <version>1.4.0</version>
</dependency>
複製程式碼

而不是使用Java實現SSM+Shiro中的配置所採用的依賴

<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>
複製程式碼

正確的程式碼示例如下

  • 新增依賴
<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>
複製程式碼
  • 自定義一個MyRealm
public class MyRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = ((UsernamePasswordToken) token).getUsername();
        if (!"zhangsan".equals(username)) {
            throw new UnknownAccountException("賬戶不存在");
        }
        return new SimpleAuthenticationInfo(username, "123", getName());
    }
}
複製程式碼
  • 建立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;
    }
}
複製程式碼
  • 建立一個Controller進行測試
@Controller
public class ShiroController {

    @PostMapping("/doLogin")
    public String doLogin(String username, String password) {
        try {
            Subject subject = SecurityUtils.getSubject();
            subject.login(new UsernamePasswordToken(username, password));
            return "redirect:/index";//驗證成功跳轉頁面
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }
        return "redirect:/login";//驗證失敗跳轉頁面
    }

    @GetMapping("/index")
    @ResponseBody
    public String index() {
        return "index";
    }

    @GetMapping("/login")
    @ResponseBody
    public String login() {
        return "login";
    }
}
複製程式碼
  • 測試結果如下

Java後端避坑——Spring Boot整合Shiro

積少成多,滴水穿石!

相關文章