一、使用security默认登录接口登录成功、生成token、返回前段

项目的结构如下:

1.引入jar包

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- alibaba json --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.41</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- JWT --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.7.0</version></dependency><!--swagger相关-start--><dependency><groupId>io.swagger</groupId><artifactId>swagger-annotations</artifactId><version>1.5.19</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency><!--swagger相关-end-->

测试的用户实体

@Data
public class User {private String id;private String name;private String password;private boolean dev;private boolean channel;public User() {}public User(String id, String name, String password) {this.id = id;this.name = name;this.password = password;}
}

Jwt生成token,拦截和验证token的合法性

package com.example.security.Jwt;import com.example.security.token.TokenManager;
import com.example.security.util.SpringContextUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;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.List;
import java.util.stream.Collectors;/*** Created by zhicheng.zhao on 2020/9/4.*/
public class JwtAuthFilter extends BasicAuthenticationFilter {private TokenManager tokenManager;public JwtAuthFilter(AuthenticationManager authenticationManager, TokenManager tokenManager) {super(authenticationManager);this.tokenManager = tokenManager;}/*** 过滤器** @param request* @param response* @param chain* @throws IOException* @throws ServletException*/protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {// 设置请求权限response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));response.setHeader("Access-Control-Allow-Credentials", "true");response.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS,DELETE,PATCH");response.setHeader("Access-Control-Allow-Headers", "tokenId,userType,token,Origin,X-Requested-With,Content-Type,Accept,appKey,hszCookie");response.setCharacterEncoding("UTF-8");response.setContentType("application/json,charset=utf-8");String url = request.getRequestURI();// 鉴权判断:本地环境模拟管理员权限,其他环境需要根据url鉴权 zzcSystem.out.println(SpringContextUtil.getProp("authVerify"));if (SpringContextUtil.getProp("authVerify")==null?false:SpringContextUtil.getProp("authVerify").equalsIgnoreCase("false1")) {// 本地环境,存储用户认证信息String tokenTmp = tokenManager.createTokenAll("test");UsernamePasswordAuthenticationToken authenticationToken = getAuthentication(tokenTmp);SecurityContextHolder.getContext().setAuthentication(authenticationToken);chain.doFilter(request, response);return;} else if (urlFilter(url)) {chain.doFilter(request, response);return;}// 过滤token为空String token = request.getHeader("token");if (token == null || "".equals(token)) {response.setHeader("Content-Type", "application/json");response.getWriter().print("token为空!");return;}// 从token获取用户认证信息UsernamePasswordAuthenticationToken authenticationToken = getAuthentication(token);if (authenticationToken == null) {response.setHeader("Content-Type", "application/json");response.getWriter().print("token信息错误!");return;}// 存储用户认证信息SecurityContextHolder.getContext().setAuthentication(authenticationToken);chain.doFilter(request, response);}/*** 不需要token的地址:* 用户名登录/手机登录/第三方登录/微信登录* 注册* 登录前(authFree)** @param url* @return*/private boolean urlFilter(String url) {return url.contains("/login")|| url.contains("Login")|| url.contains("/regist")|| url.contains("Regist")|| url.contains("/authFree");}/*** 从token获取用户认证信息** @param token* @return*/private UsernamePasswordAuthenticationToken getAuthentication(String token) {try {Claims claims = Jwts.parser().setSigningKey("JwtSecret").parseClaimsJws(token).getBody();String user = claims.getSubject();String role = claims.get("roles").toString();List<SimpleGrantedAuthority> userRolesByToken = Arrays.stream(role.split(",")).map(SimpleGrantedAuthority::new).collect(Collectors.toList());if (!user.isEmpty()) {return new UsernamePasswordAuthenticationToken(user, null, userRolesByToken);}} catch (Exception e) {logger.info(e.getMessage());}return null;}
}

查询数据库用户信息的服务

@Service
public class UserService {/*** @Description: 这里应该写的是调用Dao层,根据主键查询出用户,由于我没有配置直接返回用户,注意,密码是经过加密的* @author: YunZhao.Wang* @date: 2020/10/21 10:26* @version:*/public User getUser(String name){User user =  new User("1","test", new BCryptPasswordEncoder().encode("123")) ;if (user.getName().equals(name)){return user;}else {return new User();}}
}

实现security底层查询用户信息的接口,让security的底层查询数据的用户信息

@Service
public class CustomUserService implements UserDetailsService {@Autowiredprivate UserService userService;@Overridepublic UserDetails loadUserByUsername(String account) throws UsernameNotFoundException {//账号信息com.example.security.model.User accountInfo = userService.getUser(account);if (accountInfo == null)throw new UsernameNotFoundException("Account[" + account + "]not found");List<SimpleGrantedAuthority> authorities = new ArrayList<>();//对应的权限添加authorities.add(new SimpleGrantedAuthority("ROLE_USER"));return new User(accountInfo.getName(), accountInfo.getPassword(), authorities);}
}

集成 WebSecurityConfigurerAdapter,重写configure接口

package com.example.security.security;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.security.Jwt.JwtAuthFilter;
import com.example.security.model.User;
import com.example.security.token.TokenManager;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.builders.WebSecurity;
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.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @program: security进行登录* @description: Security* @author: YunZhao.Wang* @create: 2020-10-21 10:29**/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate CustomUserService customUserService;@Autowiredprivate TokenManager tokenManager;@Overridepublic void configure(HttpSecurity http) throws Exception {//关闭csrf保护http.csrf().disable();// 无状态http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);// 添加filterhttp.addFilterBefore(new JwtAuthFilter(authenticationManager(), tokenManager), UsernamePasswordAuthenticationFilter.class);//登陆http.formLogin().successHandler(loginSuccessHandler()).failureHandler(loginFailureHandler()).permitAll();// 无拦截http.authorizeRequests().anyRequest().permitAll();//退出http.logout().logoutSuccessUrl("/login").permitAll();}@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(customUserService).passwordEncoder(passwordEncoder());}/*** 密码加密** @return*/@Beanpublic BCryptPasswordEncoder passwordEncoder() {//密码加密return new BCryptPasswordEncoder(4);}/*** 登录成功** @return*/@BeanAuthenticationSuccessHandler loginSuccessHandler() {return new AuthenticationSuccessHandler() {@Autowiredprivate UserService userService;@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth) throws IOException, ServletException {String account = request.getParameter("username");String token = tokenManager.createTokenBusiness(account);response.setCharacterEncoding("UTF-8");response.setContentType("application/json,charset=utf-8");response.getWriter().print("登录成功!token:" + token);}};}/*** 登录失败** @return*/@BeanAuthenticationFailureHandler loginFailureHandler() {return new AuthenticationFailureHandler() {@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {//                Result result = new Result(ExceptionEnum.LOGIN_ERROR.getErrorCode(), ExceptionEnum.LOGIN_ERROR.getErrorMsg());
//                response.setHeader("Content-Type", "application/json");response.getWriter().print("登录失败!");}};}/*** 静态资源配置** @param web* @throws Exception*/@Overridepublic void configure(WebSecurity web) {web.ignoring().antMatchers("/swagger-ui.html").antMatchers("/webjars/**").antMatchers("/v2/**").antMatchers("/swagger-resources/**");}
}

token工具类

package com.example.security.token;import com.example.security.model.User;
import com.example.security.security.UserService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** Created by zhangnianzhong on 2019/8/27.*/
@Component("tokenManager")
public class TokenManager {private static Logger logger = LoggerFactory.getLogger(TokenManager.class);@Autowiredprivate UserService accountService;public String createToken(String userId) {long expire_time = 1000 * 60 * 60 * 12;String token = Jwts.builder().setSubject(userId).setExpiration(new Date(System.currentTimeMillis() + expire_time)).signWith(SignatureAlgorithm.HS512, "JwtSecret").compact();return token;}/*** B端用户权限** @param userName* @return*/public String createTokenBusiness(String userName) {long expireTime = 1000 * 60 * 60 * 12; //过期时间为12小时User account = accountService.getUser(userName);List<String> list= new ArrayList<>();//因为用户没有设置管理权限,故默认都是ROLE_00权限,在接口加注解包含00,即是管理员权限的接口if (account.isDev()) {list.add("ROLE_01");}if (account.isChannel()) {list.add("ROLE_02");}if (!account.isChannel() && !account.isDev()) {list.add("ROLE_00");}String token = Jwts.builder().signWith(SignatureAlgorithm.HS512, "JwtSecret").claim("roles", String.join(",", list)).setSubject(userName).setExpiration(new Date(System.currentTimeMillis() + expireTime)).compact();return token;}/*** 模拟所有用户权限** @param userName* @return*/public String createTokenAll(String userName) {long expireTime = 1000 * 60 * 60 * 12;List<String> list= new ArrayList<>();list.add("ROLE_00");list.add("ROLE_01");list.add("ROLE_02");list.add("ROLE_10");list.add("ROLE_11");String token = Jwts.builder().signWith(SignatureAlgorithm.HS512,"JwtSecret").claim("roles", String.join(",", list)).setSubject(userName).setExpiration(new Date(System.currentTimeMillis() + expireTime)).compact();return token;}public String getRoles(String token) {try {Claims claims = Jwts.parser().setSigningKey("JwtSecret").parseClaimsJws(token).getBody();String roles = claims.get("roles").toString();return roles;} catch (Exception e) {logger.info(e.getMessage());}return null;}
}

获取当前的环境

@Component
public class SpringContextUtil implements ApplicationContextAware {private static ApplicationContext context = null;@Overridepublic void setApplicationContext(ApplicationContext applicationContext)throws BeansException {this.context = applicationContext;}// 传入线程中public static <T> T getBean(String beanName) {return (T) context.getBean(beanName);}// 国际化使用public static String getMessage(String key) {return context.getMessage(key, null, Locale.getDefault());}/// 获取当前环境public static String getActiveProfile() {return context.getEnvironment().getActiveProfiles()[0];}/// 获取当前环境public static String getProp(String prop) {return context.getEnvironment().getProperty(prop);}
}

swagger配置文件

@Configuration
@EnableSwagger2
//@Profile({"test","dev","prod"})
public class Swagger2 {@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("com.example.security.provider.controller")).paths(PathSelectors.any()).build().globalOperationParameters(setHeaderToken());}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("权限版本二-V1-APIs").description("").termsOfServiceUrl("").version("1.0").build();}// 添加token验证private List<Parameter> setHeaderToken() {ParameterBuilder tokenPar = new ParameterBuilder();List<Parameter> pars = new ArrayList<>();tokenPar.name("token").description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();pars.add(tokenPar.build());return pars;}
}

