Shiro-初体验/SpringBoot+MybatisPlus+Shiro综合
< 返回列表时间: 2020-07-03来源:OSCHINA
引入依赖 ... <!--MybatisPlus依赖--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- 引入shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency> <!--shrio和thymeleaf集成的扩展依赖,为了能在页面上使用xsln:shrio的标签 --> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency> ... 配置Realm:认证/授权 此处的各种service对应的实体类 是经典的RBAC权限三表 user表/role表/permission表(另外还有user_role表和role_permission表) public class UserRealm extends AuthorizingRealm { @Autowired private UserService userService; @Autowired private RoleService roleService; @Autowired private PermissionService permissionService; @Override public String getName() { return this.getClass().getSimpleName(); } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); ActiveUser activeUser = (ActiveUser) principals.getPrimaryPrincipal(); Integer type = activeUser.getUser().getType(); List<String> permissions = activeUser.getPermissions(); if (CarrentConstast.USER_TYPE_SUPER.equals(type)) { info.addStringPermission("*:*"); } else { if(null!= permissions && permissions.size()>0) { info.addStringPermissions(permissions); } } return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken token1 = (UsernamePasswordToken)token; String loginname = token1.getPrincipal().toString(); QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("loginname",loginname); User one = userService.getOne(queryWrapper); List<Permission> list = new ArrayList<>(); if(null != one) { ActiveUser activeUser = new ActiveUser(); QueryWrapper<Permission> qw = new QueryWrapper<>(); qw.eq("type", CarrentConstast.TYPE_PERMISSION); qw.eq("available",CarrentConstast.AVAILABLE_TRUE); Integer uid = one.getId(); Set<Integer> set = new HashSet<>(); List<Integer> rids = roleService.getAllRoleByUserId(uid); for (Integer rid : rids) { List<Integer> pids = roleService.getAllPermissionByRid(rid); set.addAll(pids); } if(null != set && set.size()>0) { qw.in("id",set); list = permissionService.list(qw); } List<String> percode = new ArrayList<>(); list.forEach(p->{ percode.add(p.getPercode()); }); activeUser.setPermissions(percode); activeUser.setUser(one); ByteSource credentialsSalt = ByteSource.Util.bytes(one.getSalt()); return new SimpleAuthenticationInfo(activeUser,one.getPwd(),credentialsSalt,this.getName()); } return null; } } shiro配置类 @Configuration @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass(value = { SecurityManager.class }) @ConfigurationProperties(prefix = "shiro") @Data public class ShiroAutoConfiguration { private static final String SHIRO_DIALECT = "shiroDialect"; private static final String SHIRO_FILTER = "shiroFilter"; // 加密方式 private String hashAlgorithmName = "md5"; // 散列次数 常量 // 默认的登陆页面 private String loginUrl = "/index.html"; // 在yml配置中已经配置了 通过注解@ConfigurationProperties(prefix = "shiro") 自动注入 private String[] anonUrls; private String logOutUrl; private String[] authcUlrs; /** * 声明凭证匹配器 */ @Bean("credentialsMatcher") public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); credentialsMatcher.setHashAlgorithmName(hashAlgorithmName); credentialsMatcher.setHashIterations(CarrentConstast.HASHITERATIONS); return credentialsMatcher; } /** * 声明userRealm */ @Bean("userRealm") public UserRealm userRealm(CredentialsMatcher credentialsMatcher) { UserRealm userRealm = new UserRealm(); // 注入凭证匹配器 userRealm.setCredentialsMatcher(credentialsMatcher); return userRealm; } /** * 配置SecurityManager */ @Bean("securityManager") public DefaultWebSecurityManager securityManager(UserRealm userRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 注入userRealm securityManager.setRealm(userRealm); return securityManager; } /** * 配置shiro的过滤器 */ @Bean(SHIRO_FILTER) public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean(); // 设置安全管理器 factoryBean.setSecurityManager(securityManager); // 设置未登陆的时要跳转的页面 factoryBean.setLoginUrl(loginUrl); Map<String, String> filterChainDefinitionMap = new HashMap<>(); // 设置放行的路径 if (anonUrls != null && anonUrls.length > 0) { for (String anon : anonUrls) { filterChainDefinitionMap.put(anon, "anon"); } } // 设置登出的路径 if (null != logOutUrl) { filterChainDefinitionMap.put(logOutUrl, "logout"); } // 设置拦截的路径 if (authcUlrs != null && authcUlrs.length > 0) { for (String authc : authcUlrs) { filterChainDefinitionMap.put(authc, "authc"); } } Map<String, Filter> filters=new HashMap<>(5); // filters.put("authc", new ShiroLoginFilter()); //配置过滤器 factoryBean.setFilters(filters); factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return factoryBean; } /** * 注册shiro的委托过滤器,相当于之前在web.xml里面配置的 * * @return */ @Bean public FilterRegistrationBean<DelegatingFilterProxy> delegatingFilterProxy() { FilterRegistrationBean<DelegatingFilterProxy> filterRegistrationBean = new FilterRegistrationBean<DelegatingFilterProxy>(); DelegatingFilterProxy proxy = new DelegatingFilterProxy(); proxy.setTargetFilterLifecycle(true); proxy.setTargetBeanName(SHIRO_FILTER); filterRegistrationBean.setFilter(proxy); return filterRegistrationBean; } /* 加入注解的使用,不加入这个注解不生效--开始 */ /** * * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } @Bean public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } /* 加入注解的使用,不加入这个注解不生效--结束 */ /** * 这里是为了能在html页面引用shiro标签,上面两个函数必须添加,不然会报错 * * @return */ @Bean(name = SHIRO_DIALECT) public ShiroDialect shiroDialect() { return new ShiroDialect(); } } yml配置 #配置数据源的属性 spring: datasource: druid: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/erp?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC username: root password: 123456 max-active: 20 max-wait: 5000 initial-size: 1 filters: stat,log4j,wall validationQuery: SELECT 'x' #验证连接 enable: true #监控配置 stat-view-servlet: enabled: true login-username: root login-password: 123456 allow: deny: url-pattern: /druid/* #thymeleaf的配置 thymeleaf: cache: false enabled: true # web-stat-filter: # enabled: true # exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" # 接受前端json jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 #配置mybatisplus mybatis-plus: mapper-locations: - classpath:mappers/*/*Mapper.xml global-config: db-config: id-type: auto banner: true configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #shiro的配置 shiro: hash-algorithm-name: md5 hash-iterations: 2 anon-urls: - /index.html* - /sys/toLogin* - /login/login* - /resources/** login-url: /index.html log-out-url: /login/logout* authc-ulrs: - /** 登录控制器 @RestController @RequestMapping("login") public class LoginController { @Autowired private LoginfoService loginfoService; @RequestMapping("/login") public ResponseData login(Model model, String loginname, String pwd) { UsernamePasswordToken token = new UsernamePasswordToken(loginname,pwd); try { Subject subject = SecurityUtils.getSubject(); subject.login(token); ActiveUser activeUser = (ActiveUser) subject.getPrincipal(); WebUtil.getSession().setAttribute("activeUser",activeUser); Loginfo loginfo = new Loginfo(); loginfo.setLoginname(activeUser.getUser().getName()+"-"+activeUser.getUser().getLoginname()); loginfo.setLogintime(LocalDateTime.now()); loginfo.setLoginip(WebUtil.getRequest().getRemoteAddr().toString()); loginfoService.save(loginfo); return ResponseData.LOGIN_SUCCESS; } catch (AuthenticationException e) { e.printStackTrace(); return ResponseData.LOGIN_ERROR; } } } 分页插件配置 @Configuration @ConditionalOnClass(value = {PaginationInterceptor.class}) public class MyBatisConfig { @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } }
热门排行