您好,登錄后才能下訂單哦!
整合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-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及項目地址
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。