时间:2021-05-19
本文介绍了Spring-boot结合Shrio实现JWT的方法,分享给大家,具体如下:
关于验证大致分为两个方面:
主要解决方法:使用自定义的Shiro Filter
项目搭建:
这是一个spring-boot 的web项目,不了解spring-boot的项目搭建,请google。
pom.mx引入相关jar包
<!-- shiro 权限管理 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>${shiro.version}</version> </dependency> <!-- JWT --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency>Shrio 的相关配置
划重点!!自定义了一个Filter
filterMap.put("JWTFilter", new JWTFilter());@Configurationpublic class ShiroConfig { @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); // 添加自己的过滤器并且取名为JWTFilter Map<String, Filter> filterMap = new HashMap<>(); filterMap.put("JWTFilter", new JWTFilter()); shiroFilterFactoryBean.setFilters(filterMap); /* * 自定义url规则 * http://shiro.apache.org/web.html#urls- */ Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap(); filterChainDefinitionMap.put("/**", "JWTFilter"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } /** * securityManager 不用直接注入shiroDBRealm,可能会导致事务失效 * 解决方法见 handleContextRefresh * http://pact(); httpServletResponse.addHeader(AUTHORIZATION_HEADER, updateToken); //添加用户凭证 PrincipalCollection principals = new SimplePrincipalCollection(body.getId(), JWTCost.UserNamePasswordRealm);//拼装shiro用户信息 WebSubject.Builder builder = new WebSubject.Builder(servletRequest, servletResponse); builder.principals(principals); builder.authenticated(true); builder.sessionCreationEnabled(false); WebSubject subject = builder.buildWebSubject(); //塞入容器,统一调用 ThreadContext.bind(subject); filterChain.doFilter(httpServletRequest, httpServletResponse); } } else { httpServletResponse.setStatus(HttpStatus.FORBIDDEN.value()); } } }}登录失败处理
处理Shrio异常
@RestControllerAdvicepublic class GlobalControllerExceptionHandler { @ExceptionHandler(value = Exception.class) public Object allExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception exception) { String message = exception.getCause().getMessage(); LogUtil.error(message); return new ResultInfo(exception.getClass().getName(), message); } @ExceptionHandler(value = IncorrectCredentialsException.class) public String IncorrectCredentialsException(HttpServletRequest request, HttpServletResponse response, Exception exception) { response.setStatus(HttpStatus.FORBIDDEN.value()); return "IncorrectCredentialsException"; } @ExceptionHandler(value = UnknownAccountException.class) public String UnknownAccountException(HttpServletRequest request, HttpServletResponse response, Exception exception) { response.setStatus(HttpStatus.FORBIDDEN.value()); return "UnknownAccountException"; } @ExceptionHandler(value = LockedAccountException.class) public String LockedAccountException(HttpServletRequest request, HttpServletResponse response, Exception exception) { response.setStatus(HttpStatus.FORBIDDEN.value()); return "LockedAccountException"; } @ExceptionHandler(value = ExcessiveAttemptsException.class) public String ExcessiveAttemptsException(HttpServletRequest request, HttpServletResponse response, Exception exception) { response.setStatus(HttpStatus.FORBIDDEN.value()); return "ExcessiveAttemptsException"; } @ExceptionHandler(value = AuthenticationException.class) public String AuthenticationException(HttpServletRequest request, HttpServletResponse response, Exception exception) { response.setStatus(HttpStatus.FORBIDDEN.value()); return "AuthenticationException"; } @ExceptionHandler(value = UnauthorizedException.class) public String UnauthorizedException(HttpServletRequest request, HttpServletResponse response, Exception exception) { response.setStatus(HttpStatus.FORBIDDEN.value()); return "UnauthorizedException"; }}处理JWT异常
这是个坑,因为是在filter内发生的异常,@ExceptionHandler是截获不到的。
/** * 截获spring boot Error页面 */@RestControllerpublic class GlobalExceptionHandler implements ErrorController { @Override public String getErrorPath() { return "/error"; } @RequestMapping(value = "/error") public Object error(HttpServletRequest request, HttpServletResponse response) throws Exception { // 错误处理逻辑 Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception"); Throwable cause = exception.getCause(); if (cause instanceof ExpiredJwtException) { response.setStatus(HttpStatus.GATEWAY_TIMEOUT.value()); return new ResultInfo("ExpiredJwtException", cause.getMessage()); } if (cause instanceof MalformedJwtException) { response.setStatus(HttpStatus.FORBIDDEN.value()); return new ResultInfo("MalformedJwtException", cause.getMessage()); } return new ResultInfo(cause.getCause().getMessage(), cause.getMessage()); }}关于权限等授权信息,可以直接放到Redis中实现缓存。我认为也是不错的。
源码奉上:githup-shiro分支 :温馨提示:平时测试代码可能比较乱。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
spring-boot是基于spring框架的,它并不是对spring框架的功能增强,而是对spring的一种快速构建的方式。spring-boot应用程序提供
了解过spring-Boot这个技术的,应该知道Spring-Boot的核心配置文件application.properties,当然也可以通过注解自定义配置文
1.什么是spring-boot-devtoolsspring-boot-devtools是spring-boot项目开发时的一个热部署工具,安装了spring
女朋友他们项目用了spring-boot,以spring-boot-parent作为parent:org.springframework.bootspring-
SpringBoot官方文档http://docs.spring.io/spring-boot/docs/current/reference/htmlsingl