springboot整合shiro

导入依赖

<!--        shiro鉴权框架-->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.5.1</version>
</dependency><dependency><!--session持久化插件(jdis)--><groupId>org.crazycake</groupId><artifactId>shiro-redis</artifactId><version>3.2.3</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.0</version></dependency><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.2.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

工具类

redis工具类

我们采用jedis配置更加灵活方便

/*** jedis配置*/import com.google.gson.Gson;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.params.SetParams;
import zztTrans.template.utl.AccessToken;import java.util.HashMap;
import java.util.Map;public class RedisUtil {private static String ADDR = "localhost";//端口private static int PORT = 6379;//密码private static String AUTH = "123456";//连接实例的最大连接数private static int MAX_ACTIVE = 1024;//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。private static int MAX_IDLE = 200;//等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionExceptionprivate static int MAX_WAIT = 10000;//连接超时的时间private static int TIMEOUT = 10000;// 在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;private static boolean TEST_ON_BORROW = true;private static JedisPool jedisPool = null;/*** @author : cjd* @description : 初始化Jedis连接池* @date : 15:30 2019/4/11*/static {JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(MAX_ACTIVE);config.setMaxIdle(MAX_IDLE);config.setMaxWaitMillis(MAX_WAIT);config.setTestOnBorrow(TEST_ON_BORROW);jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT,AUTH);//如果设置了密码使用jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH);}/*** @author : cjd* @description : 这里我用了同步获取Jedis实例,不然多线程下同是获取jedis实例不确定会不会出问题* @date : 15:30 2019/4/11*/public static synchronized Jedis getJedis() {if (jedisPool != null) {Jedis resource = jedisPool.getResource();return resource;} else {return null;}}/*** @author : cjd* @description : 释放资源* @date : 15:34 2019/4/11*/public static void closeJedisPool(Jedis jedis) {if (jedis.isConnected()) {jedis.disconnect();}jedis.close();}/*** 移除键为token的剩余生存时间* @param token*/public static void persist(String token){Jedis jedis=getJedis();jedis.persist(token);closeJedisPool(jedis);}/*** 设置键的生存时间* @param token* @param time*/public static void expire(String token,int time){Jedis jedis=getJedis();jedis.expire(token,time);closeJedisPool(jedis);}/*** 获取键的生存时间* @param token* @return*/public static Long ttl(String token){Jedis jedis=getJedis();Long a= jedis.ttl(token);closeJedisPool(jedis);return a;}/*** 获取键的值* @param token* @return*/public static String get(String token){Jedis jedis=getJedis();String a= jedis.get(token);closeJedisPool(jedis);return a;}/*** 设置键的值* @param randomkey* @param json*/public static void set(String randomkey,String json){Jedis jedis=getJedis();jedis.set(randomkey,json);closeJedisPool(jedis);}/*** 已键删除值* @param token*/public static void del(String token){Jedis jedis=getJedis();jedis.del(token);closeJedisPool(jedis);}/*** 判断键是否存在* @param token* @return*/public static Boolean exists(String token){Jedis jedis=getJedis();Boolean flag= jedis.exists(token);closeJedisPool(jedis);return flag;}/*** 清空redis* @return*/public static String flushDB(){Jedis jedis=getJedis();String flag= jedis.flushDB();closeJedisPool(jedis);return flag;}/*** 加锁 (0.3分钟)* @param key* @param val* @return*/public static boolean hoursSetnx(String key, String val) {Jedis jedis = null;try {jedis = jedisPool.getResource();if (jedis == null) {return false;}SetParams params = new SetParams();params.nx();params.px(1000*60*60*2);boolean b = jedis.set(key, val,params).equalsIgnoreCase("ok");return b;} catch (Exception ex) {} finally {if (jedis != null) {jedis.close();}}return false;}/*** 加锁 (1分钟)* @param key* @param val* @return*/public static boolean setnx(String key, String val) {Jedis jedis = null;try {jedis = jedisPool.getResource();if (jedis == null) {return false;}SetParams params = new SetParams();params.nx();params.px(1000*60);boolean b = jedis.set(key, val,params).equalsIgnoreCase("ok");return b;} catch (Exception ex) {} finally {if (jedis != null) {jedis.close();}}return false;}/*** 加锁 (0.3分钟)* @param key* @param val* @return*/public static boolean freightSupplysetnx(String key, String val) {Jedis jedis = null;try {jedis = jedisPool.getResource();if (jedis == null) {return false;}SetParams params = new SetParams();params.nx();params.px(1000*6);boolean b = jedis.set(key, val,params).equalsIgnoreCase("ok");return b;} catch (Exception ex) {} finally {if (jedis != null) {jedis.close();}}return false;}/*** Accesstoken加锁* @param key* @param val* @return*/public static boolean RedisAccesstoken(String key, String val) {Jedis jedis = null;try {jedis = jedisPool.getResource();if (jedis == null) {return false;}SetParams params = new SetParams();params.nx();params.px(1000*3600);boolean b = jedis.set(key, val,params).equalsIgnoreCase("ok");return b;} catch (Exception ex) {} finally {if (jedis != null) {jedis.close();}}return false;}/*** 删除锁* @param key* @param val* @return*/public int delnx(String key, String val) {Jedis jedis = null;try {jedis = jedisPool.getResource();if (jedis == null) {return 0;}//if redis.call('get','orderkey')=='1111' then return redis.call('del','orderkey') else return 0 endStringBuilder sbScript = new StringBuilder();sbScript.append("if redis.call('get','").append(key).append("')").append("=='").append(val).append("'").append(" then ").append("    return redis.call('del','").append(key).append("')").append(" else ").append("    return 0").append(" end");return Integer.valueOf(jedis.eval(sbScript.toString()).toString());} catch (Exception ex) {} finally {if (jedis != null) {jedis.close();}}return 0;}}

jwt

生成token签名

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import zztTrans.system.entity.TransUser;
import zztTrans.AppSystem.entity.TransWinglong;import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.UUID;/*** 生成token签名* @author :enilu* @date :Created in 2019/7/30 22:56*/
public class JwtUtil {/*** 获得token中的信息无需secret解密也能获得** @return token中包含的用户名*/public static String getUsername(String token) {try {DecodedJWT jwt = JWT.decode(token);return jwt.getClaim("username").asString();} catch (JWTDecodeException e) {return null;}}/*** 生成签名** @param user       用户* @param expireTime 毫秒数* @return 加密的token*/public static String sign(TransUser user, long expireTime) throws UnsupportedEncodingException {Date date = new Date(System.currentTimeMillis() + expireTime);Algorithm algorithm = Algorithm.HMAC256(user.getId());// 附带username信息return JWT.create().withClaim("username", user.getUserCode()).withClaim("userId", user.getId()).withClaim("uuid", UUID.randomUUID().toString()).withExpiresAt(date).sign(algorithm);}}

WEB跨域配置

package springboot.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.*;import java.nio.charset.Charset;/*** 开启前后端跨域允许* 王文斌*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {/*** 返回前端utf8编码设置(貌似用处不大)* @return*/@Beanpublic HttpMessageConverter<String> responseBodyConverter() {StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));return converter;}/*** 允许跨域方式* @return*/@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("*").allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE").maxAge(3600).allowCredentials(true);}/*** swagger跨域配置* @return*/@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/");}/*** 配置template下的后台html路径* @param registry*/@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addRedirectViewController("/long","/templates/long.html");registry.addRedirectViewController("/kaptcha","/templates/kaptcha.html");}}

