springboot集成shiro使用redis缓存,shiro与springboot整合

  springboot集成shiro使用redis缓存,shiro与springboot整合

  

目录

1.准备工作2.编写索引、登录、注册三个JSP3 .实现用户、角色、权限三个波乔4 .实现控制器、服务、道5 .实现SaltUtil和ApplicationContextUtil两个工具类6.实现核心四郎7。实现使用心得分布式缓存演示源码

 

  此演示用跳羚希罗简单实现了登陆、注册、认证、授权的功能,并用存储做分布式缓存提高性能。

  

1.准备工作

导入pom.xml

 

  ?可扩展标记语言版本=1.0 编码=UTF八号?项目xmlns= http://maven。阿帕奇。org/POM/4。0 .0 xmlns : xsi= http://www。w3。org/2001/XML schema-instance xsi :架构位置= http://maven。阿帕奇。org/POM/4。0 .0 http://maven.apache.org/xsd/maven-4.0.0.xsd模型版本4。0 .0/模型版本父groupIdorg.springframework.boot/groupId工件id spring-boot-starter-parent/工件id version2.3.2.RELEASE/version/parent groupIdcom.ego/groupId工件-引入jsp依赖-groupId org . Apache . Tomcat . embed/groupId附属区

  artifactId>tomcat-embed-jasper</artifactId> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.5.3</version> </dependency> <!-- mybatis plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> </dependency> <!-- Druid数据源 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <!-- Mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.5.3</version> </dependency> <!-- 引入redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies></project>配置yml文件

  

spring: # 设置视图模板为jsp mvc: view: prefix: / suffix: .jsp datasource: type: com.alibaba.druid.pool.DruidDataSource druid: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=UTC username: root password: root # 监控统计拦截的filters filters: stat,wall,log4j,config # 配置初始化大小/最小/最大 initial-size: 5 min-idle: 5 max-active: 20 # 获取连接等待超时时间 max-wait: 60000 # 间隔多久进行一次检测,检测需要关闭的空闲连接 time-between-eviction-runs-millis: 60000 # 一个连接在池中最小生存的时间 min-evictable-idle-time-millis: 300000 validation-query: SELECT x test-while-idle: true test-on-borrow: false test-on-return: false # 打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false pool-prepared-statements: false max-pool-prepared-statement-per-connection-size: 20 redis: host: 127.0.0.1 port: 6379 password: abc123456 database: 0mybatis-plus: type-aliases-package: com.ego.pojo configuration: map-underscore-to-camel-case: true

 

  

2.编写index,login,register三个JSP

<%--解决页面乱码--%><%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %><!doctype html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>index</title></head><body> <form action="${pageContext.request.contextPath}/user/login" method="post"> 用户名:<input type="text" name="username" > <br/> 密码 : <input type="text" name="password"> <br> <input type="submit" value="登录"> </form></body></html><%--解决页面乱码--%><%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %><%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %><!doctype html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>index</title></head><body><h1>系统主页</h1><a href="${pageContext.request.contextPath}/user/logout">退出用户</a><ul> <%-- admin角色的用户能同时拥有用户管理和订单管理的权限,user角色的用户只拥有订单管理的权限 --%> <shiro:hasRole name="admin"> <li> <a href="">用户管理</a> </li> </shiro:hasRole> <%-- admin角色的用户对订单有增删改查的权限,user角色的用户只能查看订单 --%> <shiro:hasAnyRoles name="admin,user"> <li> <a href="">订单管理</a> <ul> <shiro:hasPermission name="order:add:*"> <li><a href="">新增</a></li> </shiro:hasPermission> <shiro:hasPermission name="order:del:*"> <li><a href="">删除</a></li> </shiro:hasPermission> <shiro:hasPermission name="order:upd:*"> <li><a href="">修改</a></li> </shiro:hasPermission> <shiro:hasPermission name="order:find:*"> <li><a href="">查询</a></li> </shiro:hasPermission> </ul> </li> </shiro:hasAnyRoles></ul></body></html><%--解决页面乱码--%><%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %><!doctype html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>register</title></head><body><h1>用户注册</h1><form action="${pageContext.request.contextPath}/user/register" method="post"> 用户名:<input type="text" name="username" > <br/> 密码 : <input type="text" name="password"> <br> <input type="submit" value="立即注册"></form></body></html>

 

  

3.实现User、Role、Permission三个POJO

