1、在pom.xml添加依赖

        <dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>

2、自定义两个注解PassToken、UserLoginToken

package com.cn.commodity.annotations;

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 UserLoginToken {
boolean required() default true;
}
package com.cn.commodity.annotations;

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 PassToken {
boolean required() default true;
}

3、定义一个获取token的服务TokenService

package com.cn.commodity.service;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.cn.commodity.entity.User;
import org.springframework.stereotype.Service; @Service("tokenService")
public class TokenService { public String getToken(User user) { //生成token
String token="";
token= JWT.create().withAudience(String.valueOf(user.getId()))
.sign(Algorithm.HMAC256(user.getPassword()));
return token;
}
}

4、定义一个拦截器

package com.cn.commodity.interceptor;

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.exceptions.JWTVerificationException;
import com.cn.commodity.annotations.PassToken;
import com.cn.commodity.annotations.UserLoginToken;
import com.cn.commodity.entity.User;
import com.cn.commodity.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method; public class AuthenticationInterceptor implements HandlerInterceptor {
@Autowired
UserService userService; @Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token
// 如果不是映射到方法直接通过
if (!(object instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) object;
Method method = handlerMethod.getMethod();
//检查是否有passtoken注释,有则跳过认证
if (method.isAnnotationPresent(PassToken.class)) {
PassToken passToken = method.getAnnotation(PassToken.class);
if (passToken.required()) {
return true;
}
}
//检查有没有需要用户权限的注解
if (method.isAnnotationPresent(UserLoginToken.class)) {
UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
if (userLoginToken.required()) {
// 执行认证
if (token == null) {
throw new RuntimeException("无token,请重新登录");
}
// 获取 token 中的 user id
String userId;
try {
userId = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
throw new RuntimeException("401");
}
User user = userService.getUserById(Integer.parseInt(userId));
if (user == null) {
throw new RuntimeException("用户不存在,请重新登录");
}
// 验证 token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
try {
jwtVerifier.verify(token);
} catch (JWTVerificationException e) {
throw new RuntimeException("401");
}
return true;
}
}
return true;
} @Override
public void postHandle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, ModelAndView modelAndView) throws Exception { } @Override
public void afterCompletion(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, Exception e) throws Exception {
}
}

5、在项目中应用该拦截器

package com.cn.commodity.interceptor;

import org.springframework.context.annotation.Bean;
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 InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor())
.addPathPatterns("/**"); // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
}
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
}

6、在controller层应用注解进行验证


package com.cn.commodity.controller;

import com.alibaba.fastjson.JSONObject;
import com.cn.commodity.annotations.PassToken;
import com.cn.commodity.annotations.UserLoginToken;
import com.cn.commodity.dao.UserDao;
import com.cn.commodity.entity.User;
import com.cn.commodity.service.TokenService;
import com.cn.commodity.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @RestController
@RequestMapping("api")
public class UserApi {
@Autowired
UserService userService;
@Autowired
TokenService tokenService; @Resource
private UserDao userDao;
//登录
@PostMapping("/login")
public Object login(@RequestBody User user){
JSONObject jsonObject=new JSONObject();
//User userForBase=userService.getUserById(user.getId());
User userForBase=userDao.selectOne(user);
if(userForBase==null){
jsonObject.put("message","登录失败,用户不存在");
return jsonObject;
}else {
if (!userForBase.getPassword().equals(user.getPassword())){
jsonObject.put("message","登录失败,密码错误");
return jsonObject;
}else {
String token = tokenService.getToken(userForBase);
jsonObject.put("token", token);
jsonObject.put("user", userForBase);
return jsonObject;
}
}
}
@UserLoginToken
@GetMapping("/getMessage")
public String getMessage(){
return "你已通过验证";
} @PassToken
@GetMapping("/skipToken")
public String skipToken(){
return "跳过passToken认证";
}
}
 

7、运行测试

a) 登陆获取token

#获取token,在项目中可以将token和user组合存在redis中。
post请求参数:
{
"userName":"yangwj1",
"password":"wj1"
} 请求url:http://localhost:8080/api/login 返回参数:
{
"user": {
"id": 2,
"userName": "yangwj1",
"password": "wj1",
"age": 1
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyIn0.z2EzbIbYLCmw5PM5Yx9arE5QGUH9ET_AC0BEy9SyE8A"
}

b)跳过token认证

请求url:http://localhost:8080/api/skipToken

返回参数:跳过passToken认证
    

c)对api进行token验证