Request请求过滤包装

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.HashMap;
import java.util.Map;/*** Request请求过滤包装* <p>* @author   hubin* @Date    2014-5-8   */
public class WafRequestWrapper extends HttpServletRequestWrapper {private boolean filterXSS = true;private boolean filterSQL = true;public WafRequestWrapper(HttpServletRequest request, boolean filterXSS, boolean filterSQL) {super(request);this.filterXSS = filterXSS;this.filterSQL = filterSQL;}public WafRequestWrapper(HttpServletRequest request) {this(request, true, true);}/*** @Description 数组参数过滤* @param parameter*              过滤参数* @return*/@Overridepublic String[] getParameterValues(String parameter) {String[] values = super.getParameterValues(parameter);if ( values == null ) {return null;}int count = values.length;String[] encodedValues = new String[count];for ( int i = 0 ; i < count ; i++ ) {encodedValues[i] = filterParamString(values[i]);}return encodedValues;}@Override@SuppressWarnings({ "rawtypes", "unchecked" })public Map getParameterMap() {Map<String, String[]> primary = super.getParameterMap();Map<String, String[]> result = new HashMap<String, String[]>(primary.size());for ( Map.Entry<String, String[]> entry : primary.entrySet() ) {result.put(entry.getKey(), filterEntryString(entry.getValue()));}return result;}protected String[] filterEntryString(String[] rawValue) {for ( int i = 0 ; i < rawValue.length ; i++ ) {rawValue[i] = filterParamString(rawValue[i]);}return rawValue;}/*** @Description 参数过滤* @param parameter*              过滤参数* @return*/@Overridepublic String getParameter(String parameter) {return filterParamString(super.getParameter(parameter));}/*** @Description 请求头过滤 * @param name*              过滤内容* @return*/@Overridepublic String getHeader(String name) {return filterParamString(super.getHeader(name));}/*** @Description Cookie内容过滤* @return*/@Overridepublic Cookie[] getCookies() {Cookie[] existingCookies = super.getCookies();if (existingCookies != null) {for (int i = 0 ; i < existingCookies.length ; ++i) {Cookie cookie = existingCookies[i];cookie.setValue(filterParamString(cookie.getValue()));}}return existingCookies;}/*** @Description 过滤字符串内容* @param rawValue*              待处理内容* @return*/protected String filterParamString(String rawValue) {if (null == rawValue) {return null;}String tmpStr = rawValue;if (this.filterXSS) {tmpStr = WafKit.stripXSS(rawValue);}if (this.filterSQL) {tmpStr = WafKit.stripSqlInjection(tmpStr);}return tmpStr;}
}

