SpringBoot+mybatis-plus整合shiro和redis

发布时间:2020-07-26 10:06:23 作者:nineteens
来源:网络 阅读:1189

  整合shiro以及将session存入reids中,导入shiro-redis包,就不用自己实现怎么往redis中存session了。现在一般都是前后端分离的项目,后台返回统一的格式给前端

  pom

  xsi:schemaLocation=

  4.0.0

  org.springframework.boot

  spring-boot-starter-parent

  2.1.6.RELEASE

  com.pwl

  springboot-shiro

  0.0.1-SNAPSHOT

  springboot-shiro

  Demo project for Spring Boot

  1.8

  org.springframework.boot

  spring-boot-starter-web

  org.springframework.boot

  spring-boot-starter-test

  test

  org.apache.shiro

  shiro-spring-boot-starter

  1.4.0

  mysql

  mysql-connector-java

  com.baomidou

  mybatis-plus-boot-starter

  2.2.0

  com.zaxxer

  HikariCP

  org.apache.velocity

  velocity-engine-core

  2.0

  org.crazycake

  shiro-redis

  2.4.2.1-RELEASE

  org.apache.shiro

  shiro-core

  redis.clients

  jedis

  2.7.2

  org.springframework.boot

  spring-boot-maven-plugin

  认证类,我用的是mybatis-plus

  package com.pwl.shiro.ream;

  import com.baomidou.mybatisplus.mapper.EntityWrapper;

  import com.baomidou.mybatisplus.mapper.Wrapper;

  import com.pwl.shiro.entity.SysUser;

  import com.pwl.shiro.service.SysPermissionService;

  import com.pwl.shiro.service.SysUserService;

  import org.apache.shiro.authc.*;

  import org.apache.shiro.authz.AuthorizationInfo;

  import org.apache.shiro.authz.SimpleAuthorizationInfo;

  import org.apache.shiro.realm.AuthorizingRealm;

  import org.apache.shiro.subject.PrincipalCollection;

  import org.apache.shiro.util.ByteSource;

  import org.slf4j.Logger;

  import org.slf4j.LoggerFactory;

  import org.springframework.beans.factory.annotation.Autowired;

  import java.util.ArrayList;

  import java.util.List;

  /**

  * @author Pan Weilong

  * @date 2019/6/20 20:11

  * @description: 接口.

  */

  public class UserRealm extends AuthorizingRealm{

  private static final Logger LOGGER = LoggerFactory.getLogger(UserRealm.class);

  @Autowired

  private SysUserService sysUserService;

  @Autowired

  private SysPermissionService sysPermissionService;

  /**

  * 授权

  *

  * @param principals

  * @return

  */

  @Override

  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

  SysUser sysUser = (SysUser) principals.getPrimaryPrincipal();

  //List sysPermissions = sysPermissionService.selectPermissionByUserId(sysUser.getUserId());

  List sysPermissions=new ArrayList<>();

  sysPermissions.add("systemUserAdd");

  SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

  info.addStringPermissions(sysPermissions);

  LOGGER.info("doGetAuthorizationInfo");

  return info;

  }

  /**

  * 认证

  *

  * @param authenticationToken

  * @return

  * @throws AuthenticationException

  */

  @Override

  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

  UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

  Wrapper objectWrapper = new EntityWrapper<>();

  objectWrapper.eq("user_name",token.getUsername());

  SysUser sysUser = sysUserService.selectOne(objectWrapper);

  if (sysUser == null) {

  return null;

  }

  LOGGER.info("doGetAuthenticationInfo");

  return new SimpleAuthenticationInfo(sysUser, sysUser.getPassword().toCharArray(), ByteSource.Util.bytes(sysUser.getSalt()), getName());

  }

  }

  shiro配置类,很重要

  package com.pwl.shiro.config;

  import com.pwl.shiro.ream.UserRealm;

  import org.apache.shiro.authc.credential.HashedCredentialsMatcher;

  import org.apache.shiro.session.mgt.SessionManager;

  import org.apache.shiro.spring.web.ShiroFilterFactoryBean;

  import org.apache.shiro.web.mgt.DefaultWebSecurityManager;

  import org.apache.shiro.web.servlet.SimpleCookie;

  import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;

  import org.crazycake.shiro.RedisCacheManager;

  import org.crazycake.shiro.RedisManager;

  import org.crazycake.shiro.RedisSessionDAO;

  import org.springframework.context.annotation.Bean;

  import org.springframework.context.annotation.Configuration;

  import java.util.LinkedHashMap;

  import java.util.Map;

  /**

  * @author Pan Weilong

  * @date 2019/6/20 20:10

  * @description: 接口.

  */

  @Configuration

  public class ShiroConfig {

  /**

  * 凭证匹配器

  *

  * @return

  */

  @Bean

  public HashedCredentialsMatcher hashedCredentialsMatcher() {

  HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();

  //md5加密

  hashedCredentialsMatcher.setHashAlgorithmName("md5");

  //加密1次

  hashedCredentialsMatcher.setHashIterations(1);

  return hashedCredentialsMatcher;

  }

  /**

  * 自定义realm

  *

  * @return

  */

  @Bean

  public UserRealm userRealm() {

  UserRealm userRealm = new UserRealm();

  userRealm.setCredentialsMatcher(hashedCredentialsMatcher());

  return userRealm;

  }

  /**

  * 安全管理器

  * 注:使用shiro-spring-boot-starter 1.4时,返回类型是SecurityManager会报错,直接引用shiro-spring则不报错

  *

  * @return

  */

  @Bean

  public DefaultWebSecurityManager securityManager() {

  DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

  securityManager.setRealm(userRealm());

  securityManager.setSessionManager(sessionManager());

  return securityManager;

  }

  /**

  * @Author

  * @Description redis缓存

  * @Date 21:32 2019/6/23

  * @Param []

  * @return org.crazycake.shiro.RedisManager

  **/

  @Bean

  public RedisManager redisManager(){

  RedisManager redisManager = new RedisManager();

  redisManager.setHost("127.0.0.1");

  redisManager.setPort(6379);

  //失效时间30分钟

  redisManager.setExpire(1800);

  return redisManager;

  }

  @Bean

  public RedisSessionDAO redisSessionDAO(){

  RedisSessionDAO redisSessionDAO = new RedisSessionDAO();

  redisSessionDAO.setRedisManager(redisManager());

  //存入redis前缀

  redisSessionDAO.setKeyPrefix("redis_");

  return redisSessionDAO;

  }

  @Bean

  public RedisCacheManager redisCacheManager(){

  RedisCacheManager redisCacheManager = new RedisCacheManager();

  redisCacheManager.setRedisManager(redisManager());

  return redisCacheManager;

  }

  @Bean

  public SessionManager sessionManager() {

  SessionManager sessionManager =new ShiroSessionManager();

  //设置过期时间ms

  ((DefaultWebSessionManager) sessionManager).setGlobalSessionTimeout(1800000);

  //删除无效的session

  ((DefaultWebSessionManager) sessionManager).setDeleteInvalidSessions(Boolean.TRUE);

  //重写url

  ((DefaultWebSessionManager) sessionManager).setSessionIdUrlRewritingEnabled(Boolean.TRUE);

  SimpleCookie simpleCookie = new SimpleCookie();

  simpleCookie.setName("loginUser");

  //设置cookie

  ((DefaultWebSessionManager) sessionManager).setSessionIdCookie(simpleCookie);

  ((DefaultWebSessionManager) sessionManager).setSessionDAO(redisSessionDAO());

  ((DefaultWebSessionManager) sessionManager).setCacheManager(redisCacheManager());

  return sessionManager;

  }

  /**

  * 设置过滤规则

  *

  * @param securityManager

  * @return

  */

  @Bean

  public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {

  ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

  shiroFilterFactoryBean.setSecurityManager(securityManager);

  shiroFilterFactoryBean.setLoginUrl("/login");

  shiroFilterFactoryBean.setSuccessUrl("/");

  shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");

  //注意此处使用的是LinkedHashMap,是有顺序的,shiro会按从上到下的顺序匹配验证,匹配了就不再继续验证

  //所以上面的url要苛刻,宽松的url要放在下面,尤其是"/**"要放到最下面,如果放前面的话其后的验证规则就没作用了。

  Map filterChainDefinitionMap = new LinkedHashMap<>();

  filterChainDefinitionMap.put("/static/**", "anon");

  filterChainDefinitionMap.put("/login", "anon");

  filterChainDefinitionMap.put("/captcha.jpg", "anon");

  filterChainDefinitionMap.put("/favicon.ico", "anon");

  filterChainDefinitionMap.put("/**", "authc");

  shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

  return shiroFilterFactoryBean;

  }

  }

  为了避免session频繁从redis中读取,要重写方法

  package com.pwl.shiro.config;

  import org.apache.shiro.session.Session;

  import org.apache.shiro.session.UnknownSessionException;

  import org.apache.shiro.session.mgt.SessionKey;

  import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;

  import org.apache.shiro.web.session.mgt.WebSessionKey;

  import javax.servlet.ServletRequest;

  import java.io.Serializable;

  /**

  * @author Pan Weilong

  * @date 2019/6/22 10:40

  * @description: 接口.

  */

  public class ShiroSessionManager extends DefaultWebSessionManager {

  @Override

  protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {

  Serializable sessionId = getSessionId(sessionKey);

  ServletRequest request = null;

  if (sessionKey instanceof WebSessionKey) {

  request = ((WebSessionKey) sessionKey).getServletRequest();

  }

  if (request != null && null != sessionId) {

  Object sessionObj = request.getAttribute(sessionId.toString());

  if (sessionObj != null) {

  return (Session) sessionObj;

  }

  }

  Session session = super.retrieveSession(sessionKey);

  if (request != null && null != sessionId) {

  request.setAttribute(sessionId.toString(), session);

  }

  return session;

  }

  }

  统一异常处理类

  package com.pwl.shiro.exception;

  import com.pwl.shiro.common.ResultVO;

  import org.apache.shiro.authz.UnauthenticatedException;

  import org.apache.shiro.authz.UnauthorizedException;

  import org.slf4j.Logger;

  import org.slf4j.LoggerFactory;

  import org.springframework.beans.BeansException;

  import org.springframework.context.ApplicationContext;

  import org.springframework.context.ApplicationContextAware;

  import org.springframework.web.bind.annotation.ControllerAdvice;

  import org.springframework.web.bind.annotation.ExceptionHandler;

  import org.springframework.web.bind.annotation.ResponseBody;

  import javax.servlet.http.HttpServletRequest;

  /**

  * @Author Pan Weilong

  * @Description 全局异常捕获

  * @Date 15:11 2019/6/20

  * @Param

  * @return

  **/

  @ControllerAdvice

  public class GlobalExceptionHandler implements ApplicationContextAware {

  private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

  private ApplicationContext applicationContext;

  @ExceptionHandler(value = Exception.class)

  @ResponseBody

  public ResultVO defaultErrorHandler(HttpServletRequest request, Exception e) throws Exception {

  if(e instanceof UnauthenticatedException){

  return new ResultVO().returnFail(401,"认证失败");

  }else if(e instanceof UnauthorizedException){

  return new ResultVO().returnFail(401,"无权限访问");

  }

  return new ResultVO().returnFail(e.getMessage());

  }

  @Override

  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

  this.applicationContext = applicationContext;

  }

  }

  返回统一的格式

  package com.pwl.shiro.common;

  import java.io.Serializable;

  /**

  * @author Pan Weilong

  * @date 2019/6/20 15:03

  * @description: 结果统一返回

  */

  public class ResultVO implements Serializable {

  private static final long serialVersionUID = 1L;

  public static final int SUCCESS = 200;

  public static final int FAIL = 1;

  private String msg = "success";

  private int code = SUCCESS;

  private T data;

  public ResultVO() {

  super();

  }

  public ResultVO(T data) {

  super();

  this.data = data;

  }

  public ResultVO(T data, String msg) {

  super();

  this.data = data;

  this.msg = msg;

  }

  public ResultVO(Throwable e) {

  super();

  this.msg = e.getMessage();

  this.code = FAIL;

  }

  /**

  *

  * 返回成功

  * @param data

  * @return

  */

  public ResultVO returnSuccess(T data) {

  this.data = data;

  return this;

  }

  /**

  * 无锡人流医院 http://www.bhnkyy39.com/

  * 返回失败

  *

  * @param code

  * @param msg

  * @return

  */

  public ResultVO returnFail(Integer code , String msg) {

  this.code = code;

  this.msg = msg;

  return this;

  }

  public ResultVO returnFail(String msg) {

  this.code = 500;

  this.msg = msg;

  return this;

  }

  public String getMsg() {

  return msg;

  }

  public void setMsg(String msg) {

  this.msg = msg;

  }

  public int getCode() {

  return code;

  }

  public void setCode(int code) {

  this.code = code;

  }

  public T getData() {

  return data;

  }

  public void setData(T data) {

  this.data = data;

  }

  }

  controller

  package com.pwl.shiro.controller;

  import com.pwl.shiro.common.ResultVO;

  import com.pwl.shiro.entity.SysUser;

  import org.apache.shiro.SecurityUtils;

  import org.apache.shiro.authc.UsernamePasswordToken;

  import org.apache.shiro.authz.UnauthenticatedException;

  import org.apache.shiro.subject.Subject;

  import org.springframework.web.bind.annotation.GetMapping;

  import org.springframework.web.bind.annotation.PostMapping;

  import org.springframework.web.bind.annotation.RequestBody;

  import org.springframework.web.bind.annotation.RestController;

  import javax.servlet.http.HttpServletRequest;

  /**

  * @author Pan Weilong

  * @date 2019/6/20 21:00

  * @description: 接口.

  */

  @RestController

  public class LonginController {

  @GetMapping("/login")

  public ResultVO login(HttpServletRequest request){

  return new ResultVO().returnFail(401,"认证失败");

  }

  @PostMapping("/login")

  public ResultVO login(@RequestBody SysUser sysUser) {

  Subject user = SecurityUtils.getSubject();

  UsernamePasswordToken token = new UsernamePasswordToken(sysUser.getUserName(), sysUser.getPassword());

  try {

  //shiro帮我们匹配密码什么的,我们只需要把东西传给它,它会根据我们在UserRealm里认证方法设置的来验证

  user.login(token);

  } catch (Exception e) {

  e.printStackTrace();

  throw new UnauthenticatedException();

  }

  return new ResultVO("登录成功");

  }

  }

  package com.pwl.shiro.controller;

  import com.pwl.shiro.common.ResultVO;

  import com.pwl.shiro.entity.SysUser;

  import com.pwl.shiro.service.SysUserService;

  import org.apache.shiro.authz.annotation.RequiresPermissions;

  import org.springframework.beans.factory.annotation.Autowired;

  import org.springframework.web.bind.annotation.GetMapping;

  import org.springframework.web.bind.annotation.RequestMapping;

  import org.springframework.web.bind.annotation.RestController;

  import java.util.List;

  /**

  *

  * 前端控制器

  *

  *

  * @author pwl

  * @since 2019-06-20

  */

  @RestController

  @RequestMapping("/sysUser")

  public class SysUserController {

  @Autowired

  private SysUserService sysUserService;

  //需要有systemUser权限才能访问

  @RequiresPermissions("systemUserAdd")

  @GetMapping

  public ResultVO getUserList(){

  List sysUsers = sysUserService.selectList(null);

  return new ResultVO(sysUsers);

  }

  //需要有add权限才能访问

  @RequiresPermissions("Add")

  @GetMapping("/getList")

  public ResultVO getList(){

  List sysUsers = sysUserService.selectList(null);

  return new ResultVO(sysUsers);

  }

  }

  首次登陆的时候

  然后登陆

  最后访问需要某些权限的接口

  当用户没有权限的时候访问接口

  贴的部分代码

  sql及项目地址


推荐阅读:
  1. SpringBoot整合Shiro安全框架
  2. springboot整合spring @Cache和Redis

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

springboot mybatis shiro

上一篇:无业务不伸缩之二,云监控搭配SLB及ESS(进阶篇)

下一篇:MySQL——全量,增量备份与恢复(实战篇!)

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》