Shiro是一个比较常用的安全认证框架,简单又实用。在Spring Boot中整合Shiro有两种方式:
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.
在网上找了各种教程寻找解决的办法,大部分都说是过滤器的问题,要在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> 复制代码
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"; } } 复制代码
积少成多,滴水穿石!