md5加密工具

md5单项加密

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;/*** md5单项加密*/
@Component
public class Md5 {private static final String KEY = "666666";public String md5(String input) {byte[] code = null;try {code = MessageDigest.getInstance("md5").digest(input.getBytes());} catch (NoSuchAlgorithmException e) {code = input.getBytes();}BigInteger bi = new BigInteger(code);return bi.abs().toString(32).toUpperCase();}//测试md5加密public static String md52(String input) {byte[] code = null;try {code = MessageDigest.getInstance("md5").digest(input.getBytes());} catch (NoSuchAlgorithmException e) {code = input.getBytes();}BigInteger bi = new BigInteger(code);return bi.abs().toString(32).toUpperCase();}public static String getMD5(String plainText) {try {MessageDigest md = MessageDigest.getInstance("MD5");//获取MD5实例md.update(plainText.getBytes());//此处传入要加密的byte类型值byte[] digest = md.digest();//此处得到的是md5加密后的byte类型值/*下边的运算就是自己添加的一些二次小加密,记住这个千万不能弄错乱,否则在解密的时候,你会发现值不对的(举例:在注册的时候加密方式是一种,在我们登录的时候是不是还需要加密它的密码然后和数据库的进行比对,但是最后我们发现,明明密码对啊,就是打不到预期效果,这时候你就要想一下,你是否有改动前后的加密方式)*/int i;StringBuilder sb = new StringBuilder();for (int offset = 0; offset < digest.length; offset++) {i = digest[offset];if (i < 0) {i += 255;}if (i < 17) {sb.append(0);}sb.append(Integer.toHexString(i));//通过Integer.toHexString方法把值变为16进制}return sb.toString().substring(0, 32);//从下标0开始,length目的是截取多少长度的值} catch (NoSuchAlgorithmException e) {e.printStackTrace();return null;}}public static String encrypt(String pwd) {if (StringUtils.isBlank(pwd)) {return null;}return DigestUtils.sha256Hex(KEY + pwd);//        return DigestUtils.sha1Hex(KEY + pwd);}}

去除session

import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.SubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSubjectFactory;/***去除session*/public class StatelessDefaultSubjectFactor extends DefaultWebSubjectFactory {@Overridepublic Subject createSubject(SubjectContext context) {//不创建sessioncontext.setSessionCreationEnabled(false);return super.createSubject(context);}
}

判断token是否存在

import org.apache.shiro.subject.Subject;
import zztTrans.redissocket.RedisUtil;import java.util.HashMap;
import java.util.Map;/*** 判断token是否存在*/
public class TokenSubjectUtil {private static Map<String, Subject> subjectMap=new HashMap<>();public static void saveSubject(String reandomkey, Subject sub){subjectMap.put(reandomkey,sub);}public static String getSubject(String key){if(key==null){key="0";}String json=  RedisUtil.get(key);return json;}
}

接口

@MyLog(value = "登录验证")
@PostMapping(value = "login")
@ApiOperation(value = "登录验证", notes = "登录验证", response = ApiResult.class)
public ApiResult<String> login(@Valid @RequestBody TransUser user) {//创建一个subject对象Subject subject = SecurityUtils.getSubject();// 把用户名和密码封装为 UsernamePasswordToken 对象UsernamePasswordToken token = new UsernamePasswordToken(user.getUserCode(), md5.md5(user.getUserPass()));try {QueryWrapper<TransUser> queryWrapper = new QueryWrapper<>();queryWrapper.eq("user_code", user.getUserCode());queryWrapper.eq("user_pass", md5.md5(user.getUserPass()));//查询出来的user对象TransUser user1 = transUserService.getOne(queryWrapper);if(user1!=null) {if ("1".equals(user1.getStatus())) {return ApiResult.fail("该用户已被禁用请联系管理员");}}//进行登录认证subject.login(token);String randomkey = transUserService.loginForToken(user1);Map map = new HashMap();map.put("token", randomkey);Object obj = JSONArray.toJSON(user1);String json = obj.toString();RedisUtil.set(randomkey,json);RedisUtil.expire(randomkey,1800);System.out.println("subjet: "+subject+"---------------------------");return ApiResult.ok(map);} catch (UnknownAccountException e) {return ApiResult.fail("用户名不存在");} catch (IncorrectCredentialsException e) {return ApiResult.fail("密码错误");} catch (UnsupportedEncodingException e) {return ApiResult.fail("token创建失败");}
}

shiro最重要的验证体

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.springframework.beans.factory.annotation.Autowired;
import zztTrans.system.entity.TransUser;
import zztTrans.system.service.TransRoleService;
import zztTrans.system.service.TransUserService;
import zztTrans.system.web.vo.TransRoleQueryVo;import java.util.Collections;
import java.util.Set;/*** shiro最重要的验证体*/
public class UserRealm extends AuthorizingRealm {@Autowiredprivate TransUserService transUserService;@Autowiredprivate TransRoleService transRoleService;/*** 授权*去除session之后将不会执行授权(将进入自定义拦截器)* @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("执行了授权");String username = principalCollection.toString();SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();TransRoleQueryVo role=transRoleService.getCoreByuserCode(username);Set<String> roles= Collections.singleton(role.getRoleName());//进行roles验证授权info.setRoles(roles);return info;}/*** 登录认证** @param token* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("执行了认证");//用户,名密码UsernamePasswordToken userToken=(UsernamePasswordToken) token;//条件QueryWrapper<TransUser> queryWrapper = new QueryWrapper<>();queryWrapper.eq("user_code",userToken.getUsername());//查询出来的user对象TransUser user = transUserService.getOne(queryWrapper);if(user==null){return null;}return new SimpleAuthenticationInfo(token.getPrincipal(),user.getUserPass(),getName());}}

配置

import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import zztTrans.util.shrio.StatelessDefaultSubjectFactor;import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;@Configuration
public class ShiroConfig {/*** 3* shirofilterfactoryBen*/@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();//设置安全管理器bean.setSecurityManager(defaultWebSecurityManager);//添加shiro的内置过滤器/*** anon:无需认证就可以访问**(已下内置过滤器,去除session后会报错,使用自定义拦截器就可以了)* authc:必须认证才能访问* user:必须拥有记住我* perms:拥有对一个资源的权限才能访问* role:拥有某个角色权限才能访问*///自定义授权验证Map<String, Filter> filterMap1 = new HashMap<String, Filter>(1);filterMap1.put("jwt", new NoSessionFilter());filterMap1.put("appjwt", new AppFilter());filterMap1.put("jwtroles", new RoleFilter());bean.setFilters(filterMap1);Map<String, String> filterMap = new LinkedHashMap<>();/*** 登录登出不拦截*/filterMap.put("/web/api/UserLong/**", "anon");filterMap.put("/web/api/UserLong/noauth", "anon");filterMap.put("/app/api/UserLong/**", "anon");/*** swagger不拦截*/filterMap.put("/swagger-ui.html", "anon");filterMap.put("/webjars/springfox-swagger-ui/**", "anon");filterMap.put("/swagger-resources/**", "anon");filterMap.put("/doc.html/**", "anon");filterMap.put("/favicon.ico", "anon");filterMap.put("/webjars/**", "anon");/*** druid不拦截*/filterMap.put("/druid/**", "anon");filterMap.put("/v2/api-docs", "anon");filterMap.put("/service-worker.js", "anon");/*** springbootAdmin不拦截*/filterMap.put("/applications", "anon");filterMap.put("/wallboard", "anon");filterMap.put("/applications/**", "anon");filterMap.put("/wallboard/**", "anon");filterMap.put("/instances/**", "anon");/*** 图片不拦截*/filterMap.put("/img/**", "anon");filterMap.put("/audio/**", "anon");filterMap.put("/certimg/**", "anon");filterMap.put("/QRcode/**", "anon");filterMap.put("/cert/**", "anon");/*** 支付回调不拦截*/filterMap.put("/web/api/user/**", "anon");/*** 轮播图不拦截*/filterMap.put("/app/api/DyAppBanner/**", "anon");filterMap.put("/web/api/TransVerification/text", "jwtroles[WD]");filterMap.put("/web/api/**", "jwt");filterMap.put("/app/api/**", "appjwt");bean.setFilterChainDefinitionMap(filterMap);return bean;}/*** 2** @param userRealm* @return*/@Beanpublic DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(userRealm);//关闭sessionDefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();defaultSessionStorageEvaluator.setSessionStorageEnabled(false);subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);securityManager.setSubjectDAO(subjectDAO);securityManager.setSubjectFactory(subjectFactor());return securityManager;}/*** 创建realm对象,需要自定义类:1** @return*/@Beanpublic UserRealm userRealm() {return new UserRealm();}@Beanpublic StatelessDefaultSubjectFactor subjectFactor() {StatelessDefaultSubjectFactor statelessDefaultSubjectFactor = new StatelessDefaultSubjectFactor();return statelessDefaultSubjectFactor;}}

自定义拦截器

普通拦截器

import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import zztTrans.redissocket.RedisUtil;
import zztTrans.util.shrio.TokenSubjectUtil;import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** 无Session登录token验证,自定义jwt拦截器*/
public class NoSessionFilter extends BasicHttpAuthenticationFilter {@Overrideprotected boolean isAccessAllowed(ServletRequest request, ServletResponse response,Object mappedValue){System.out.println("isAccessAllowed");HttpServletRequest httpServletRequest=(HttpServletRequest) request;System.out.println(httpServletRequest.getServletPath());String token=httpServletRequest.getHeader("token");String subject= TokenSubjectUtil.getSubject(token);if (subject == null||"".equals(subject)){return false;}if(token!=null) {RedisUtil.persist(token);RedisUtil.expire(token, 1800);System.out.println("-----------------------" + RedisUtil.ttl(token) + "-------------------------------");}return true;}@Overrideprotected boolean onAccessDenied(ServletRequest request,ServletResponse response) throws Exception{response.setContentType("application/json;charset=utf-8");response.getWriter().write("{\"code\":50005,\"message\":\"未登录\"}");return false;}/*** 对跨域提供支持*/@Overrideprotected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {HttpServletRequest httpServletRequest = (HttpServletRequest) request;HttpServletResponse httpServletResponse = (HttpServletResponse) response;httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));// 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {httpServletResponse.setStatus(HttpStatus.OK.value());return false;}return super.preHandle(request, response);}}

权限认证拦截器

import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import zztTrans.redissocket.RedisUtil;
import zztTrans.system.service.TransUserService;
import zztTrans.system.web.vo.TransUserQueryVo;
import zztTrans.util.shrio.TokenSubjectUtil;
import zztTrans.util.startuputil.SpringContextUtil;import javax.security.auth.Subject;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;/*** 无Session登录token验证,自定义jwt拦截器*/
public class RoleFilter extends BasicHttpAuthenticationFilter {@Overrideprotected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {System.out.println("isAccessAllowed");HttpServletRequest httpServletRequest = (HttpServletRequest) request;System.out.println(httpServletRequest.getServletPath());String token = httpServletRequest.getHeader("token");String subject = TokenSubjectUtil.getSubject(token);if (subject == null || "".equals(subject)) {try {response.setContentType("application/json;charset=utf-8");response.getWriter().write("{\"code\":50005,\"message\":\"未登录\"}");} catch (IOException e) {e.printStackTrace();}}boolean flat = false;if (subject != null|| !"".equals(subject)) {String[] rolesArray = (String[]) mappedValue;TransUserService transUserService = SpringContextUtil.getBean(TransUserService.class);String userId= transUserService.getUserid(token);if (rolesArray != null && rolesArray.length != 0) {Set<String> roles = CollectionUtils.asSet(rolesArray);for (String item : roles) {System.out.println("userId==============="+ userId);System.out.println("item==============="+ item);TransUserQueryVo bean = transUserService.getTransUserQueryVo(userId, item);if (bean!=null) {flat = true;RedisUtil.persist(token);RedisUtil.expire(token, 604800);System.out.println("-----------------------" + RedisUtil.ttl(token) + "-------------------------------");}}}}return flat;}@Overrideprotected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {response.setContentType("application/json;charset=utf-8");response.getWriter().write("{\"code\":50008,\"message\":\"未授权\"}");return false;}/*** 对跨域提供支持*/@Overrideprotected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {HttpServletRequest httpServletRequest = (HttpServletRequest) request;HttpServletResponse httpServletResponse = (HttpServletResponse) response;httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));// 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {httpServletResponse.setStatus(HttpStatus.OK.value());return false;}return super.preHandle(request, response);}}

springboot整合shiro相关推荐

  1. springboot整合shiro使用shiro-spring-boot-web-starter

    此文章仅仅说明在springboot整合shiro时的一些坑,并不是教程 增加依赖 <!-- 集成shiro依赖 --> <dependency><groupId> ...

  2. springboot整合shiro和session的详细过程和自定义登录拦截器

    文章目录 1.shiro依赖 2.shiro配置 shiro过滤器配置: 关联自定义的其他管理器 自定义会话工厂: 3.登陆时记录用户信息 4.shiro一些工具类的学习 5.自定义登录拦截器 shi ...

  3. SpringBoot整合Shiro实现登录认证和授权CHCache

    文章目录 一. springboot实现普通登录 1 添加依赖 2 编写配置文件 3 新建实体类和mapper 4 编写业务层代码 5 编写控制器 6 编写启动类 7 编写登录页面和主页面 二. sp ...

  4. 补习系列(6)- springboot 整合 shiro 一指禅

    欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...

  5. SpringBoot整合Shiro实现权限控制,验证码

    本文介绍 SpringBoot 整合 shiro,相对于 Spring Security 而言,shiro 更加简单,没有那么复杂. 目前我的需求是一个博客系统,有用户和管理员两种角色.一个用户可能有 ...

  6. SpringBoot 整合Shiro 一指禅

    目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...

  7. SpringBoot整合Shiro搭建登录注册认证授权权限项目模板

    主要内容: 1 SpringBoot整合Shiro安全框架; 2 Shiro主要学习内容总结;(执行流程.主要对象接口.注意事项等) 3 Redis实现对权限信息缓存; ! 温馨提示: 想要快速搭Sh ...

  8. SpringBoot整合Shiro学习(上)

    SpringBoot整合Shiro(上) 基于[编程不良人]2020最新版Shiro教程,整合SpringBoot项目实战教程 哔哩哔哩链接:https://www.bilibili.com/vide ...

  9. Springboot整合Shiro之授权

      本文我们来介绍SpringBoot整合Shiro来实现授权的操作 一.注解的使用方式 1.配置类修改   在权限校验的时候,我们一般在控制中通过注解来实现权限的校验,但我们需要放开注解的使用,在配 ...

最新文章

  1. Android Sensor——传感器
  2. 列举ospf的5种报文类型_这5种“专升本”你都知道吗?那个含金量更高呢?报考如何选择?...
  3. jdk动态代理与cglib动态代理例子
  4. lvm 的用法和小案例
  5. 机器学习笔记(八):线性回归算法的评测标准 | 凌云时刻
  6. WEB UI设计尺寸规范
  7. ETERM航班销售控制指令
  8. 数据分析师说坐飞机安全么
  9. vue3 + crypto-js加密解密(普通版本/TS版本)
  10. 【AI视野·今日CV 计算机视觉论文速览 第151期】Tue, 6 Aug 2019
  11. ubuntu1404 安装 ppsspp
  12. 一文看全!史上以来的59家测序仪公司
  13. 鸿蒙系统宣传标语,有多项新功能加持,搭载鸿蒙系统的华为手表WATCH 3来了!...
  14. c# propertyGrid下拉选项
  15. 技嘉1080显卡体质测试软件,技嘉GTX 1080 Xtreme Gaming双卡SLI性能深度评测+拆解
  16. 神奇的css(动态水滴)
  17. no moudle named ‘sklearn‘
  18. Linux 版本分支图
  19. 平滑的加权轮询均衡算法
  20. HDFS查看文件大小以及统计 总和

热门文章

  1. 软件需求分析(以美团外卖为例)
  2. 《把时间当做朋友-李笑来》
  3. 山师计算机考研山大,研友分享:海大,山大,山师考研分析
  4. 九阴真经Ambari——1.熟悉Hortonworks官网结构并找到Ambari下载地址
  5. 这个“安装 OS X Yosemite”应用程序副本不能验证
  6. 高中数学知识点;二次函数与幂函数(高考备考)
  7. 轻松熊喵喵 -- 名词解释(自用)
  8. Spring Cloud 系列之 Alibaba Nacos 注册中心(一)
  9. 第一时间安装试用中科红旗桌面操作系统V11
  10. 看懂IPv6+,这篇就够了