IniRealm
如果我们想在SpringBoot中进行使用Shiro, 那么我们肯定是需要围绕如下环节进行研究.
创建 pom.xml
:
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.3</version>
</parent><dependencies><dependency> <!-- 导入 shiro-spring, 会自动引入 shiro-core, shiro-web --><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.1</version></dependency><dependency> <!-- springboot 没有提供对 shiro 的自动配置, shiro 的自动配置需手动完成 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency> <!-- 引入 thymeleaf 模板引擎 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency> <!-- 引入 lombok --><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency> <!-- 引入 druid-spring-boot-starter, 自动配置 Druid --><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.17</version></dependency><dependency> <!-- 会自动引入 mybatis, mybatis-spring, spring-boot-starter-jdbc --><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><dependency> <!-- 引入 mysql 扩展 --><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency><dependency> <!-- 引入 SpringBoot 测试依赖 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency>
</dependencies>
创建/resources/application.yml
:
server: # 设置启动端口port: 80spring:thymeleaf: # 设置 thymeleaf 模板存放位置prefix: "classpath:/templates/"suffix: ".html"datasource:druid: # 设置数据库连接url: jdbc:mysql://localhost:3306/shiro?useSSL=true&characterEncoding=utf-8&useUnicode=trueusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Drivermvc:static-path-pattern: /static/** # 设置静态资源访问路径web:resources:static-locations: classpath:/static/** # 设置静态资源保存目录mybatis:mapper-locations: classpath:mappers/*.xml # 设置 mybatis mapper文件存放位置, 用于扫描type-aliases-package: com.heihu577.bean # 设置 JavaBean 存放位置定义com.heihu577.MainApp类:@SpringBootApplication
public class MainApp {public static void main(String[] args) {ConfigurableApplicationContext ioc = SpringApplication.run(MainApp.class, args);}
}
因为Shiro需要我们手动配置, 所以我们定义com.heihu577.config.ShiroAutoConfiguration类如下:
@Configuration
public class ShiroAutoConfiguration {@Beanpublic IniRealm getIniRealm() { // 先使用 IniReal 做演示IniRealm iniRealm = new IniRealm("classpath:shiro.ini");/* classpath:shiro.ini 文件内容如下:[users]heihuUser=heihuPass,sellerhacker=123456,ckmgradmin=admin888,admin[roles]seller=order-add,order-del,order-listckmgr=ck-add,ck-del,ck-listadmin=**/return iniRealm;}@Beanpublic SecurityManager getSecurityManager(IniRealm iniRealm) {DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();defaultWebSecurityManager.setRealm(iniRealm); // 要想完成校验, 需要 Realm// SecurityUtils.setSecurityManager(defaultWebSecurityManager); // 设置 SecurityUtils 下的 SecurityManagerreturn defaultWebSecurityManager;}@Beanpublic ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 准备一个拦截器, 用于拦截用户请求shiroFilterFactoryBean.setSecurityManager(securityManager); // 进行数据校验的核心是 SecurityManager, 所以这里需要配置 SecurityManager// 配置拦截规则...HashMap<String,String> filterMap = new HashMap();filterMap.put("/", "anon"); // anon 匿名用户可访问filterMap.put("/login", "anon"); // 对 login.html 不拦截filterMap.put("/register", "anon"); // 对 register.html 不拦截filterMap.put("/user/login", "anon");filterMap.put("/**", "authc"); // authc 认证用户可访问filterMap.put("/static/**", "anon"); // 对 /static/** 都不拦截// user: 使用 RememberMe 用户可访问// perms: 对应权限可访问// role: 对应角色可访问shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); // 将规则设置进来shiroFilterFactoryBean.setLoginUrl("/login"); // 设置默认的登录界面shiroFilterFactoryBean.setUnauthorizedUrl("/"); // 设置未授权访问的跳转URLreturn shiroFilterFactoryBean;}
}
随后定义com.heihu577.controller.PageController && com.heihu577.controller.UserController控制器如下:
@Controller
public class PageController {@RequestMapping(value = {"/"})public String index() {return "index"; // 跳转 thymeleaf 下的 index.html 模板引擎}@RequestMapping("/login")public String login() {return "login";}
}@Controller
@RequestMapping("/user")
public class UserController {@Resourceprivate UserServiceImpl userService; // 自动注入 userService@PostMapping("/login")public String login(String username, String password) {try {userService.login(username, password);System.out.println("登陆成功!");return "index"; // 登录成功去 index 页面.} catch (Exception e) { // 使用 try-catch 进行判断登录状态System.out.println("登录失败!");return "login"; // 登录失败去 login 页面, 若想要注入数据, 使用 Model 即可}}
}
定义两个模板如下:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>主页</title>
</head>
<body><h1>Hello World!</h1>
</body>
</html>
<!-- login.html -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>登录表单</title>
</head>
<body><form action="/user/login" method="post">u: <input type="text" name="username"/><br>p: <input type="password" name="password"/><br><input type="submit"></form>
</body>
</html>
定义com.heihu577.service.UserServiceImpl
如下:
@Service
public class UserServiceImpl {public void login(String username, String password) throws Exception { // 登陆失败会抛出异常, 登陆成功没返回值UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);Subject subject = SecurityUtils.getSubject();subject.login(usernamePasswordToken); // 发送登录请求.}
}
最终可以实现用户登录, 判断账号密码是否正确. 当前为了学习方便, 使用了 IniRealm 进行演示, 其中思路如下.
而如果我们想要使用JdbcRealm
, 那么我们则需要配置相应的Realm.