请求参数header中:
token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyIn0.z2EzbIbYLCmw5PM5Yx9arE5QGUH9ET_AC0BEy9SyE8A 请求url:http://localhost:8080/api/getMessage 返回参数:你已通过验证

springboot之JWT实现权限认证的更多相关文章

  1. SpringBoot集成JWT实现权限认证

    目录 一.JWT认证流程 二.SpringBoot整合JWT 三.测试 上一篇文章<一分钟带你了解JWT认证!>介绍了JWT的组成和认证原理,本文将介绍下SpringBoot整合JWT实现 ...

  2. springboot使用jwt进行权限验证

    springboot使用jwt进行权限验证 依赖准备 首先导入对应的依赖 <dependencies> <dependency> <groupId>org.apac ...

  3. SpringBoot整合JWT实现登录认证

    什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点 ...

  4. spring-boot整合shiro作权限认证

    spring-shiro属于轻量级权限框架,即使spring-security更新换代,市场上大多数企业还是选择shiro 废话不多说  引入pom文件 <!--shiro集成spring--& ...

  5. springboot集成shiro实现权限认证

    github:https://github.com/peterowang/shiro 基于上一篇:springboot集成shiro实现身份认证 1.加入UserController package ...

  6. Shiro-JWT SpringBoot前后端分离权限认证的一种思路

    JWT-Shiro 整合 JWT-与Shiro整合进行授权认证的大致思路 图示 大致思路 将登录验证从shiro中分离,自己结合JWT实现 用户登陆后请求认证服务器进行密码等身份信息确认,确认成功后 ...

  7. 轻松上手SpringBoot+SpringSecurity+JWT实RESTfulAPI权限控制实战

    前言 我们知道在项目开发中,后台开发权限认证是非常重要的,springboot 中常用熟悉的权限认证框架有,shiro,还有就是springboot 全家桶的 security当然他们各有各的好处,但 ...

  8. JWT实现登录认证实例

    JWT全称JSON Web Token,是一个紧凑的,自包含的,安全的信息交换协议.JWT有很多方面的应用,例如权限认证,信息交换等.本文将简单介绍JWT登录权限认证的一个实例操作. JWT组成 JW ...

  9. SpringBoot系列 - 集成JWT实现接口权限认证

    会飞的污熊 2018-01-22 16173 阅读 spring jwt springboot RESTful API认证方式 一般来讲,对于RESTful API都会有认证(Authenticati ...

随机推荐

  1. SpringCloud各个组件通俗解析

    https://www.cnblogs.com/lonelyJay/p/9936241.html

  2. maven常用命令参数

    整理了一些maven常用命令参数,以便参考:参考了maven官网和网上其他一些maven追随者的文件,不在此一一列举,但表示感谢! mvn命令参数 mvn -v, --version 显示版本信息; ...

  3. spark几个错误

    一.java.lang.NoSuchMethodError: net.jpountz.lz4.LZ4BlockInputStream.<init>(Ljava/io/InputStream ...

  4. Python与数据库 sqlalchemy 建立声明层表对象的两种方式

    在对表对象进行建立的时候,通常有两种方式可以完成,以下是两种方式的建立过程对比 首先导入需要的模块,获取一个声明层 1 from sqlalchemy.sql.schema import Table, ...

  5. HDU 6154 - CaoHaha's staff | 2017 中国大学生程序设计竞赛 - 网络选拔赛

    /* HDU 6154 - CaoHaha's staff [ 构造,贪心 ] | 2017 中国大学生程序设计竞赛 - 网络选拔赛 题意: 整点图,每条线只能连每个方格的边或者对角线 问面积大于n的 ...

  6. Codeforces Round #598 (Div. 3) A,B,C,D{E,F待补}

    A. Payment Without Change   #include<bits/stdc++.h> using namespace std; #define int long long ...

  7. learning express step(十三)

    learning express error handle code: const express = require('express'); const app = express(); app.g ...

  8. 原来INF文件是干这个的

    When the drivers for a device are installed, the installer uses information in an information (INF) ...

  9. UOJ269. 【清华集训2016】如何优雅地求和 [生成函数]

    传送门 思路 神仙题.jpg 脑子一抽,想把\(f(x)\)表示成下降幂的形式,也就是 \[ f(x)=\sum_{i=0}^m f_ix_{(i)}\\ x_{(i)}=\prod_{k=0}^{i ...

  10. mac 安装软件 显示信任任何来源

    “通用”里有时没有“任何来源”这个选项: 显示"任何来源"选项在控制台中执行: sudo spctl --master-disable 不显示"任何来源"选项( ...