package com.ego.pojo;import com.baomidou.mybatisplus.annotation.*;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.Serializable;import java.util.ArrayList;import java.util.List;/** * @author 袁梦达 2019012364 */@Data@NoArgsConstructor@AllArgsConstructor@TableName("t_user")@ApiModel("用户实体类")public class User implements Serializable { /** 数据库中设置该字段自增时该注解不能少 **/ @TableId(type = IdType.AUTO) @ApiModelProperty(name = "id", value = "ID 主键") private Integer id; @TableField(fill = FieldFill.INSERT_UPDATE) @ApiModelProperty(name = "username", value = "用户名") private String username; @TableField(fill = FieldFill.INSERT_UPDATE) @ApiModelProperty(name = "password", value = "密码") private String password; @TableField(fill = FieldFill.INSERT) @ApiModelProperty(name = "salt", value = "盐") private String salt; @TableField(fill = FieldFill.INSERT_UPDATE) @ApiModelProperty(name = "age", value = "年龄") private Integer age; @TableField(fill = FieldFill.INSERT_UPDATE) @ApiModelProperty(name = "email", value = "邮箱") private String email; @TableField(fill = FieldFill.INSERT_UPDATE) @ApiModelProperty(name = "address", value = "地址") private String address; @TableField(exist = false) private List<Role> roles = new ArrayList<>();}package com.ego.pojo;import com.baomidou.mybatisplus.annotation.*;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.Serializable;import java.util.ArrayList;import java.util.List;/** * @author 袁梦达 2019012364 */@Data@NoArgsConstructor@AllArgsConstructor@TableName("t_role")@ApiModel("角色实体类")public class Role implements Serializable { /** 数据库中设置该字段自增时该注解不能少 **/ @TableId(type = IdType.AUTO) @ApiModelProperty(name = "id", value = "ID 主键") private Integer id; @TableField(fill = FieldFill.INSERT_UPDATE) @ApiModelProperty(name = "name", value = "角色名称") private String name; @TableField(exist = false) private List<Permission> permissions = new ArrayList<>();}package com.ego.pojo;import com.baomidou.mybatisplus.annotation.*;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.Serializable;/** * @author 袁梦达 2019012364 */@Data@NoArgsConstructor@AllArgsConstructor@TableName("t_permission")@ApiModel("权限实体类")public class Permission implements Serializable { /** 数据库中设置该字段自增时该注解不能少 **/ @TableId(type = IdType.AUTO) @ApiModelProperty(name = "id", value = "ID主键") private Integer id; @TableField(fill = FieldFill.INSERT_UPDATE) @ApiModelProperty(name = "name", value = "权限名称") private String name; @TableField(fill = FieldFill.INSERT_UPDATE) @ApiModelProperty(name = "url", value = "权限菜单URL") private String url;}

 

  

4.实现Controller、Service、Dao

这里dao采用了mybatis-plus

 

  

