springboot+jwt
大概了解下SpringMVC和jwt,百度
代码:
1.整体框架
2.controller
package com.yiyezhiqiu.jwt.jwt.controller; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPObject;
import com.yiyezhiqiu.jwt.jwt.annotation.LoginAnnotation;
import com.yiyezhiqiu.jwt.jwt.annotation.OtherPermit;
import com.yiyezhiqiu.jwt.jwt.domain.Users;
import com.yiyezhiqiu.jwt.jwt.service.IUsersService;
import com.yiyezhiqiu.jwt.jwt.service.impl.GetToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; /**
* 实现jwt,token验证
* 业务需求:没有登陆成功,不能访问其他页面,当登陆成功后,带入成功后返回给前端的token来访问其他页面
* 实现:
* 1.了解springMVC,mvc在实现时有处理controller,那么我们在处理controller前对路径进行拦截,实现WebMvcConfigure接口。
* 2.拦截处理:实现HandlerInterceptor接口 ,在实现类中对请求的token进行验证。
*
*
* 具体做法:
* 1.springboot整合mybatis,跑通能查数据库
* 2.写一个拦截处理器,即实现HandlerInterceptor接口
* 2.1:思路
* 对登陆操作不进行token验证,对非登陆操作要进行token验证
* 2.2:做法
* 2.2.1:写两个注解,一个是用来对登陆进行控制,一个是其他页面进行控制
* 2.2.2:开始写MyInterceptor中代码
*
*
* 3.实现WebMvcConfigure接口,对所有路径进行拦截,并把拦截器处理器实例加进来-》也就是实现拦截后使用拦截处理器去处理
*
*
*
*
*
*/ @Slf4j
@RestController
@RequestMapping(value = "/users")
public class UsersController { @Autowired
IUsersService usersService;
@Resource(name = "GetToken")
GetToken getToken; JSONObject jsonObject = new JSONObject(); /**
* 注册
*/
@RequestMapping(value = "/register",method = RequestMethod.POST,produces = "application/json")
public JSONObject register(@RequestBody Users users){ int result = usersService.saveUsers(users);
if(result >0){
jsonObject.put("status",true);
jsonObject.put("message","新增成功");
return jsonObject;
}else{
jsonObject.put("status",false);
jsonObject.put("message","新增失败");
return jsonObject;
}
} /**
* 登陆
* @param users
* @return
*/
@LoginAnnotation
@RequestMapping(value = "/login",method = RequestMethod.POST,produces = "application/json")
public JSONObject usersLogin(@RequestBody Users users){ log.info("userName;"+users.getUserName()+",password:"+users.getPassword()); int result = usersService.findUsers(users);
if(result >0){
String token = getToken.token(users);
jsonObject.put("users",users);
jsonObject.put("message",token); }else{
jsonObject.put("message","帐号或者密码错误");
}
return jsonObject;
} /**
* 其他页面
* @return
*/
@OtherPermit
@RequestMapping(value = "/otherPage",method = RequestMethod.GET)
public JSONObject otherPage(){
//模仿下登陆后,传入token,token验证后返回有效信息
JSONObject jsonObject = new JSONObject();
jsonObject.put("message","验证成功");
jsonObject.put("code",200);
return jsonObject;
} }
3.service:
3.1 IUserService
package com.yiyezhiqiu.jwt.jwt.service; import com.yiyezhiqiu.jwt.jwt.domain.Users; public interface IUsersService { public int saveUsers(Users users); public int findUsers(Users users); }
3.2 impl下的UsersServiceImpl
package com.yiyezhiqiu.jwt.jwt.service.impl; import com.yiyezhiqiu.jwt.jwt.dao.UsersDao;
import com.yiyezhiqiu.jwt.jwt.domain.Users;
import com.yiyezhiqiu.jwt.jwt.service.IUsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service; import java.util.HashMap;
import java.util.Map;
@Service
public class UsersServiceImpl implements IUsersService { @Autowired
UsersDao usersDao;
/**
* 新增
*/ @Override
public int saveUsers(Users users) {
int result = usersDao.saveUsers(users); return result ;
} /**
* 查询
*
*/ @Override
public int findUsers(Users users) { Map<String,Object> params = new HashMap<>();
params.put("userName",users.getUserName());
params.put("password", users.getPassword());
Users user = usersDao.findUsers(params); if(null != user){
return 1;
}else{
return 0;
}
}
}
3.3 impl下的GetToken
package com.yiyezhiqiu.jwt.jwt.service.impl; import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.yiyezhiqiu.jwt.jwt.domain.Users;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component; /**
* 生成token
*/
@Component("GetToken")
public class GetToken { public String token(Users users){ String token = "";
token = JWT.create().withAudience(users.getUserName()).sign(Algorithm.HMAC256(users.getPassword())); return token;
}
}
4.dao层
package com.yiyezhiqiu.jwt.jwt.dao; import com.yiyezhiqiu.jwt.jwt.domain.Users;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository; import java.util.Map; @Mapper
@Repository
public interface UsersDao { /**
* 注册用户
*/ public int saveUsers(Users users); /**
* 查询用户
*/ public Users findUsers (Map<String,Object> params); }
5.configure
package com.yiyezhiqiu.jwt.jwt.configure; import com.yiyezhiqiu.jwt.jwt.interceptor.MyInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration
public class MyWebMvcConfigure implements WebMvcConfigurer { /**
* 拦截url并给相应拦截处理器处理
* @param registry
*/ @Override
public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**")//拦截所有
.excludePathPatterns("/users/register");//不拦截这个注册路径
} } 6.interceptor
package com.yiyezhiqiu.jwt.jwt.interceptor; import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.yiyezhiqiu.jwt.jwt.annotation.LoginAnnotation;
import com.yiyezhiqiu.jwt.jwt.annotation.OtherPermit;
import com.yiyezhiqiu.jwt.jwt.dao.UsersDao;
import com.yiyezhiqiu.jwt.jwt.domain.Users;
import com.yiyezhiqiu.jwt.jwt.service.IUsersService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map; @Slf4j
@Component
public class MyInterceptor implements HandlerInterceptor { @Autowired
IUsersService usersService; @Autowired
UsersDao usersDao;
private static MyInterceptor myInterceptor; /**
* 这一段用来解决依赖注入不成功问题
*/
@PostConstruct
public void init (){
myInterceptor = this;
myInterceptor.usersDao = this.usersDao;
} /**
* springMVC正常流程时,处理器处理controller前被拦截处理
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { JSONObject jsonObject = new JSONObject();
String token = request.getHeader("token");
//HandleMethod包含一些controller的方法,handler 就是一个全路径方法
HandlerMethod handlerMethod = (HandlerMethod)handler;
Method method = handlerMethod.getMethod();
//思路,通过判断请求的路径中的方法是否有相应的注解
if(method.isAnnotationPresent(LoginAnnotation.class)){
log.info("这是登陆");
return true;
} //需要验证token
if(method.isAnnotationPresent(OtherPermit.class)){
//重置reset
response.reset();
//设置编码格式
response.setCharacterEncoding("utf-8");
response.setContentType("application/json");
//这里用reponse.getWriter()后面会报重复使用的错
ServletOutputStream pw = response.getOutputStream(); log.info("进来验证token");
if(StringUtils.isEmpty(token)){
jsonObject.put("message","no token"); pw.print(jsonObject.toJSONString());
return false;
}else{
try{
String userName = JWT.decode(token).getAudience().get(0);
log.info("userName;"+userName);
Map<String,Object> map = new HashMap<>();
map.put("userName",userName);
log.info("userDao:"+usersDao);
log.info("userservice:"+usersService);
Users users = myInterceptor.usersDao.findUsers(map); try{
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(users.getPassword())).build();
jwtVerifier.verify(token);
return true;
}catch (Exception e){
jsonObject.put("message","token invalid");
jsonObject.put("code","401");
pw.print(jsonObject.toJSONString());
return false;
} }catch(Exception e){
jsonObject.put("message","token invalid");
jsonObject.put("code","401");
pw.print(jsonObject.toJSONString());
return false;
} } }
return false;
} /**
* MVC时处理器处理controller后被拦截处理
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } /**
* 在返回视图前拦截
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/ @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }
}
7.annotation;
7.1 LoginAnnotation
package com.yiyezhiqiu.jwt.jwt.annotation; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* 注明是登陆注解
*/ @Target({ElementType.METHOD,ElementType.TYPE}) //注解放在哪,方法上还是类还是哪里
@Retention(RetentionPolicy.RUNTIME)//啥时候启用,运行时
public @interface LoginAnnotation { boolean get() default true; } 7.2 Otherpermit
package com.yiyezhiqiu.jwt.jwt.annotation; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* 其他页面注解
*/
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface OtherPermit { boolean other() default true;
}
8.domain
package com.yiyezhiqiu.jwt.jwt.domain; import lombok.Data; @Data
public class Users { private int id;
private String userName;
private String password;
private String gender; }
9.UsersMapping.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.yiyezhiqiu.jwt.jwt.dao.UsersDao"> <insert id = "saveUsers" parameterType="com.yiyezhiqiu.jwt.jwt.domain.Users" keyProperty="id" useGeneratedKeys="true">
insert into users(user_name,password,gender) values (#{userName},#{password},#{gender})
</insert> <select id="findUsers" parameterType="java.util.HashMap" resultType="com.yiyezhiqiu.jwt.jwt.domain.Users"> select * from users where
user_name = #{userName}
<if test="password != null and password != ''">
and password = #{password}
</if> </select>
</mapper>
10. application.yml
#端口号
server:
port: 8088 #数据库
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
username: root
password: zhang #dao和xml映射
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.yiyezhiqiu.jwt.jwt.domain #可以打印出sql语句
logging:
level:
com:
yiyezhiqiu:
jwt:
jwt:
dao: debug 11.pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yiyezhiqiu.jwt</groupId>
<artifactId>jwt</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jwt</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<!--jwt 依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency> <dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency> <dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency> <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>
结果:postman调试 1.登陆测试:输入用户名,密码。而且为正确
2.登陆测试,输入用户名和密码不正确
3. 不带token,访问其他页面
4.带正确toke访问其他页面
5.带不正确token访问其他页面
github地址:https://github.com/yiyeluowuchen/springboot-jwt-token.git
总结:
遇到问题与解决
1.问题:在拦截器 MyInterceptor中以下注入失败,一直报空。
@Autowired
IUsersService usersService; @Autowired
UsersDao usersDao; 解决:
/**
* 这一段用来解决依赖注入不成功问题
*/
private static MyInterceptor myInterceptor;
@PostConstruct
public void init (){
myInterceptor = this;
myInterceptor.usersDao = this.usersDao;
}
解决后调用方式:
Users users = myInterceptor.usersDao.findUsers(map); 解决该问题用到博客:
https://blog.csdn.net/georgeshaw1/article/details/749430892.
问题:在response.getWriter()时,报getWriter()has already been called for this response 异常
解决:
分析:该异常是response异常被其他调用了,我这里主要是因为在controller中有返回值给前端,然后在这里MyInterceptor中又用,就会导致这种情况
解决办法:
使用 ServletOutputStream pw = response.getOutputStream();代替 3.
报有:
ava.io.CharConversionException: Not an ISO 8859-1 character: [失] 分析:这是因为使用getOutputStrieam不能输出中文字符,改成英文就好了 4.多学习下注解的声明和使用场景
springboot+jwt的更多相关文章
- SpringBoot+JWT+SpringSecurity+MybatisPlus实现Restful鉴权脚手架
若图片查看异常,请前往掘金查看:https://juejin.im/post/5d1dee34e51d4577790c1cf4 前言 JWT(json web token)的无状态鉴权方式,越来越流行 ...
- springboot+jwt做api的token认证
本篇和大家分享jwt(json web token)的使用,她主要用来生成接口访问的token和验证,其单独结合springboot来开发api接口token验证很是方便,由于jwt的token中存储 ...
- SpringBoot+JWT+Shiro+MybatisPlus实现Restful快速开发后端脚手架
一.背景 前后端分离已经成为互联网项目开发标准,它会为以后的大型分布式架构打下基础.SpringBoot使编码配置部署都变得简单,越来越多的互联网公司已经选择SpringBoot作为微服务的入门级微框 ...
- springboot+jwt实现token登陆权限认证
一 前言 此篇文章的内容也是学习不久,终于到周末有时间码一篇文章分享知识追寻者的粉丝们,学完本篇文章,读者将对token类的登陆认证流程有个全面的了解,可以动态搭建自己的登陆认证过程:对小项目而已是个 ...
- SpringBoot + JWT + Redis 开源知识社区系统
「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识.准备 Java 面试,首选 JavaGuide!:https://javaguide.cn/ 你好,我是 Guide!这 ...
- springboot+jwt完成登录认证
本demo用于测试jwt,通过登录验证通过后,使用jwt生成token,然后在请求header中携带token完成访问用户列表信息. 准备工作: 1. 实体类SysUser.java package ...
- SpringBoot系列之前后端接口安全技术JWT
@ 目录 1. 什么是JWT? 2. JWT令牌结构怎么样? 2.1 标头(Header) 2.2 有效载荷(Playload) 2.3 签名(Signature) 3. JWT原理简单介绍 4. J ...
- 【原创】SpringBoot & SpringCloud 快速入门学习笔记(完整示例)
[原创]SpringBoot & SpringCloud 快速入门学习笔记(完整示例) 1月前在系统的学习SpringBoot和SpringCloud,同时整理了快速入门示例,方便能针对每个知 ...
- SpringBoot 并发登录人数控制
通常系统都会限制同一个账号的登录人数,多人登录要么限制后者登录,要么踢出前者,Spring Security 提供了这样的功能,本文讲解一下在没有使用Security的时候如何手动实现这个功能 dem ...
随机推荐
- 【H5适配 笔记1】rem适配
设备像素比(dpr)= 物理像素(手机渲染像素.分辨率)/设备独立像素(手机所显示元素的大小) 视口(viewport) 布局视口(获取浏览器布局视口高度,包括内边距,但不包括垂直滚动条.边框和外边距 ...
- PHPstorm主题、插件等相关推荐
自己想升级PHPstorm,但是一直升级不了,捣腾一下午,终于它over掉了. 重新下载安装,发现应该把自己喜欢的插件.主题配色等记录一下. material theme UI主题插件 不知道为啥,看 ...
- tensorflow expand_dims和squeeze
有时我们会碰到升维或降维的需求,比如现在有一个图像样本,形状是 [height, width, channels],我们需要把它输入到已经训练好的模型中做分类,而模型定义的输入变量是一个batch,即 ...
- [Python]python去除两个txt文件的重复词汇 python 2020.2.10
两个txt文件词汇,用换行符分隔.可以用代码将要处理的文件去掉另一个文件所包含的重复内容. 如: a.txt内容为: 衡山 泰山 西湖 紫禁城 b.txt内容为: 泰山 衡山 长白山 张三丰 将a.t ...
- 《深入理解java虚拟机》读书笔记八——第九章
第九章 类加载及执行子系统的案例与实战 Q:如果有10个WEB应用程序都是用Spring来进行组织管理的话,可以把Spring放到Common或Shared目录下(Tomcat5.0)让这些程序共享. ...
- MapReduce自定义排序器不生效一个可能的原因
有问题的代码: package com.mytq.weather; import org.apache.hadoop.io.WritableComparable; import org.apache. ...
- SpringBoot--自动配置原理-4个注解
一.自动配置原理 四个元注解:修饰注解的注解 @Target(ElementType.TYPE) 这个注解用在那个位置上,可以使用在类上,方法上,成员变量上 @Retention(RetentionP ...
- JAVAWEB应用模块(一)登录模块
java后台代码(MD5加密+token验证): import com.smart.ssai.admin.domain.User; import com.smart.ssai.admin.servic ...
- phpstorm汉化包
链接:https://pan.baidu.com/s/1dG7AWI87dOJJezra9veFrA 提取码:btmf 下载后放到lib目录中 即可
- Java TreeSet集合 比较器排序Comparator的使用
比较器排序Comparator的使用 存储学生对象,并遍历,创建TreeSet集合使用带参构造方法 要求,按照学生年龄从小到大排序,如果年龄相同,则按照姓名的字母循序排序 结论 用TreeSet集合存 ...