拦截器

1.结构架构图

2.Shiro拦截器

2.1.ShiroConfig

代码:

package com.auth;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {@Autowiredprivate LoginRealm  loginRealm;/*** 配置安全管理器:哪种类型的管理器* @return*/@Beanpublic SecurityManager securityManager() {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();/** 关闭shiro自带的session,详情见文档* http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29*/DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();defaultSessionStorageEvaluator.setSessionStorageEnabled(false);subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);securityManager.setSubjectDAO(subjectDAO);// 设置自定义 realm.securityManager.setRealm(loginRealm);return securityManager;}/*** 配置拦截器* @param securityManager* @return*/@Beanpublic ShiroFilterFactoryBean factory(SecurityManager securityManager) {ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();factoryBean.setSecurityManager(securityManager);Map filterMap = new HashMap();factoryBean.setFilters(filterMap);// 设置无权限时跳转的 url;Map<String, String> filterRuleMap = new HashMap();//访问/login和/unauthorized 不需要经过过滤器//设置我们自定义的JWT过滤器filterMap.put("jwt", new JWTFilter());//不登录就能访问的写这里//filterRuleMap.put("/api2/**", "anon");filterRuleMap.put("/api/**","jwt,authc");//此网页需要过滤判断以后才能通过//必须要登录才能访问写这里filterRuleMap.put("/**", "anon");// 访问 /unauthorized/** 不通过JWTFilterfactoryBean.setFilterChainDefinitionMap(filterRuleMap);return factoryBean;}}

2.1.1.该类是一个config类(配置类)

2.1.2.设置我们自定义的JWT过滤器,并命名为jwt

filterMap.put("jwt", new JWTFilter());

2.1.3.必须要登录才能访问(要验证令牌,使用"jwt,authc",一般用于删除、修改、查询等界面)

filterRuleMap.put("/api/**","jwt,authc");

2.1.4.不登录就能访问(直接放行,不需要去做验证,一般用于登录,首页等界面)

filterRuleMap.put("/**", "anon");

2.2.JWTFilter

代码:

package com.auth;import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class JWTFilter extends BasicHttpAuthenticationFilter {/*** 第二步* 是否能进下一步处理** @param request* @param response* @param mappedValue* @return true可以访问action了,false则执行onAccessDenied*/@Overrideprotected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {try {//System.out.println("isAccessaLLOWED");//得到客户端传过来的令牌String token = ((HttpServletRequest) request).getHeader("token");//System.out.println("客户端令牌"+token);//封装JWTToken jwtToken = new JWTToken(token);//登录:实际是调用LoginRealm里面doGetAuthenticationInfogetSubject(request, response).login(jwtToken);//判断是否有权限String url = ((HttpServletRequest) request).getRequestURI();getSubject(request, response).checkPermission(url);return true;} catch (Exception e) {return false;}}@Overrideprotected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {System.out.println("onAccessDenied");HttpServletResponse r = (HttpServletResponse) response;r.setStatus(401);return false;}/*** 用于跨域   第一步** @param request* @param response* @return true可以进下一步isAccessAllowed,如果false则被拦截不能通过* @throws Exception*/@Overrideprotected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {//System.out.println("这是preHandle");HttpServletRequest httpServletRequest = (HttpServletRequest) request;HttpServletResponse httpServletResponse = (HttpServletResponse) response;httpServletResponse.addHeader("Access-Control-Allow-Origin", "*");httpServletResponse.addHeader("Access-Control-Allow-Headers", "*");httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");httpServletResponse.addHeader("Access-Control-Expose-Headers", "token");// 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {httpServletResponse.setStatus(HttpStatus.OK.value());return false;}//更新令牌且发送给客户端String token = ((HttpServletRequest) request).getHeader("token");//System.out.println("更新令牌"+token);String newToken = JwtUtil.updateToken(token);if (newToken.length() > 0) {httpServletResponse.addHeader("token", newToken);//System.out.println("更新以后的令牌判断"+token);}return super.preHandle(request, response);}
}

2.2.1.用于跨域

2.2.2更新令牌且发送给客户端放在header里的原因是,最好在body里放数据。当newToken.length()等于0时,说明令牌失效或者是错误的。

String token = ((HttpServletRequest) request).getHeader("token");
String newToken = JwtUtil.updateToken(token);
if (newToken.length() > 0) {httpServletResponse.addHeader("token", newToken);
}
return super.preHandle(request, response);

2.3.JWTToken

代码:

package com.auth;import org.apache.shiro.authc.AuthenticationToken;public class JWTToken implements AuthenticationToken {private String token;public JWTToken(){}/*** Instantiates a new Jwt token.** @param token the token*/public JWTToken(String token) {this.token = token;}/*** 以前的用户名* @return*/@Overridepublic Object getPrincipal() {return token;}/*** 以前的密码* @return*/@Overridepublic Object getCredentials() {return token;}
}

2.3.1.相当于pojo,里面有用户名、密码

2.4.LoginRealm

代码:

ackage com.auth;import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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.stereotype.Component;@Component
public class LoginRealm extends AuthorizingRealm {@Overridepublic boolean supports(AuthenticationToken token) {return token instanceof JWTToken;}/*** 管授权* @param principals* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();String tokenString = principals.toString();String username = JwtUtil.getUsername(tokenString);//查数据库,用户的权限,略,通过用户名从数据库查authorizationInfo.addStringPermission("/api/show");return authorizationInfo;}/*** 管登录* @param token* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//JWTFilter传过来的令牌String tokenString =(String) token.getPrincipal();//System.out.println("JWTFilter传过来的令牌"+tokenString);//取用户名,如果为null则无效String username = JwtUtil.getUsername(tokenString);if (username==null){throw new RuntimeException("令牌无效");}return new SimpleAuthenticationInfo(tokenString, tokenString, getName());}
}

2.4.1.主要是两个功能,一个是管理登录,还有一个是管理权限

2.4.2.JWTFilter传过来的令牌

String tokenString =(String) token.getPrincipal();

2.4.3.取用户名,如果为null则无效返回的new SimpleAuthenticationInfo(tokenString, tokenString, getName()),其实是一个布尔类型即true或者false

String username = JwtUtil.getUsername(tokenString);
if (username==null)
{throw new RuntimeException("令牌无效");
}
return new SimpleAuthenticationInfo(tokenString, tokenString, getName());

2.4.4.查数据库,用户的权限,略

authorizationInfo.addStringPermission("/api/searchDep");authorizationInfo.addStringPermission("/api/removeDep");

2.5.JwtUtil

代码:

package com.auth;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;@Component
public class JwtUtil {//密码,绝对保密,写在配置文件中public static String sercetKey = "mingtianhenganghao";public final static long keeptime = 180000000;/* @Value("${token.sercetKey}")public  static String sercetKey;@Value("${token.keeptime:30000}")public static long keeptime;*/public static void main(String[] args) {//根据用户名产生令牌// String token = JwtUtil.generToken("admin", null,null);//System.out.println(token);//根据令牌取用户名String token="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhZG1pbiIsImlhdCI6MTU5OTkxMzA5MSwiZXhwIjoxNTk5OTMxMDkxfQ.9_P_o9hwbsdlo2517jfSUoB3flUvCvOg1m96MCwHkks";String username = JwtUtil.getUsername(token);System.out.println(username);}/*** 产生令牌* @param id  用户名* @param issuer  签发者* @param subject 主体(内容)* @return*/public static String generToken(String id, String issuer, String subject) {long ttlMillis = keeptime;SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(sercetKey);Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());JwtBuilder builder = Jwts.builder().setId(id).setIssuedAt(now);if (subject != null) {builder.setSubject(subject);}if (issuer != null) {builder.setIssuer(issuer);}builder.signWith(signatureAlgorithm, signingKey);if (ttlMillis >= 0) {long expMillis = nowMillis + ttlMillis;Date exp = new Date(expMillis);builder.setExpiration(exp);}return builder.compact();}/*** 更新令牌* @param token* @return*/public static String updateToken(String token) {try {Claims claims = verifyToken(token);String id = claims.getId();String subject = claims.getSubject();String issuer = claims.getIssuer();Date date = claims.getExpiration();return generToken(id, issuer, subject);} catch (Exception ex) {//  ex.printStackTrace();}return "";}/*** 获取用户名* @param token* @return*/public static String getUsername(String token) {try {Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(sercetKey)).parseClaimsJws(token).getBody();return claims.getId();} catch (Exception e) {//e.printStackTrace();}return null;}public static Claims verifyToken(String token) {Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(sercetKey)).parseClaimsJws(token).getBody();return claims;}
}

2.5.1.三个功能:将用户信息变为令牌,将令牌还原,更新令牌(设置令牌失效时间)

2.5.2.产生令牌

public static String generToken(String id, String issuer, String subject) {long ttlMillis = keeptime;SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(sercetKey);Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());JwtBuilder builder = Jwts.builder().setId(id).setIssuedAt(now);if (subject != null) {builder.setSubject(subject);}if (issuer != null) {builder.setIssuer(issuer);}builder.signWith(signatureAlgorithm, signingKey);if (ttlMillis >= 0) {long expMillis = nowMillis + ttlMillis;Date exp = new Date(expMillis);builder.setExpiration(exp);}return builder.compact();
}

2.5.3.还原令牌信息(获取用户名)

public static String getUsername(String token) {try {Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(sercetKey)).parseClaimsJws(token).getBody();return claims.getId();} catch (Exception e) {//e.printStackTrace();}return null;
}

2.5.4.更新令牌(设置令牌实效时间)

public static String updateToken(String token) {try {Claims claims = verifyToken(token);String id = claims.getId();String subject = claims.getSubject();String issuer = claims.getIssuer();Date date = claims.getExpiration();return generToken(id, issuer, subject);} catch (Exception ex) {//  ex.printStackTrace();}return "";
}

(设置实效时间)

/* @Value("${token.sercetKey}") public  static String sercetKey; @Value("${token.keeptime:30000}") public static long

读者福利:

由于篇幅限制,不能完整的把全部内容分享出来,如果你觉得此文档对你有帮助,那就关注+点赞哦

shiro 文档_spring---Shiro拦截器相关推荐

  1. Sharepoint的文档库用资源管理器方式浏览报错“Explorer View ”解决方案。

    最近在安装Wss3.0时候,在拷贝已存在资料到客户电脑上时,打开客户的文档库的资源管理器的时候,提示Explorer view 错误,而且客户端访问的时候也报错. 在经过N多的查询和搜索之后终于找到的 ...

  2. Chronos首页、文档和下载 - 作业调度器 - 开源中国社区

    Chronos首页.文档和下载 - 作业调度器 - 开源中国社区

  3. spring mvc拦截器_Spring MVC拦截器示例

    spring mvc拦截器 我认为现在是时候看看Spring的MVC拦截器机制了,这种机制已经存在了很多年,并且是一个非常有用的工具. Spring Interceptor会按照提示说:在传入的HTT ...

  4. oracle帮助文档_Spring Boot Config文档,使用IntelliJ IDEA的两种方法

    一个Spring Boot文档,两种方式. 在优锐课的java沙龙分享中,在现代软件开发中,应用程序由配置驱动. 如果可配置属性的数量很大,则很难记住每个属性的用途,结构或类型. 因此,有必要对这些属 ...

  5. 360安全卫士造成Sharepoint文档库”使用资源管理器打开“异常

    备注:企业用户还是少用360为妙 有客户反馈:部门里的XP SP2环境客户机全部异常,使用资源管理器打开Sharepoint文档库,看到的界面样式很老土,跟本地文件夹不一样. 刚开始在测试环境上折腾了 ...

  6. jvm-014(张龙老师jvm教程) ClassLoader 源码doc文档及数组类加载器

    一.ClassLoader 源码doc文档 ClassLoader是一个负责加载类的对象,它本身是一个抽象类.在给定一个类的二进制名字时,类加载器会尝试去定位(已经存在的class文件)或生成(动态代 ...

  7. 【PC工具】更新免费文库文档下载器,免费下载文库文档,冰点下载器

        节省大家时间先发总结: 今天更新的是亲测能用的冰点下载器     大圣文库就不用试了,收费的,目测事前能用是推广 域名加365或vvv的方法好像不好用了 总结:用今天更新的冰点文库 版本:v3 ...

  8. 针对word.docx文档的关键词索引器

    前言 之前曾想做这样一个工具,用来遍历目录下的word.docx文档查询关键词,主要是有几个目的: 1.在项目开始阶段,通过关键词检索feature,我脑子实在是记不住文档都在哪: 2.收尾阶段,检查 ...

  9. win10Word文档点击后文件资源管理器卡死转篮圈问题解决

    这几天在打开word文档的时候总会出现加载不出来页面卡死的状态,如下图所示: 但是先打开Word以后从中查找路径打开文件并没有问题.为此,我在网上查找了众多方法,起初以为是word的文档的问题,查看微 ...

最新文章

  1. linux平台的实验描述,基于LINUX的操作系统实验平台的设计与实现
  2. shell切割日志脚本
  3. Codechef REBXOR HYSBZ - 4260(01字典树+区间异或最大)
  4. IOC操作Bean管理注解方式(注入属性@Autowired和Qualifier)
  5. linux下进程调度模拟程序,linux认证辅导:linux进程调度模拟怎么做?
  6. python编写函数_如何用Python编写自己喜欢的R函数
  7. (Mirage系列之四)Mirage经典案例之集中桌面管理
  8. 【mysql知识点总结】
  9. PyTorch:tensor-数学API
  10. 【优化算法】多跟踪器优化算法 (MTOA)【含Matlab源码 1090期】
  11. 论文降重的技巧(一顿操作猛如虎-一看查重35%)
  12. 稳压二极管型号对应电压表
  13. 自动驾驶(五十八)---------自动驾驶2019年终盘点
  14. 声艺fx16调音台怎么样_声艺调音台FX16II使用说明书.doc
  15. Spring学习笔记—Spring之旅
  16. VMware14安装Ubuntu18.10
  17. Consumer消息拉取和消费流程分析
  18. 为什么你的大脑那么喜欢图表?13张图告诉你
  19. 证件照的要求是什么?
  20. android弱网模拟路由器,Mac 下使用命令行模拟弱网环境

热门文章

  1. R语言数据结构之矩阵
  2. postman 接口测试工具介绍
  3. 最大公约数 最小公倍数
  4. oracle安装时ins-32031,安装oracle数据库时的报错处理[INS-35172]
  5. python dict遍历性能,Python:遍历list vs over dict items效率
  6. numpy 修改数据类型
  7. javascript 字符串中间隔固定位置插入字符
  8. github上传文件夹教程
  9. 【文本分类】Attention-Based Bidirectional Long Short-Term Memory Networks for Relation Classification
  10. anaconda: import numpy报错:ImportError: DLL load failed: 找不到指定的模块。