package com.ego.controller;import com.ego.pojo.User;import com.ego.service.UserService;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.IncorrectCredentialsException;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.subject.Subject;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;/** * @author 袁梦达 2019012364 */@Controller@RequestMapping("/user")public class UserController { @Autowired private UserService userService; /** * 用户登录 * @param username * @param password * @return */ @RequestMapping("/login") public String login(String username,String password){ // 获取当前登录用户 Subject subject = SecurityUtils.getSubject(); try { // 执行登录操作 subject.login(new UsernamePasswordToken(username,password)); // 认证通过后直接跳转到index.jsp return "redirect:/index.jsp"; } catch (UnknownAccountException e) { e.printStackTrace(); System.out.println("用户名错误!"); } catch (IncorrectCredentialsException e) { System.out.println("密码错误!"); } catch (Exception e) { } // 如果认证失败仍然回到登录页面 return "redirect:/login.jsp"; } @RequestMapping("/logout") public String logout(){ subject.logout(); // 退出后仍然会到登录页面 * 用户注册 * @param user @RequestMapping("/register") public String register(User user){ userService.register(user); return "redirect:/login.jsp"; return "redirect:/register.jsp";}package com.ego.service.impl;import com.ego.dao.mapper.UserMapper;import com.ego.shiro.ShiroConstant;import com.ego.utils.SaltUtil;import org.apache.shiro.crypto.hash.Md5Hash;import org.springframework.stereotype.Service;@Service("userService")public class UserServiceImpl implements UserService { private UserMapper userMapper; @Override public void register(User user) { //生成随机盐 String salt = SaltUtil.getSalt(ShiroConstant.SALT_LENGTH); //保存随机盐 user.setSalt(salt); //生成密码 Md5Hash password = new Md5Hash(user.getPassword(), salt, ShiroConstant.HASH_ITERATORS); //保存密码 user.setPassword(password.toHex()); userMapper.insert(user); public User findUserByUserName(String userName) { return userMapper.findUserByUserName(userName);import com.ego.dao.mapper.RoleMapper;import com.ego.pojo.Role;import com.ego.service.RoleService;import java.util.List;@Service("roleService")public class RoleServiceImpl implements RoleService { private RoleMapper roleMapper; public List<Role> getRolesByUserId(Integer userId) { return roleMapper.getRolesByUserId(userId);import com.ego.dao.mapper.PermissionMapper;import com.ego.pojo.Permission;import com.ego.service.PermissionService;@Service("permissionService")public class PermissionServiceImpl implements PermissionService { private PermissionMapper permissionMapper; public List<Permission> getPermissionsByRoleId(Integer roleId) { return permissionMapper.getPermissionsByRoleId(roleId);package com.ego.dao.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Select;@Mapperpublic interface UserMapper extends BaseMapper<User> { @Select("SELECT u.id,u.username,u.password,u.salt,u.age,u.email,u.address FROM t_user u WHERE u.username = #{username}") User findUserByUserName(String username);public interface RoleMapper extends BaseMapper<Role> { @Select("select r.id,r.name from t_role r left join t_user_role ur on ur.role_id = r.id where ur.user_id = #{userId}") List<Role> getRolesByUserId(Integer userId);public interface PermissionMapper extends BaseMapper<Permission> { @Select("select p.id,p.name,p.url from t_permission p left join t_role_permission rp on rp.permission_id = p.id where rp.role_id = #{roleId}") List<Permission> getPermissionsByRoleId(Integer roleId);

 

  

5.实现SaltUtil和ApplicationContextUtil两个工具类

package com.ego.utils;import java.util.Random;/** * @author 袁梦达 2019012364 */public class SaltUtil { public static String getSalt(int n){ char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()".toCharArray(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < n; i++) { char aChar = chars[new Random().nextInt(chars.length)]; sb.append(aChar); } return sb.toString(); }}import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;@Componentpublic class ApplicationContextUtil implements ApplicationContextAware { public static ApplicationContext context; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; /** * 根据工厂中的类名获取类实例 */ public static Object getBean(String beanName){ return context.getBean(beanName);

 

  

6.实现核心Shiro

package com.ego.utils;import java.util.Random;/** * @author 袁梦达 2019012364 */public class SaltUtil { public static String getSalt(int n){ char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()".toCharArray(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < n; i++) { char aChar = chars[new Random().nextInt(chars.length)]; sb.append(aChar); } return sb.toString(); }}package com.ego.utils;import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;/** * @author 袁梦达 2019012364 */@Componentpublic class ApplicationContextUtil implements ApplicationContextAware { public static ApplicationContext context; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; } /** * 根据工厂中的类名获取类实例 */ public static Object getBean(String beanName){ return context.getBean(beanName); }}

 

  

7.实现Redis分布式缓存

package com.ego.shiro;import com.ego.shiro.cache.RedisCacheManager;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.realm.Realm;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import java.util.HashMap;import java.util.Map;/** * @author 袁梦达 2019012364 */@Configurationpublic class ShiroConfiguration { //1.创建shiroFilter //负责拦截所有请求 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); //给filter设置安全管理器 shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); //配置系统受限资源 //配置系统公共资源 Map<String,String> map = new HashMap<String,String>(); map.put("/user/login", "anon"); map.put("/user/register","anon"); map.put("/register.jsp","anon"); map.put("/index.jsp","authc");//authc 请求这个资源需要认证和授权 //默认认证界面路径 shiroFilterFactoryBean.setLoginUrl("/login.jsp"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } //2.创建安全管理器 public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm){ DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); //给安全管理器设置 defaultWebSecurityManager.setRealm(realm); return defaultWebSecurityManager; //3.创建自定义realm public Realm getRealm(){ CustomerRealm customerRealm = new CustomerRealm(); // 设置密码匹配器 HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); // 设置加密方式 credentialsMatcher.setHashAlgorithmName(ShiroConstant.HASH_ALGORITHM_NAME.MD5); // 设置散列次数 credentialsMatcher.setHashIterations(ShiroConstant.HASH_ITERATORS); customerRealm.setCredentialsMatcher(credentialsMatcher); // 设置缓存管理器 customerRealm.setCacheManager(new RedisCacheManager()); // 开启全局缓存 customerRealm.setCachingEnabled(true); // 开启认证缓存并指定缓存名称 customerRealm.setAuthenticationCachingEnabled(true); customerRealm.setAuthenticationCacheName("authenticationCache"); // 开启授权缓存并指定缓存名称 customerRealm.setAuthorizationCachingEnabled(true); customerRealm.setAuthorizationCacheName("authorizationCache"); return customerRealm;}public class ShiroConstant { /** 随机盐的位数 **/ public static final int SALT_LENGTH = 8; /** hash的散列次数 **/ public static final int HASH_ITERATORS = 1024; public interface HASH_ALGORITHM_NAME { String MD5 = "MD5";import com.ego.pojo.Permission;import com.ego.pojo.Role;import com.ego.pojo.User;import com.ego.service.PermissionService;import com.ego.service.RoleService;import com.ego.service.UserService;import com.ego.utils.ApplicationContextUtil;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.Authentication      

	  
	  
	  
	  
	  
	  
        

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: