赞
踩
互相交流入口地址
整体目录:
【九】springboot整合redis实现启动服务时热点数据保存在全局和缓存
【十三】springboot整合WebService关于传参数
【十五】springboot整合WebSocket实现聊天室
【十六】RabbitMQ基础篇(下载安装并基础使用,内含各种坑问题)
【十九】初学Kafka并实战整合SpringCloudStream进行使用
【二十】springboot整合ElasticSearch实战(万字篇)
【二十三】springboot整合activiti7(1)实战演示篇
【二十四】springboot整合spring事务详解以及实战
【二十五】springboot使用EasyExcel和线程池实现多线程导入Excel数据
【二十六】springboot整合jedis和redisson布隆过滤器处理缓存穿透
【二十八】springboot之threadLocal参数解析器实现session一样保存当前登录功能
目录
第三步:新增token工具类(用来生成token以及效验token)
介绍:接下来我会把学习阶段学到的框架等知识点进行整合,每一次整合是在前一章的基础上进行的,所以后面的整合不会重复放前面的代码。每次的demo我放在结尾,本次是接着上一章的内容延续的,只增加新增的或者修改的代码。
整合token,每次请求接口时进行token效验,效验通过才可以请求到接口,我是通过jwt生成的token。token个人理解大概就是用来判断用户登录状态,是否已登录的。
首先展示一下目录结构,是根据前面几章进行的增加(原因:内容过多),如下:
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </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>
- </dependency>
-
- <!--swagger -->
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-swagger2</artifactId>
- <version>2.9.2</version>
- </dependency>
- <!--swagger-ui.html模式 -->
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-swagger-ui</artifactId>
- <version>2.9.2</version>
- </dependency>
- <!--doc.html模式 -->
- <dependency>
- <groupId>com.github.xiaoymin</groupId>
- <artifactId>swagger-bootstrap-ui</artifactId>
- <version>1.9.2</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
- <dependency>
- <groupId>com.auth0</groupId>
- <artifactId>java-jwt</artifactId>
- <version>3.9.0</version>
- </dependency>
-
- <!-- https://mvnrepository.com/artifact/org.json/json -->
- <dependency>
- <groupId>org.json</groupId>
- <artifactId>json</artifactId>
- <version>20190722</version>
- </dependency>
- </dependencies>
其实就增加了jwt和json两个依赖。
TokenInterceptor类(拦截器):
- @Component
- public class TokenInterceptor implements HandlerInterceptor {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
-
- //跨域请求会首先发一个option请求,直接返回正常状态并通过拦截器
- if(request.getMethod().equals("OPTIONS")){
- response.setStatus(HttpServletResponse.SC_OK);
- return true;
- }
- response.setCharacterEncoding("utf-8");
- String token = request.getHeader("token");
- if (token!=null){
- boolean result= TokenUtils.verify(token);
- if (result){
- System.out.println("通过拦截器");
- return true;
- }
- }
- response.setContentType("application/json; charset=utf-8");
- try {
- JSONObject json=new JSONObject();
- json.put("msg","token verify fail");
- json.put("code","500");
- response.getWriter().append(json.toString());
- System.out.println("认证失败,未通过拦截器");
- } catch (Exception e) {
- return false;
- }
- /**
- * 还可以在此处检验用户存不存在等操作
- */
- return false;
- }
- }
PS:此处token从request里面获取header里面的key值是token,你要根据自己的情况来,你在前端header里面传的token叫什么名称,这里就取什么名字。
WebConfiguration类(配置拦截器):
- @Configuration
- public class WebConfiguration implements WebMvcConfigurer {
-
- @Autowired
- private TokenInterceptor tokenInterceptor;
-
- /**
- * 解决跨域请求
- * @param registry
- */
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping("/**")
- .allowedHeaders("*")
- .allowedMethods("*")
- // .allowedOrigins("*")
- .allowedOriginPatterns("*")
- .allowCredentials(true);
- }
-
- /**
- * 异步请求配置
- * @param configurer
- */
- @Override
- public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
- configurer.setTaskExecutor(new ConcurrentTaskExecutor(Executors.newFixedThreadPool(3)));
- configurer.setDefaultTimeout(30000);
- }
-
- /**
- * 配置拦截器、拦截路径
- * 每次请求到拦截的路径,就会去执行拦截器中的方法
- * @param configurer
- */
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- List<String> excludePath = new ArrayList<>();
- //排除拦截,除了注册登录(此时还没token),其他都拦截
- excludePath.add("/userController/login"); //登录
- excludePath.add("/userController/register"); //注册
- excludePath.add("/doc.html"); //swagger
- excludePath.add("/swagger-ui.html"); //swagger
- excludePath.add("/swagger-resources/**"); //swagger
- excludePath.add("/v2/api-docs"); //swagger
- excludePath.add("/webjars/**"); //swagger
- // excludePath.add("/static/**"); //静态资源
- // excludePath.add("/assets/**"); //静态资源
- registry.addInterceptor(tokenInterceptor)
- .addPathPatterns("/**")
- .excludePathPatterns(excludePath);
- WebMvcConfigurer.super.addInterceptors(registry);
-
- }
- }
PS:addInterceptors方法里面需要按自己情况进行修改,excludePath集合add的是需要放行的接口路径,前几章整合了swagger,所以此处需要放行swagger相关的路径,swagger-ui.html、doc.html、swagger-resources、等等,你再加上自己想要放行的接口路径即可,一般是首页请求的接口以及登录注册的接口(不需要进行token效验的接口)。
- public class TokenUtils {
-
- //token到期时间10小时
- private static final long EXPIRE_TIME= 10*60*60*1000;
- //密钥盐
- private static final String TOKEN_SECRET="ljdyaishijin**3nkjnj??";
-
- /**
- * 生成token
- * @param user
- * @return
- */
- public static String sign(User user){
-
- String token=null;
- try {
- Date expireAt=new Date(System.currentTimeMillis()+EXPIRE_TIME);
- token = JWT.create()
- //发行人
- .withIssuer("auth0")
- //存放数据
- .withClaim("username",user.getUserName())
- //过期时间
- .withExpiresAt(expireAt)
- .sign(Algorithm.HMAC256(TOKEN_SECRET));
- } catch (IllegalArgumentException|JWTCreationException je) {
-
- }
- return token;
- }
-
-
- /**
- * token验证
- * @param token
- * @return
- */
- public static Boolean verify(String token){
-
- try {
- //创建token验证器
- JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
- DecodedJWT decodedJWT=jwtVerifier.verify(token);
- System.out.println("认证通过:");
- System.out.println("username: " + decodedJWT.getClaim("username").asString());
- System.out.println("过期时间: " + decodedJWT.getExpiresAt());
- } catch (IllegalArgumentException |JWTVerificationException e) {
- //抛出错误即为验证不通过
- return false;
- }
- return true;
- }
-
- }
PS:此处到期时间可以自定义按情况进行设置,1000是1秒。此处token的生成方法以及效验方法可以根据具体情况进行更改,生成token1是使用的jwt,此处验证方法存在一个用户有多个token的情况(可以同时多次登陆同一账号,重新请求token之后,前一次的token只要没有过期也能使用。),可以整合redis后进行改造(后面会讲到),可以达到一个用户只有一个token的效果(重新请求token之后,前一次的token即使没有过期也不能使用。)
- @ApiOperation(value = "登录")
- @GetMapping("/login")
- @ApiImplicitParams({
- @ApiImplicitParam(name = "userName", value = "用户名", paramType = "String"),
- @ApiImplicitParam(name = "passWord", value = "密码", paramType = "String")
- })
- public BaseResponse<HashMap> login(@RequestParam(value = "userName") String userName, @RequestParam(value = "passWord") String passWord) throws JsonProcessingException {
- //包装token
- User user = new User();
- user.setUserName(userName);
- user.setPassword(passWord);
- String token= TokenUtils.sign(user);
- HashMap<String,Object> hs=new HashMap<>();
- hs.put("token",token);
- return RespGenerator.returnOK(hs);
- }
PS:可以根据自己的情况包装数据作为登录请求的返回结果。
1、当请求没有放行的接口不带token请求时:
结果:会提示token效验失败。
2、当请求放行的接口不带token请求时:
结果:成功请求到接口,此处是登陆接口,返回了token。
3、当请求没有放行的接口带token请求时:
结果:成功请求到接口。
本期整合到此完毕,接下来会继续更新加强整合,尽情期待。
访问地址:http://localhost:8085/swagger-ui.html或者http://localhost:8085/doc.html
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。