seo提高关键词,重庆百度搜索优化,网站建设与维护书籍推荐,做汤的网站有哪些一、思路 
前端调用后端可以使用jwt鉴权#xff1b;调用三方接口也可以使用jwt鉴权。对接多个三方则与每个third parth都约定一套token规则#xff0c;因为如果使用同一套token#xff0c;token串用可能造成权限越界问题#xff0c;且payload交叉业务不够清晰。下面的demo包…一、思路 
前端调用后端可以使用jwt鉴权调用三方接口也可以使用jwt鉴权。对接多个三方则与每个third parth都约定一套token规则因为如果使用同一套tokentoken串用可能造成权限越界问题且payload交叉业务不够清晰。下面的demo包含了两套jwt前端和一个三方openApi的 
1、token生成 
1签发给前端的token在本项目生成 
2签发给第三方的token由第三方根据双方约定的算法、密钥和payload通信信息自己生成 。不能调用本项目被调用方接口生成否则这个生成token的接口需要加白名单 会造成接口攻击和token泄露的安全问题。 
2、token校验 先判断是哪个业务的token再用各自约定的算法和业务规则校验。这里是根据url来判断的 不能只根据audience来判断如用前端的token访问open api接口从token解析出audience 是前端的再用前端的规则校验校验通过访问成功 
二、demo 1、pom与配置文件 
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdopenapi-ta/artifactIdgroupIdus.zoom.openapi/groupIdversion1.0-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdopenapi-ta-mas/artifactIdpropertiesmaven.compiler.source17/maven.compiler.sourcemaven.compiler.target17/maven.compiler.targetta.product.nameMas/ta.product.name/propertiesdependenciesdependencygroupIdus.zoom.openapi/groupIdartifactIdopenapi-ta-commons/artifactIdversion1.0-SNAPSHOT/version/dependencydependencygroupIdus.zoom.openapi.mas/groupIdartifactIdopen-api-mas-common/artifactIdversion1.0.1/version/dependencydependencygroupIdcom.github.pagehelper/groupIdartifactIdpagehelper/artifactIdversion5.1.8/version/dependencydependencygroupIdcom.fasterxml.jackson.datatype/groupIdartifactIdjackson-datatype-jsr310/artifactIdversion2.13.0/version/dependency/dependenciesbuildpluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-compiler-plugin/artifactIdversion3.8.1/versionconfigurationsource1.8/sourcetarget1.8/targetencodingUTF-8/encodingskiptrue/skipexecutablefalse/executable/configuration/pluginplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-surefire-plugin/artifactIdversion${surefire.version}/versionconfigurationsystemPropertyVariablesorg.uncommons.reportng.escape-outputfalse/org.uncommons.reportng.escape-outputspring.profiles.active${spring.profiles.active}/spring.profiles.activeta.product.name${ta.product.name}/ta.product.name/systemPropertyVariablesskipfalse/skiptestFailureIgnorefalse/testFailureIgnoreargLine-javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar--add-opens java.base/java.langALL-UNNAMED/argLinesuiteXmlFilessuiteXmlFile${project.basedir}/src/main/resources/suites/${spring.profiles.active}/AlertRuleAPIBvtSuite.xml/suiteXmlFile/suiteXmlFilespropertiesusedefaultlistenersfalse/usedefaultlisteners/properties/configuration/plugin/pluginsresourcesresourcedirectorysrc/main/resources/directoryfilteringtrue/filteringincludesinclude**/*.properties/includeinclude**/*.xml/includeincludeapplication.yml/includeincludeapplication-${spring.profiles.active}.yml/include/includes/resourceresourcedirectorysrc/main/java/directoryfilteringfalse/filtering/resource/resources/buildprofilesprofileiddev/idactivation!--default env--activeByDefaulttrue/activeByDefault/activationpropertiesspring.profiles.activedev/spring.profiles.active/properties/profileprofileidgo/idpropertiesspring.profiles.activego/spring.profiles.active/properties/profileprofileidaw1/idpropertiesspring.profiles.activeaw1/spring.profiles.active/properties/profileprofileidus02/idpropertiesspring.profiles.activeus02/spring.profiles.active/properties/profileprofileidus03/idpropertiesspring.profiles.activeus03/spring.profiles.active/properties/profileprofileidus04/idpropertiesspring.profiles.activeus04/spring.profiles.active/properties/profileprofileidus05/idpropertiesspring.profiles.activeus05/spring.profiles.active/properties/profileprofileidus06/idpropertiesspring.profiles.activeus06/spring.profiles.active/properties/profileprofileidus07/idpropertiesspring.profiles.activeus07/spring.profiles.active/properties/profileprofileidus01/idpropertiesspring.profiles.activeus01/spring.profiles.active/properties/profile/profiles/project 
server.port6666
server.servlet.context-path/jwtDemo 
2、启动类  
package com.demo.security;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.jmx.support.RegistrationPolicy;SpringBootApplication
//解决报错MXBean already registered with name org.apache.commons.pool2:typeGenericObjectPool,namepool
EnableMBeanExport(registration  RegistrationPolicy.IGNORE_EXISTING)
public class JWTApplication {public static void main(String[] args) {SpringApplication.run(JWTApplication.class, args);}
}3、全局配置 
1webMVC 
package com.demo.security.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;Configuration
public class WebMvcConfig implements WebMvcConfigurer {//设置跨域Beanpublic CorsFilter corsFilter() {UrlBasedCorsConfigurationSource source  new UrlBasedCorsConfigurationSource();CorsConfiguration config  new CorsConfiguration();config.setAllowCredentials(true);config.addAllowedOrigin(http://localhost:9528);config.addAllowedHeader(*);config.addAllowedMethod(*);source.registerCorsConfiguration(/**, config);return new CorsFilter(source);}
}2security 
package com.demo.security.config;import org.springframework.security.crypto.password.PasswordEncoder;public class MyPasswordEncoder implements PasswordEncoder {Overridepublic String encode(CharSequence charSequence) {return charSequence.toString();}Overridepublic boolean matches(CharSequence charSequence, String s) {return s.equals(charSequence.toString());}/*public DefaultPasswordEncoder() {this(-1);}*//*** param strength*            the log rounds to use, between 4 and 31*//*public DefaultPasswordEncoder(int strength) {}public String encode(CharSequence rawPassword) {return MD5.encrypt(rawPassword.toString());}public boolean matches(CharSequence rawPassword, String encodedPassword) {return encodedPassword.equals(MD5.encrypt(rawPassword.toString()));}*/
}package com.demo.security.config;import com.demo.security.filter.LoginFilter;
import com.demo.security.filter.TokenAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
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.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;EnableWebSecurity
Configuration
EnableGlobalMethodSecurity(prePostEnabled  true)
public class SecurityWebConfig {Autowiredprivate UserDetailsService userDetailsService;Beanpublic PasswordEncoder passwordEncoder() {return new MyPasswordEncoder();}Beanpublic AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {return authConfig.getAuthenticationManager();}Beanpublic SecurityFilterChain configure(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {http.csrf(AbstractHttpConfigurer::disable);http.headers(AbstractHttpConfigurer::disable);http.sessionManagement(sessionManagement - {sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS);});http.authorizeRequests().anyRequest().authenticated().and()//1、登陆、退出url均由前端拦截器控制这里注释掉。//1.1、前端拦截器中判断缓存token为空为空则post请求访问/login目的是进入LoginFilter获取token//1.2、不为空则带token访问接口如果AuthenticationFilter拦截token不合法则根据错误码跳转到登陆页面重复1.1的操作//.logout().logoutUrl(/logout).and()//2、身份认证filter访问系统除了白名单接口需要先登陆。post请求/login接口会进入这个拦截器// 校验用户名密码是否正确正确返回token给前端不正确则返回异常信息.addFilterBefore(new LoginFilter(authenticationManager), LoginFilter.class)//3、授权filerauthenticationManager为BasicAuthenticationFilter的必传参数。所有的接口都会走到这里// 根据用户id查询权限,连同身份一起塞入SecurityContextHolder全局变量后面获取用户信息则直接从SecurityContextHolder中get.addFilterBefore(new TokenAuthenticationFilter(authenticationManager,userDetailsService),TokenAuthenticationFilter.class);return http.build();}Beanpublic WebSecurityCustomizer webSecurityCustomizer() {return (web) - web.ignoring().requestMatchers(/param/**, /user-websocket-endpoint/**,/menu-websocket-endpoint/**);}
} 
4、security数据源 
1常量模拟数据库 
package com.demo.security.constant;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 模拟数据库查询数据假设有用户名/密码/角色/资源* admin/123/xtgly/user_manage、role_manage、menu_manage、school_manage* zs/123/userAdmin、roleAdmin/user_manage、role_manage、menu_manage* ls/123/schoolAdmin/school_manage*/
public class UserDBConstants {public static MapString, String getUsers() {MapString,String users  new HashMap();users.put(admin,123);users.put(zs,123);users.put(ls,123);return users;}public static MapString,ListString getUserRoles() {MapString,ListString userRoles  new HashMap();//adminListString adminRoles  new ArrayList();adminRoles.add(xtgly);userRoles.put(admin,adminRoles);//zsListString zsRoles  new ArrayList();zsRoles.add(userAdmin);zsRoles.add(roleAdmin);userRoles.put(zs,zsRoles);//lsListString lsRoles  new ArrayList();lsRoles.add(schoolAdmin);userRoles.put(ls,lsRoles);return userRoles;}public static MapString,ListString getUserPermissions() {MapString,ListString userPermissions  new HashMap();ListString lsPermissions  new ArrayList();//lslsPermissions.add(school_manage);userPermissions.put(ls,lsPermissions);//zsListString zsPermissions  new ArrayList();zsPermissions.add(user_manage);zsPermissions.add(role_manage);zsPermissions.add(menu_manage);userPermissions.put(zs,zsPermissions);//adminListString adminPermissions  new ArrayList();adminPermissions.add(user_manage);adminPermissions.add(role_manage);adminPermissions.add(menu_manage);adminPermissions.add(school_manage);userPermissions.put(admin,adminPermissions);return userPermissions;}
}2UserDetails 
package com.demo.security.dto;import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;
import java.util.List;
Data
public class UserDTO implements UserDetails {private Integer id;private String userName;private String userAccount;private ListString roles;private ListString menus;private String passWord;public UserDTO (Integer id,String userName,String userAccount,ListString roles,ListString menus,String passWord){this.id  id;this.userAccount  userAccount;this.userName  userName;this.roles  roles;this.menus  menus;this.passWord  passWord;}Overridepublic Collection? extends GrantedAuthority getAuthorities() {return null;}public ListString getMenus() {return menus;}public void setMenus(ListString menus) {this.menus  menus;}Overridepublic String getPassword() {return passWord;}Overridepublic String getUsername() {return this.userAccount;}Overridepublic boolean isAccountNonExpired() {return true;}Overridepublic boolean isAccountNonLocked() {return true;}Overridepublic boolean isCredentialsNonExpired() {return true;}Overridepublic boolean isEnabled() {return true;}
}3UserDetailService 
package com.demo.security.service;import com.demo.security.constant.UserDBConstants;
import com.demo.security.dto.UserDTO;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import java.util.List;
import java.util.Map;/*** 当什么也没有配置的时候账号和密码是由 Spring Security 定义生成的。* 而在实际项目中账号和密码都是从数据库中查询出来的。所以我们要通过自定义逻辑控制认证逻辑*/
Service(userDetailsService)
public class MyUserDetailsService implements UserDetailsService {Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//模拟数据库查询MapString, String userMap  UserDBConstants.getUsers();String dbPwd  userMap.get(username);if(StringUtils.isEmpty(dbPwd)){throw new UsernameNotFoundException(用户不存在);}MapString, ListString userRoles  UserDBConstants.getUserRoles();ListString roles  userRoles.get(username);MapString, ListString userMenus  UserDBConstants.getUserPermissions();ListString menus  userMenus.get(username);UserDTO userDTO  new UserDTO(null,null,username,roles,menus,dbPwd);return userDTO;}
}5、filter 
1前端登录 
package com.demo.security.filter;import com.demo.security.constant.UserDBConstants;
import com.demo.security.dto.ResponseMsg;
import com.demo.security.dto.UserDTO;
import com.demo.security.util.JwtUtil;
import com.google.gson.Gson;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;Slf4j
public class LoginFilter extends UsernamePasswordAuthenticationFilter {private AuthenticationManager authenticationManager;public LoginFilter(AuthenticationManager authenticationManager) {//super(new AntPathRequestMatcher(/login, POST));this.authenticationManager  authenticationManager;}/*** /login POST接口验证* param req* param res* return* throws AuthenticationException*/Overridepublic Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException {try {logger.info(进入LoginFilter);String userName  req.getParameter(userName);String passWord  req.getParameter(passWord);if (StringUtils.isEmpty(userName)) {throw new UsernameNotFoundException(请输入账号);}if (StringUtils.isEmpty(passWord)) {throw new UsernameNotFoundException(请输入密码);}//验证用户名密码是否正确MapString, String userMap  UserDBConstants.getUsers();if(!userMap.keySet().contains(userName)){throw new UsernameNotFoundException(用户不存在);}if(!passWord.equals(userMap.get(userName))){throw new UsernameNotFoundException(密码错误);}//这里权限返回空由后面的授权过滤器查询return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userName, passWord, new ArrayList()));} catch (UsernameNotFoundException e) {//返回错误信息res.setCharacterEncoding(UTF-8);res.setContentType(application/text;charsetutf-8);try {res.getWriter().write(e.getMessage());} catch (IOException e1) {e1.printStackTrace();}return null;}catch (Exception e){throw new RuntimeException(e);}}Overrideprotected void successfulAuthentication(HttpServletRequest request,HttpServletResponse res,jakarta.servlet.FilterChain chain,Authentication authResult)throws IOException{UserDTO userDTO  (UserDTO) authResult.getPrincipal();String jwtToken  JwtUtil.generateWebToken(userDTO);//返ResponseMsg resMsg  ResponseMsg.builder().code(200).data(jwtToken).build();res.setContentType(ContentType.TEXT_HTML.toString());Gson gson  new Gson();res.getWriter().write(gson.toJson(resMsg));}
}2token验证 
package com.demo.security.filter;import com.demo.security.util.JwtUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;import java.io.IOException;Slf4j
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {private UserDetailsService userDetailsService;public TokenAuthenticationFilter(AuthenticationManager authenticationManager, UserDetailsService userDetailsService) {super(authenticationManager);this.userDetailsService  userDetailsService;}Overrideprotected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {logger.info(登陆成功后访问,url{}req.getRequestURI());String token  req.getHeader(token);res.setCharacterEncoding(UTF-8);res.setContentType(application/text;charsetutf-8);//1、必填tokenif(StringUtils.isEmpty(token)){logger.info(登陆成功后访问,url{},token为空req.getRequestURI());res.getWriter().write(token为空);return;}//2、校验token是否合法合法则解析出userName//token可能是前端的也可能是open api的String userName  JwtUtil.getUserNameByToken(req,token);if(StringUtils.isEmpty(userName)){logger.info(登陆成功后访问,url{},token错误或失效req.getRequestURI());res.getWriter().write(token错误或者失效);return;}//3、根据userName获取user实体存入全局UserDetails currentUser  userDetailsService.loadUserByUsername(userName);UsernamePasswordAuthenticationToken authentication  new UsernamePasswordAuthenticationToken(currentUser,null,currentUser.getAuthorities());SecurityContextHolder.getContext().setAuthentication(authentication);chain.doFilter(req, res);}
}6、一些dto和常量 
package com.demo.security.dto;import lombok.Builder;
import lombok.Data;Data
Builder
public class ResponseMsg {private Object data;private Integer code;
}package com.demo.security.constant;import org.springframework.security.web.util.matcher.AntPathRequestMatcher;import java.util.List;public class UrlConstants {public static final String WEB_API_PRE  /v1/**;public static final String OPEN_API_PRE  /openApi/**;public static final ListAntPathRequestMatcher WEB_MATCHERS   List.of(new AntPathRequestMatcher(WEB_API_PRE));public static final ListAntPathRequestMatcher OPEN_API_MATCHERS List.of(new AntPathRequestMatcher(OPEN_API_PRE));
}7、JWTUtil 
package com.demo.security.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.demo.security.constant.UrlConstants;
import com.demo.security.dto.UserDTO;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;Slf4j
public class JwtUtil {//签发方private static final String APPLICATION_ISSUER  jwt_demo;//签发给private static final String TO_WEB  to_web;private static final String TO_OPEN_API  to_open_api;//密钥private static final String WEB_SECRET  web-secret;private static final String OPEN_API_SECRET  open-api-secret;//jwt过期事件public static final int EXPIRE_TIME  30 * 60 * 1000;/*** 生成给前端的签名* return 加密的token*/public static String generateWebToken(UserDTO userDTO) {Date date  new Date(System.currentTimeMillis()  EXPIRE_TIME);Algorithm algorithm  Algorithm.HMAC256(WEB_SECRET);// 附带username信息return JWT.create()//iss签发方.withIssuer(APPLICATION_ISSUER)//aud接收jwt的一方.withAudience(TO_WEB)//expjwt的过期时间这个过期时间必须要大于签发时间//.withExpiresAt()//其他自定义通信信息.withClaim(userName, userDTO.getUsername())//.withClaim(age,userDTO.getAge());.withExpiresAt(date).sign(algorithm);}/*** open api的签名生成* 此处是给单元测试用的调用方项目应该自己生成* return 加密的token*/public static String generateOpenApiToken(String userName) {Date date  new Date(System.currentTimeMillis()  EXPIRE_TIME);Algorithm algorithm  Algorithm.HMAC256(OPEN_API_SECRET);// 附带username信息return JWT.create()//iss签发方.withIssuer(APPLICATION_ISSUER)//aud接收jwt的一方.withAudience(TO_OPEN_API)//expjwt的过期时间这个过期时间必须要大于签发时间//.withExpiresAt()//其他自定义通信信息.withClaim(userName, userName)//.withClaim(age,age);.withExpiresAt(date).sign(algorithm);}public static String getUserNameByToken(HttpServletRequest req, String token) {DecodedJWT jwt  JWT.decode(token);//1、是否过期Date expireDate  jwt.getExpiresAt();if(expireDate.before(new Date())){log.error(token已过期);return null;}//2、签发方是否正确if(!APPLICATION_ISSUER.equals(jwt.getIssuer())){log.error(不是本项目签发的token);return null;}//3、是否合法String audience  jwt.getAudience().get(0);boolean check  preCheckToken(audience,token,req);if(!check){return null;}MapString, Claim claims  jwt.getClaims();String userName  claims.get(userName).asString();return userName;}/*** 根据url来判断是web还是open api更准确* 如果只根据audience来判断则web的token也可以访问open api** param audience* param token* param req* return*/private static boolean preCheckToken(String audience, String token, HttpServletRequest req) {if(TO_WEB.equals(audience)  urlMatches(req, UrlConstants.WEB_MATCHERS)){log.info(这是前端token);return verifyToken(WEB_SECRET,token);}else if(TO_OPEN_API.equals(audience)  urlMatches(req,UrlConstants.OPEN_API_MATCHERS)){log.info(这是open api token);return verifyToken(OPEN_API_SECRET,token);}log.error(token来源不合法);return false;}public static boolean urlMatches(HttpServletRequest request, ListAntPathRequestMatcher matchers) {OptionalAntPathRequestMatcher first  matchers.stream().filter(m - m.matches(request)).findFirst();return first.isPresent();}private static boolean verifyToken(String secret, String token) {Algorithm algorithm  Algorithm.HMAC256(secret);try{JWTVerifier verifier  JWT.require(algorithm).build();verifier.verify(token);return true;}catch (Exception e){log.error(token非法);return false;}}
} 
8、checkUtil 
package com.demo.security.check;import com.demo.security.dto.UserDTO;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;import java.awt.*;
import java.util.List;Component(menuAuthorizationCheck)
public class MenuAuthorizationCheck {public boolean hasMenuAuthorization(String menuCode) {UserDTO currentUser  (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();ListString menus  currentUser.getMenus();return menus.contains(menuCode);}/* *//*** open api是否有权限访问* param menuCode* return*//*public boolean hasOpenMenuAuthorization(String menuCode) {UserDTO currentUser  (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();ListString menus  currentUser.getMenus();return menus.contains(menuCode);}*/
}9、controller 
1前端业务接口 
package com.demo.security.controller;import com.demo.security.dto.ResponseMsg;
import com.demo.security.dto.UserDTO;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RequestMapping(/v1/user)
RestController
public class UserController {RequestMapping(/test)public String test(){return 这是user test;}RequestMapping(/getCurrentUser)public ResponseMsg getCurrentUser() {UserDTO currentUser  (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();System.out.println(当前用户为:currentUser);return ResponseMsg.builder().code(200).data(currentUser).build();}
} 
package com.demo.security.controller;import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RequestMapping(/v1/menu)
RestController
public class MenuManageController {PreAuthorize(menuAuthorizationCheck.hasMenuAuthorization(menu_manage))RequestMapping(/test)public String test(){return 这是菜单管理;}
}package com.demo.security.controller;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RequestMapping(/v1/school)
RestController
Slf4j
public class SchoolManageController {RequestMapping(/test)public String test(){log.info(这是学校管理controller);return 这是学校管理;}
}package com.demo.security.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RequestMapping(/v1/role)
RestController
public class RoleManageController {RequestMapping(/test)public String test(){return 这是角色管理;}
}2open api业务接口 
package com.demo.security.openapi;import com.demo.security.dto.ResponseMsg;
import com.demo.security.dto.UserDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RequestMapping(/openApi/user)
RestController
public class OpenUserController {RequestMapping(/test)public String test(){return 这是open api user test;}RequestMapping(/getCurrentUser)public ResponseMsg getCurrentUser() {UserDTO currentUser  (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();System.out.println(当前用户为:currentUser);return ResponseMsg.builder().code(200).data(currentUser).build();}
} package com.demo.security.openapi;import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RequestMapping(/openApi/menu)
RestController
public class OpenMenuController {PreAuthorize(menuAuthorizationCheck.hasMenuAuthorization(menu_manage))RequestMapping(/test)public String test(){return 这是open api菜单管理;}
}package com.demo.security.openapi;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RequestMapping(/openApi/school)
RestController
Slf4j
public class OpenSchoolController {RequestMapping(/test)public String test(){log.info(这是学校管理controller);return 这是open api学校管理;}
}测试验证 
1模拟前端调用 
① 登录访问 localhost:6666/jwtDemo/login?userNameadminpassWord123 使用返回的token调用业务接口 
② 访问 localhost:6666/jwtDemo/v1/user/test ③ 访问localhost:6666/jwtDemo/v1/user/getCurrentUser ④ 访问localhost:6666/jwtDemo/v1/menu/test ⑤ 访问 localhost:6666/jwtDemo/v1/school/test 2模拟openapi调用 
① 使用单元测试生成一个token 
package com.demo.jwt.openapi;import com.demo.security.JWTApplication;
import com.demo.security.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;SpringBootTest(classes  {JWTApplication.class}, webEnvironment  SpringBootTest.WebEnvironment.RANDOM_PORT)
RunWith(SpringRunner.class)
Slf4j
public class MyTest {/*** 模拟open api调用方生成token。* open api应该自己生成token双方约定好生成的算法、密钥和payload通信字段* 不能调用本项目被调用方接口生成否则对于生成token的接口需要加白名单会造成接口攻击和token泄露的安全问题**/Testpublic void  createOpenApiToken(){String userName  zs;String token  JwtUtil.generateOpenApiToken(userName);log.info(生成token{},token);}}使用这个token调用业务接口 
② 访问 localhost:6666/jwtDemo/openApi/user/getCurrentUser ③ 访问 localhost:6666/jwtDemo/openApi/school/test ④ 访问 localhost:6666/jwtDemo/openApi/menu/test 3前端使用openapi的token调用接口 
都报错 4openapi使用前端的token调用接口 
同样都报错  文章转载自: http://www.morning.lcbt.cn.gov.cn.lcbt.cn http://www.morning.pqchr.cn.gov.cn.pqchr.cn http://www.morning.qgghj.cn.gov.cn.qgghj.cn http://www.morning.nxbsq.cn.gov.cn.nxbsq.cn http://www.morning.bbrf.cn.gov.cn.bbrf.cn http://www.morning.wqpb.cn.gov.cn.wqpb.cn http://www.morning.ddgl.com.cn.gov.cn.ddgl.com.cn http://www.morning.wngpq.cn.gov.cn.wngpq.cn http://www.morning.qkzdc.cn.gov.cn.qkzdc.cn http://www.morning.wcczg.cn.gov.cn.wcczg.cn http://www.morning.dfygx.cn.gov.cn.dfygx.cn http://www.morning.xyrss.cn.gov.cn.xyrss.cn http://www.morning.jgnst.cn.gov.cn.jgnst.cn http://www.morning.ykmkz.cn.gov.cn.ykmkz.cn http://www.morning.mfqmk.cn.gov.cn.mfqmk.cn http://www.morning.rfmzs.cn.gov.cn.rfmzs.cn http://www.morning.qrksj.cn.gov.cn.qrksj.cn http://www.morning.rfgkf.cn.gov.cn.rfgkf.cn http://www.morning.tkchm.cn.gov.cn.tkchm.cn http://www.morning.qnbgh.cn.gov.cn.qnbgh.cn http://www.morning.bfwk.cn.gov.cn.bfwk.cn http://www.morning.wsyq.cn.gov.cn.wsyq.cn http://www.morning.bqwrn.cn.gov.cn.bqwrn.cn http://www.morning.zmnyj.cn.gov.cn.zmnyj.cn http://www.morning.rfjmy.cn.gov.cn.rfjmy.cn http://www.morning.bzfld.cn.gov.cn.bzfld.cn http://www.morning.rmtmk.cn.gov.cn.rmtmk.cn http://www.morning.zbkwj.cn.gov.cn.zbkwj.cn http://www.morning.gpcy.cn.gov.cn.gpcy.cn http://www.morning.yixingshengya.com.gov.cn.yixingshengya.com http://www.morning.qgjxy.cn.gov.cn.qgjxy.cn http://www.morning.gcrlb.cn.gov.cn.gcrlb.cn http://www.morning.qfmcm.cn.gov.cn.qfmcm.cn http://www.morning.mpszk.cn.gov.cn.mpszk.cn http://www.morning.tsdjj.cn.gov.cn.tsdjj.cn http://www.morning.gglhj.cn.gov.cn.gglhj.cn http://www.morning.nsrlb.cn.gov.cn.nsrlb.cn http://www.morning.gkfwp.cn.gov.cn.gkfwp.cn http://www.morning.tnnfy.cn.gov.cn.tnnfy.cn http://www.morning.kpxky.cn.gov.cn.kpxky.cn http://www.morning.rrcrs.cn.gov.cn.rrcrs.cn http://www.morning.pcgmw.cn.gov.cn.pcgmw.cn http://www.morning.dwzwm.cn.gov.cn.dwzwm.cn http://www.morning.yznsx.cn.gov.cn.yznsx.cn http://www.morning.ksggl.cn.gov.cn.ksggl.cn http://www.morning.nlglm.cn.gov.cn.nlglm.cn http://www.morning.ybgyz.cn.gov.cn.ybgyz.cn http://www.morning.xxwhz.cn.gov.cn.xxwhz.cn http://www.morning.npmx.cn.gov.cn.npmx.cn http://www.morning.hkchp.cn.gov.cn.hkchp.cn http://www.morning.kqyyq.cn.gov.cn.kqyyq.cn http://www.morning.ngmjn.cn.gov.cn.ngmjn.cn http://www.morning.rzsxb.cn.gov.cn.rzsxb.cn http://www.morning.yrngx.cn.gov.cn.yrngx.cn http://www.morning.ftwlay.cn.gov.cn.ftwlay.cn http://www.morning.jpgfx.cn.gov.cn.jpgfx.cn http://www.morning.gwwtm.cn.gov.cn.gwwtm.cn http://www.morning.nkyc.cn.gov.cn.nkyc.cn http://www.morning.shsh1688.com.gov.cn.shsh1688.com http://www.morning.lgqdl.cn.gov.cn.lgqdl.cn http://www.morning.hyjpl.cn.gov.cn.hyjpl.cn http://www.morning.grxyx.cn.gov.cn.grxyx.cn http://www.morning.dxpqd.cn.gov.cn.dxpqd.cn http://www.morning.jzccn.cn.gov.cn.jzccn.cn http://www.morning.nrzkg.cn.gov.cn.nrzkg.cn http://www.morning.zympx.cn.gov.cn.zympx.cn http://www.morning.fpkdd.cn.gov.cn.fpkdd.cn http://www.morning.tmcmj.cn.gov.cn.tmcmj.cn http://www.morning.fqhbt.cn.gov.cn.fqhbt.cn http://www.morning.kjrp.cn.gov.cn.kjrp.cn http://www.morning.kndst.cn.gov.cn.kndst.cn http://www.morning.gbfzy.cn.gov.cn.gbfzy.cn http://www.morning.ygxf.cn.gov.cn.ygxf.cn http://www.morning.hngmg.cn.gov.cn.hngmg.cn http://www.morning.ygkk.cn.gov.cn.ygkk.cn http://www.morning.sqnrz.cn.gov.cn.sqnrz.cn http://www.morning.wglhz.cn.gov.cn.wglhz.cn http://www.morning.zcfsq.cn.gov.cn.zcfsq.cn http://www.morning.wbfg.cn.gov.cn.wbfg.cn http://www.morning.twhgn.cn.gov.cn.twhgn.cn