Springboot中怎么集成Spring Security JWT实现接口权限认证
发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,小编给大家分享一下Springboot中怎么集成Spring Security JWT实现接口权限认证,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下
千家信息网最后更新 2026年10月31日Springboot中怎么集成Spring Security JWT实现接口权限认证
小编给大家分享一下Springboot中怎么集成Spring Security JWT实现接口权限认证,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
1、添加依赖
org.springframework.boot spring-boot-starter-security io.jsonwebtoken jjwt 0.9.1 2、集成JWT工具类(JwtUtils)
package com.dreamteam.chdapp.utils;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.servlet.http.HttpServletRequest;import java.util.Date;import java.util.HashMap;import java.util.Map;/** * @Author HeYunHui * @create 2020/11/15 14:12 */public class JwtUtils { private static final Logger logger= LoggerFactory.getLogger(JwtUtils.class); public static final long EXPIRATION_TIME=60*60*1000;// 令牌环有效期 public static final String SECRET="abc123456def";//令牌环密钥 public static final String TOKEN_PREFIX="Bearer";//令牌环头标识 public static final String HEADER_STRING="Passport";//配置令牌环在http heads中的键值 public static final String ROLE="ROLE";//自定义字段-角色字段 //生成令牌环 public static String generateToken(String userRole,String userid){ HashMap map=new HashMap<>(); map.put(ROLE,userRole); map.put("userid",userid); String jwt= Jwts.builder() .setClaims(map) .setExpiration(new Date(System.currentTimeMillis()+EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS512,SECRET) .compact(); return TOKEN_PREFIX+" "+jwt; } //生成令牌环 public static String generateToken(String userRole,String userid,long exprationtime){ HashMap map=new HashMap<>(); map.put(ROLE,userRole); map.put("userid",userid); String jwt= Jwts.builder() .setClaims(map) .setExpiration(new Date(System.currentTimeMillis()+exprationtime)) .signWith(SignatureAlgorithm.HS512,SECRET) .compact(); return TOKEN_PREFIX+" "+jwt; } //令牌环校验 public static Map validateTokenAndGetClaims(HttpServletRequest request){ String token=request.getHeader(HEADER_STRING); if(token==null){ throw new TokenValidationException("Missing Token"); } else{ Map body= Jwts.parser() .setSigningKey(SECRET) .parseClaimsJws(token.replace(TOKEN_PREFIX,"")) .getBody(); return body; } } static class TokenValidationException extends RuntimeException{ public TokenValidationException(String msg){ super(msg); } }} 3、集成JWT filter(拦截器/过滤器)
package com.dreamteam.chdapp.filter;import com.dreamteam.chdapp.utils.JwtUtils;import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.util.AntPathMatcher;import org.springframework.util.PathMatcher;import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.util.Arrays;import java.util.Map;import static com.dreamteam.chdapp.utils.JwtUtils.ROLE;/** * @Author HeYunHui * @create 2020/11/15 14:46 */public class JwtAuthenticationFilter extends OncePerRequestFilter { private static final PathMatcher pathmatcher = new AntPathMatcher(); private String[] protectUrlPattern = {"/manage/**", "/member/**", "/auth/**"}; //哪 些请求需要进行安全校验 public JwtAuthenticationFilter() { } @Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {//是不是可以在这里做多种方式登录呢 try { if (isProtectedUrl(httpServletRequest)) { Map claims = JwtUtils.validateTokenAndGetClaims(httpServletRequest); String role = String.valueOf(claims.get(ROLE)); String userid = String.valueOf(claims.get("userid")); //最关键的部分就是这里, 我们直接注入了 SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken( userid, null, Arrays.asList(() -> role) )); } } catch (Exception e) { e.printStackTrace(); httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage()); return; } filterChain.doFilter(httpServletRequest, httpServletResponse); } //是否是保护连接 private boolean isProtectedUrl(HttpServletRequest request) { boolean flag = false; for (int i = 0; i < protectUrlPattern.length; i++) { if (pathmatcher.match(protectUrlPattern[i], request.getServletPath())) { return true; } } return false; }} 4、配置JWT config类(配置类)
跨域访问:客户端与服务端域名不同或是端口号不同。防止跨域攻击
package edu.ynmd.cms.config;import edu.ynmd.cms.filter.JwtAuthenticationFilter;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.config.http.SessionCreationPolicy;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;import org.springframework.security.web.firewall.HttpFirewall;import org.springframework.security.web.firewall.StrictHttpFirewall;@Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true)public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } @Bean public HttpFirewall allowUrlEncodedSlashHttpFirewall() { StrictHttpFirewall firewall = new StrictHttpFirewall(); firewall.setAllowUrlEncodedSlash(true); return firewall; } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .cors() //允许跨域访问 .and() .authorizeRequests() .antMatchers("/").authenticated() //配置那些url需要进行校验--所有请求都需要校验"/" .antMatchers("/public/**").permitAll() //那些请求不需要校验 .anyRequest().authenticated() //自定义校验类 .and() .addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS)//关闭session ; }}5、Action注解
在Controller类中添加
@CrossOrigin@RestController@PreAuthorize("hasAuthority('admin')") //配置角色,拥有该角色的用户方可访问@RequestMapping("/manage")postman测试http://localhost:7070/manage/userList,不可访问
public开头的可以访问
6、token令牌环,访问需校验的资源
public的Controller类添加
@PostMapping("/login") @ResponseBody public HashMap login( @RequestBody Account account) throws IOException {// Users u=manageService.getUserByUserNameAndPass(account.username,account.password); if(account.username.equals("admin")&&account.password.equals("123456")){// if(u!=null){ String jwt= JwtUtils.generateToken("admin","123456789abc");// String jwt= JwtUtils.generateToken(u.getRoleid(),u.getUsersid()); return new HashMap(){{ put("msg","ok"); put("token",jwt);// put("role",u.getRoleid()); put("role","admin"); }}; } else { //return new ResponseEntity(HttpStatus.UNAUTHORIZED); return new HashMap(){{ put("msg","error"); put("token","error"); }}; } } public static class Account{ public String username; public String password; } postman测试,随便输用户名密码
输入代码中的用户名密码
去JWT官网https://jwt.io/,页面下滑,将得到的token输入,得到
manage的Controller类中添加测试
@GetMapping("testSecurityResource") @ResponseBody public String testSecurityResource() throws Exception{ return "受保护的资源"; }用postman访问http://localhost:7070/manage/testSecurityResource,返回结果
7、service工具类
通用请求处理
package com.dreamteam.chdapp.controller.common;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Controller;/** * 通用请求处理 * @Author HeYunHui * @create 2020/11/14 15:38 */@Controllerpublic class CommonController { protected static final Logger log= LoggerFactory.getLogger(CommonController.class); /** * 字符串为空 * @param value * @return */ public static boolean isNullOrSpace(String value){ if(value==null){ return true; } else { if(value.equals("")){ return true; } else { return false; } } }}Service层
String getCurrentUserId();//从令牌环中获取useridString getCurrentRole();//从令牌环中获取角色idServiceImpl
/** * 获取当前登录用的的Id * @return */ @Override public String getCurrentUserId() { String userid= (String) SecurityContextHolder.getContext().getAuthentication() .getPrincipal(); if(CommonController.isNullOrSpace(userid)){ return null; } else { return userid; } } /** * 获取当前登录用户的角色 * @return */ @Override public String getCurrentRole() { String role=null; Collection authorities = (Collection) SecurityContextHolder.getContext().getAuthentication().getAuthorities(); for (GrantedAuthority authority : authorities) { role = authority.getAuthority(); } if(CommonController.isNullOrSpace(role)){ return null; } else{ return role; } } 修改manage的Controller类
@GetMapping("testSecurityResource") @ResponseBody public String testSecurityResource() throws Exception{ String userid=userInfoService.getCurrentUserId(); String role=userInfoService.getCurrentRole(); return "受保护的资源,当前用户的id是"+userid+"当前用户的角色是"+role; }用postman测试
这是前面自定义的
8、识别token信息
如果将下图中的角色换掉,将不能访问
9、自动更新令牌环
添加Controller类
package com.dreamteam.chdapp.controller;import com.dreamteam.chdapp.controller.common.CommonController;import com.dreamteam.chdapp.utils.JwtUtils;import org.springframework.security.access.prepost.PreAuthorize;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;import java.util.Collection;import java.util.HashMap;/** * 令牌环自动更新 * @Author HeYunHui * @create 2020/11/16 17:24 * @PreAuthorize("hasAuthority('admin')")//只允许有admin角色的用户访问 hasAnyAuthority([auth2,auth3]) */@CrossOrigin@RestController@PreAuthorize("hasAnyAuthority('admin','member')")@RequestMapping("/auth")public class AuthController { /** * 更新令牌环信息 * @param request * @return */ @GetMapping("refreshToken") @ResponseBody public HashMap refreshToken(HttpServletRequest request){ String role=null; Collection authorities = (Collection) SecurityContextHolder.getContext().getAuthentication().getAuthorities(); for (GrantedAuthority authority : authorities) { role = authority.getAuthority(); } // UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication() .getPrincipal(); String userid= (String)SecurityContextHolder.getContext().getAuthentication() .getPrincipal(); if(CommonController.isNullOrSpace(role)){ return new HashMap(){{ put("token","error"); }}; } else{ String jwt=""; //一小时 jwt= JwtUtils.generateToken(role,userid,60*60*1000); HashMap m=new HashMap<>(); m.put("token",jwt); return m; } } /** * 获取当前登录用户的角色 * @return */ @GetMapping("getRole") @ResponseBody public HashMap getRoleByToken(){ String role=""; String userid=""; Collection authorities = (Collection) SecurityContextHolder.getContext().getAuthentication().getAuthorities(); for (GrantedAuthority authority : authorities) { role = authority.getAuthority(); } if(CommonController.isNullOrSpace(role)){ return new HashMap(){{ put("role","error"); }}; } else{ HashMap m=new HashMap<>(); m.put("role",role); return m; } }} 用postman测试
10、使用数据库存储用户信息
(1)实体类
package com.dreamteam.chdapp.entity;import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.annotation.TableName;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import org.springframework.stereotype.Component;@Component@Data@AllArgsConstructor@NoArgsConstructor/** * 表名 */@TableName("users")public class Users { @TableId(type = IdType.AUTO) private String usrId; private String usrName; private String usrTel; private String usrPwd; private String usrType; }UserMapper
package com.dreamteam.chdapp.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.dreamteam.chdapp.entity.Users;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Param;import org.springframework.stereotype.Repository;import java.util.List;/** * @Author HeYunHui * @create 2020/11/11 21:50 */@Repository@Mapperpublic interface UserMapper extends BaseMapper { List getUsersByUsrNameAndPwd(@Param("usrName")String usrName, @Param("usrPwd") String usrPwd);} UsersMapper.xml
service
Users getUsersByUsrNameAndPwd(String usrName,String usrPwd);serviceImpl JWT获取用户名密码
@Override public Users getUsersByUsrNameAndPwd(String usrName, String usrPwd) { List ul=userMapper.getUsersByUsrNameAndPwd(usrName,usrPwd); if(ul.size()>0){ return ul.get(0); } return null; } Controller
@PostMapping("/login") @ResponseBody public HashMap login( @RequestBody Account account) throws IOException { Users u=userInfoService.getUsersByUsrNameAndPwd(account.username,account.password);// if(account.username.equals("admin")&&account.password.equals("123456")){ if(u!=null){// String jwt= JwtUtils.generateToken("admin","123456789abc"); String jwt= JwtUtils.generateToken(u.getUsrType(),u.getUsrId()); return new HashMap(){{ put("msg","ok"); put("token",jwt); put("role",u.getUsrType());// put("role","admin"); }}; } else { //return new ResponseEntity(HttpStatus.UNAUTHORIZED); return new HashMap(){{ put("msg","error"); put("token","error"); }}; } } public static class Account{ public String username; public String password; } 以上是"Springboot中怎么集成Spring Security JWT实现接口权限认证"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!
令牌
用户
角色
测试
配置
登录
信息
密码
用户名
篇文章
资源
保护
更新
接口
权限
认证
不同
内容
字段
工具
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
江苏根荣互联网科技
科技互联网公司装修
互联网下的科技发展
互联网科技的发展
安徽鑫晟辉互联网科技
壕鑫互联网络科技
伴你行互联网科技有限公司
居家互联网科技有限公司
联恩商钥互联网科技有限公司
现代科技和互联网有关系吗
温州喔噻互联网科技有限公司
央行互联网金融科技公司
互联网科技公司实习生
互联网与医疗科技
广东工业互联网大赛深圳学泰科技
银川新华互联网科技学校原画
互联网科技博主张洲
承德科技产业互联网平台
武汉亿视互联网科技有限公司
互联网 科技节活动 微视频大赛
互联网科技园
广州紫鲸互联网科技有限公司
国智互联网科技
广州善班互联网科技
互联网科技公司实习生
移动互联网科技公司
996高科技互联网公司
电子商务与互联网科技的关系
黑云互联网科技有限公司
山东大美朱楼互联网科技有限公司