controller接口

@RestController
@Api(tags = {"用户管理"},description = "带接口鉴权的用户管理接口")
public class UserController {@PreAuthorize("hasAnyRole('00')")@GetMapping("getUser")@ApiOperation(value = "获取用户",notes = "获取用户")public User getUser(){return new User("3","ceshi","789");}
}

配置文件

server.port= 10010

之后我们可以使用postman进行测试,使用security自带的login接口,是psot请求

二、请求头带上token访问后端接口

之后我们使用返回的token访问获取用户的接口,打开swagger接口(http://localhost:10010/swagger-ui.html),

因为默认都是00的权限,登录我是写死的,返回的一定也是00的权限,为了测试,我们修改获取用户借口中的注解参数

再次访问,出现403错误,无权限访问,现在的token是非00生成的,所以只能权限为非00的访问,这个返回结果我没有定义全局的异常处理,大家可以对异常进行再一次的封装

实例的连接

链接: https://pan.baidu.com/s/10ibBRxHEWakoENNBsvRALA 提取码: cd7u 复制这段内容后打开百度网盘手机App,操作更方便哦

SpringBoot使用security和jwt进行鉴权设计相关推荐

  1. Spring security+jwt服务鉴权完整代码

    将代码下载到本地, 直接以包的形式添加到项目中就可以实现鉴权功能了. <!-- spring-security 和 jwt start --><dependency><g ...

  2. springboot做代理分发服务+代理鉴权

    还原背景 大家都做过b-s架构的应用,也就是基于浏览器的软件应用.现在呢有个场景就是FE端也就是前端工程是前后端分离的,采用主流的前端框架VUE编写.服务端采用的是springBoot架构. 现在有另 ...

  3. 还在直接用 JWT 做鉴权?JJWT 真香

    点击关注公众号,回复"1024"获取2TB学习资源! jwt是什么? JWTs是JSON对象的编码表示.JSON对象由零或多个名称/值对组成,其中名称为字符串,值为任意JSON值. ...

  4. 还在直接用JWT做鉴权?JJWT真香

    欢迎关注方志朋的博客,回复"666"获面试宝典 jwt是什么? JWTs是JSON对象的编码表示.JSON对象由零或多个名称/值对组成,其中名称为字符串,值为任意JSON值.JWT ...

  5. 【Gorho】springboot整合Shiro+jwt 前后端分离 超级详细的shiro+jwt鉴权过程

    shiro+jwt+springboot 说在前面 简介 项目环境(pom.xml) 项目结构(各种包和类) 鉴权流程 具体代码 配置Shiro 配置JWTUtils 定义JwtFilter 定义Jw ...

  6. 请求令牌 接口_时序图说明JWT用户认证及接口鉴权的细节

    JWT用户认证及接口鉴权的细节以及原理 一.回顾JWT的授权及鉴权流程 在笔者的上一篇文章中,已经为大家介绍了JWT以及其结构及使用方法.其授权与鉴权流程浓缩为以下两句话: 授权:使用可信用户信息(用 ...

  7. SpringBoot 2 + Spring Security 5 + JWT 的单页应用 Restful 解决方案

    此前我已经写过一篇类似的教程,但那时候使用了投机的方法,没有尊重 Spring Security 的官方设计,自己并不感到满意.这段时间比较空,故重新研究了一遍. 特性 使用 JWT 进行鉴权,支持 ...

  8. 接口使用jwt返回token_Java中使用JWT生成Token进行接口鉴权实现方法

    先介绍下利用JWT进行鉴权的思路: 1.用户发起登录请求. 2.服务端创建一个加密后的JWT信息,作为Token返回. 3.在后续请求中JWT信息作为请求头,发给服务端. 4.服务端拿到JWT之后进行 ...

  9. java 接口鉴权_安全|Java中使用JWT生成Token进行接口鉴权实现

    先介绍下利用JWT进行鉴权的思路: 1.用户发起登录请求. 2.服务端创建一个加密后的JWT信息,作为Token返回. 3.在后续请求中JWT信息作为请求头,发给服务端. 4.服务端拿到JWT之后进行 ...

最新文章

  1. 机器学习面试:这25个实用又有深度的问题
  2. 深海中的STL—nth_element
  3. C#学习基本概念之属性使用
  4. Shell-06 函数
  5. java 文件监听器_java7 文件监听器
  6. 删除的时候提示“该项目不在C:\User\桌面 中
  7. 2016noip蚯蚓《单调队列》
  8. 国家自然科学基金申请书写作攻略
  9. ppap文件过程流程图制作_PPAP提交范本---过程流程图
  10. 神经+符号知识推理论文浅读4篇
  11. OpenGL及GLUT---------------函数整理
  12. html5 拖拽 编辑 插件,超给力 Vue.js 可视化H5拖拽编辑器Quark-H5
  13. 电脑重装系统Win10关闭网速限制的方法
  14. 漫画制作软件Comic Strip Factory Mac
  15. 【Spikingjelly】SNN框架教程的代码解读_4
  16. 建立自己的机器人手臂-组装
  17. Postman接口测试自动化介绍
  18. 实验二 Java基础语法练习-基本数据类型、运算符与表达式、选择结构
  19. 无线衰落信道的分类方式和选择性衰落条件
  20. 国庆节我们用代码画个国旗

热门文章

  1. linux od命令详解
  2. epoll与tornado 简介
  3. Shodan API使用指南 撒旦网
  4. 使用TDI与WinSock进行客户端服务器编程
  5. VC界面库BCGControlBar和Xtreme Toolkit详细对比评测
  6. ZVM – 记VMP保护代码还原工程
  7. C++ 程序不一定从 main 处开始执行
  8. 利用FreeNas创建iSCSI块级存储
  9. 怎么看待传菜机器人_太科幻了!这家顺德菜餐厅里全是机器人,炒菜送菜样样行...
  10. handler post r 同一个线程的疑惑