目录
-
一、SpringBoot整合Shiro
- 1、环境配置
- 2、静态资源
- 3、MyController
- 4、自定义UserRealm
- 5、ShiroConfig 配置类
<dependencies> <dependency> <groupId>com.github.theborakompanioni <dependency> <groupId>mysql <dependency> <groupId>org.apache.shiro <dependency> <groupId>org.springframework.boot private int id; private String name; private String pwd; private String perms; }
dao
@Repository @Mapper public interface UserMapper { @Select("SELECT * FROM user WHERE name = #{name}") public User queryUserByName(String name); }
service
@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public User queryUserByName(String name) { return userMapper.queryUserByName(name); } }
application.yml
spring: datasource: username: root password: 1111 url: jdbc:mysql://localhost:3306/springboot_shiro driver-class-name: com.mysql.cj.jdbc.Driver initialization-mode: always # 数据源更改为druid type: com.alibaba.druid.pool.DruidDataSource druid: # 连接池配置 # 配置初始化大小、最小、最大 initial-size: 1 min-idle: 1 max-active: 20 # 配置获取连接等待超时的时间 max-wait: 3000 validation-query: SELECT 1 FROM DUAL test-on-borrow: false test-on-return: false test-while-idle: true pool-prepared-statements: true time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000 filters: stat,wall,slf4j2、静态资源
跳转到目录
- index.html 首页
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"> <head> <meta charset="UTF-8"> <title>Title <shiro:guest> <a th:href="@{/toLogin}">登录 @GetMapping({"/", "/index"}) public String toIndex(Model model) { model.addAttribute("msg", "Hello Shiro !"); return "index"; } @GetMapping("/user/add") public String add() { return "user/add"; } @GetMapping("/user/update") public String update() { return "user/update"; } @GetMapping("/toLogin") public String toLogin() { return "login"; } @PostMapping("/login") // 会执行UserRealm的认证方法 public String login(String username, String password, Model model) { // 获取当前的用户 Subject subject = SecurityUtils.getSubject(); // 封装用户的登录数据(这个数据在doGetAuthenticationInfo中拿到了) UsernamePasswordToken token = new UsernamePasswordToken(username, password); // 执行登录的方法 try { subject.login(token); return "index"; } catch (UnknownAccountException e) { // 用户名不存在异常 model.addAttribute("msg", "用户名不存在/错误"); return "login"; // 跳转到登录页 } catch (IncorrectCredentialsException e) { // 密码错误 model.addAttribute("msg", "密码错误"); return "login"; // 跳转到登录页 } } @RequestMapping("/noauth") @ResponseBody public String unauthorized() { return "未经授权无法访问此页面!"; } }4、自定义UserRealm
跳转到目录
/** * Description: 自定义UserRealm, 需要继承AuthorizingRealm * * @author zygui * @date 2020/4/23 11:28 */ public class UserRealm extends AuthorizingRealm { @Autowired private UserService userService; /* 用户在前台登录的时候, 此时会调用下面的两个方法 */ // 授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了->授权UserRealm.doGetAuthorizationInfo"); // 用来存储授权的对象 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 给用户添加user:add权限 //info.addStringPermission("user:add"); // 拿到当前登录的这个对象(认证中的user) Subject subject = SecurityUtils.getSubject(); User currentUser = (User) subject.getPrincipal(); // 从数据库中获取该角色的权限,并授权 info.addStringPermission(currentUser.getPerms()); // 从数据库中获取角色的权限 return info; } // 认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("执行了->认证UserRealm.doGetAuthenticationInfo"); // 用户名,密码 // String name = "root"; // String password = "123"; UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken; // 从数据库中获取用户: userToken.getUsername()就是前台用户输入的用户名 User user = userService.queryUserByName(userToken.getUsername()); if (user == null) { return null; // 抛出异常 UnknowAccountException } // 用户名认证 // if (!userToken.getUsername().equals(name)) { // return null; // 抛出异常 UnknowAccountException // } // 密码认证, Shiro自动帮我们做; 加密了 return new SimpleAuthenticationInfo(user, user.getPwd(), ""); } }5、ShiroConfig 配置类
跳转到目录
shiro的内置过滤器详解:
/** * Description: shiro的配置类 * * @author zygui * @date 2020/4/23 11:25 */ @Configuration public class ShiroConfig { /* Shiro的三个核心! Subject: 用户 SecurityManager: 管理所有用户 Realm: 连接数据 */ // ShiroFilterFactoryBean: ShiroFilter过滤器的bean @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean() { ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean(); // 设置安全管理器(Bean的依赖注入) filterFactoryBean.setSecurityManager(defaultWebSecurityManager()); // 拦截操作 /* 添加shiro的内置过滤器 anon: 无需认证就可以访问 authc: 必须认证(登录)才能访问 user: 必须拥存在用户才能访问 perms: 拥有对某个资源的权限才能访问 roles: 拥有某个角色权限才能访问 */ HashMap<String, String> filterMap = new LinkedHashMap<>(); // 授权(必须是user用户有add权限才可以访问 filterMap.put("/user/add", "perms[user:add]"); filterMap.put("/user/update", "perms[user:update]"); // filterMap.put("/user/add", "authc"); // filterMap.put("/user/update", "authc"); filterMap.put("/user/*", "authc"); filterFactoryBean.setFilterChainDefinitionMap(filterMap); // 设置登录的请求 filterFactoryBean.setLoginUrl("/toLogin"); // 未授权页面 filterFactoryBean.setUnauthorizedUrl("/noauth"); return filterFactoryBean; } // DefaultWebSecurityManager @Bean public DefaultWebSecurityManager defaultWebSecurityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 依赖注入userRealm的bean securityManager.setRealm(userRealm()); return securityManager; } // 创建Realm对象; 需要自定义Realm(继承AuthorizingRealm) @Bean public UserRealm userRealm() { return new UserRealm(); } // 整合ShiroDialect, 用来整合 shiro thymeleaf @Bean public ShiroDialect shiroDialect() { return new ShiroDialect(); } }