Предотвращение внутренних ям Java — Spring Boot интегрирует Shiro

Shiro

ShiroЭто широко используемая структура аутентификации безопасности, простая и практичная. Есть два способа интегрировать Широ в Spring Boot:

  • 1. Реализовать конфигурацию в традиционном SSM+Shiro на Java.
  • 2. Используйте автоматические зависимости конфигурации, предоставленные Широ.
    В этой статье выбран второй практичный способ интеграции, но при использовании 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.
  • Сообщение об ошибке почтальона выглядит следующим образом

Я нашел различные руководства в Интернете, чтобы найти решение, в большинстве из них говорится, что это проблема с фильтром, и вам нужно добавить DelegatingFilterProxy в web.xml. Однако интеграция этой статьи тестируется в среде Spring Boot, и файл web.xml не используется.Если добавить файл web.xml, весь проект будет выглядеть невзрачным. Поэтому решительно отказывайтесь от этого решения. Как это решить? Позже, попросив совета у коллег, я понял, что для использования официально предоставленной Широ автоматической конфигурации необходимы следующие зависимости.

<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());
    }
}
  • Создать ШироКонфиг
@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
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";
    }
}
  • Результаты теста следующие

Сложите, бросьте воду сквозь камень!