整合shiro以及將session存入reids中,導(dǎo)入shiro-redis包,就不用自己實(shí)現(xiàn)怎么往redis中存session了?,F(xiàn)在一般都是前后端分離的項(xiàng)目,后臺(tái)返回統(tǒng)一的格式給前端
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、網(wǎng)頁(yè)空間、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、萊陽(yáng)網(wǎng)站維護(hù)、網(wǎng)站推廣。
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
認(rèn)證類(lèi),我用的是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;
/**
* 授權(quán)
*
* @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;
}
/**
* 認(rèn)證
*
* @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配置類(lèi),很重要
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時(shí),返回類(lèi)型是SecurityManager會(huì)報(bào)錯(cuò),直接引用shiro-spring則不報(bào)錯(cuò)
*
* @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);
//失效時(shí)間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();
//設(shè)置過(guò)期時(shí)間ms
((DefaultWebSessionManager) sessionManager).setGlobalSessionTimeout(1800000);
//刪除無(wú)效的session
((DefaultWebSessionManager) sessionManager).setDeleteInvalidSessions(Boolean.TRUE);
//重寫(xiě)url
((DefaultWebSessionManager) sessionManager).setSessionIdUrlRewritingEnabled(Boolean.TRUE);
SimpleCookie simpleCookie = new SimpleCookie();
simpleCookie.setName("loginUser");
//設(shè)置cookie
((DefaultWebSessionManager) sessionManager).setSessionIdCookie(simpleCookie);
((DefaultWebSessionManager) sessionManager).setSessionDAO(redisSessionDAO());
((DefaultWebSessionManager) sessionManager).setCacheManager(redisCacheManager());
return sessionManager;
}
/**
* 設(shè)置過(guò)濾規(guī)則
*
* @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會(huì)按從上到下的順序匹配驗(yàn)證,匹配了就不再繼續(xù)驗(yàn)證
//所以上面的url要苛刻,寬松的url要放在下面,尤其是"/**"要放到最下面,如果放前面的話其后的驗(yàn)證規(guī)則就沒(méi)作用了。
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中讀取,要重寫(xiě)方法
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;
}
}
統(tǒng)一異常處理類(lèi)
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,"認(rèn)證失敗");
}else if(e instanceof UnauthorizedException){
return new ResultVO().returnFail(401,"無(wú)權(quán)限訪問(wèn)");
}
return new ResultVO().returnFail(e.getMessage());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
返回統(tǒng)一的格式
package com.pwl.shiro.common;
import java.io.Serializable;
/**
* @author Pan Weilong
* @date 2019/6/20 15:03
* @description: 結(jié)果統(tǒng)一返回
*/
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;
}
/**
*無(wú)錫人流醫(yī)院 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,"認(rèn)證失敗");
}
@PostMapping("/login")
public ResultVO login(@RequestBody SysUser sysUser) {
Subject user = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(sysUser.getUserName(), sysUser.getPassword());
try {
//shiro幫我們匹配密碼什么的,我們只需要把東西傳給它,它會(huì)根據(jù)我們?cè)赨serRealm里認(rèn)證方法設(shè)置的來(lái)驗(yàn)證
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權(quán)限才能訪問(wèn)
@RequiresPermissions("systemUserAdd")
@GetMapping
public ResultVO getUserList(){
List sysUsers = sysUserService.selectList(null);
return new ResultVO(sysUsers);
}
//需要有add權(quán)限才能訪問(wèn)
@RequiresPermissions("Add")
@GetMapping("/getList")
public ResultVO getList(){
List sysUsers = sysUserService.selectList(null);
return new ResultVO(sysUsers);
}
}
首次登陸的時(shí)候
然后登陸
最后訪問(wèn)需要某些權(quán)限的接口
當(dāng)用戶沒(méi)有權(quán)限的時(shí)候訪問(wèn)接口
貼的部分代碼
sql及項(xiàng)目地址
網(wǎng)站欄目:SpringBoot+mybatis-plus整合shiro和redis
文章鏈接:http://jinyejixie.com/article36/iicepg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)、商城網(wǎng)站、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、面包屑導(dǎo)航、ChatGPT、全網(wǎng)營(yíng)銷(xiāo)推廣
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)