当前位置: 首页 > news >正文

企业网站策划案例wordpress 做门户

企业网站策划案例,wordpress 做门户,24小时最新军事新闻,云服务器是什么java - SpringBoot3.x接入Security6.x实现JWT认证 文章目录 java - SpringBoot3.x接入Security6.x实现JWT认证一、引言二、环境三、Maven依赖四、认识JWT1. JWT组成 五、认识Security6.x1. 和旧版本的区别#xff08;Security5.7以前的版本#xff09;2. Security6.x的默认筛…java - SpringBoot3.x接入Security6.x实现JWT认证 文章目录 java - SpringBoot3.x接入Security6.x实现JWT认证一、引言二、环境三、Maven依赖四、认识JWT1. JWT组成 五、认识Security6.x1. 和旧版本的区别Security5.7以前的版本2. Security6.x的默认筛选器3. 注册SecurityFilterChain 六、基于OncePerRequestFilter自定义JWT认证筛选器1. 标记认证成功 七、遇到的问题1. 加入Security6后一直出现登录页2. 配置完匿名访问的URL后仍然执行自定的筛选器 八、完成JWT认证的主要代码1. JwtUtil2. JwtTokenFilter3. SecuritConfig 总结 一、引言 SpringBoot3.x的安全默认依赖Security6.xSecurity6.x于Security5.7以前的配置有了很大区别。我们将深入探讨这两个版本之间的差异以及它们如何影响现代Web应用的安全架构。特别是我们将重点分析JWTJSON Web Tokens过滤器的工作原理以及它是如何与匿名访问相结合为应用提供更加灵活的安全控制。 二、环境 JDK 17SpringBoot 3.2Security 6.3 三、Maven依赖 !-- Security安全 -- dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-security/artifactIdversion3.2.2/version /dependency !-- jwt接口认证 -- dependencygroupIdcom.auth0/groupIdartifactIdjava-jwt/artifactIdversion4.4.0/version /dependency 四、认识JWT JSON Web Token (JWT)是一个开放标准(RFC 7519)它定义了一种紧凑的、自包含的方式用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任因为它是数字签名的。 1. JWT组成 JSON Web Token由三部分组成它们之间用圆点(.)连接一个典型的JWT看起来是这个样子的 第一部分header典型的由两部分组成token的类型“JWT”和算法名称比如HMAC SHA256或者RSA等等然后用Base64对这个JSON编码就得到JWT的第一部分。第二部分payload它包含声明要求声明是关于实体(通常是用户)和其他数据的声明。第三部分签名是用于验证消息在传递过程中有没有被更改并且对于使用私钥签名的token它还可以验证JWT的发送方是否为它所称的发送方。 注意不要在JWT的payload或header中放置敏感信息除非它们是加密的。 {alg: RS256 }. { //存储自定义的用户信息,属性可以自定扩充login_name: admin,user_id: xxxxx,... }. [signature]请求header应该是这样的Authorization: Bearer 五、认识Security6.x 1. 和旧版本的区别Security5.7以前的版本 SpringBoot3中默认Security升级到了6.x写法上发生了很大的变化最显著的变化之一就是对WebSecurityConfigurerAdapter类的使用方式的改变。这个类在 Spring Security 中被广泛用于自定义安全配置。以下是主要的差异和写法上的变化 废弃WebSecurityConfigurerAdapter 在Security5.x 版本中WebSecurityConfigurerAdapter 是实现安全配置的常用方法。用户通过继承这个类并覆盖其方法来自定义安全配置。到了 Spring Security 6.xWebSecurityConfigurerAdapter 被标记为过时deprecated意味着它可能在未来的版本中被移除。这一变化是为了推动使用更现代的配置方法即使用组件式配置。 新版本建议使用组件式配置 在 Spring Security 6.x 中推荐使用组件式配置。这意味着你可以创建一个配置类该类不再需要继承 WebSecurityConfigurerAdapter。 你可以直接定义一个或多个 SecurityFilterChain Bean来配置安全规则。这种方式更加灵活并且与 Spring Framework 的整体风格更加一致。 2. Security6.x的默认筛选器 支持的所有筛选器在spring-security-config-6.2.1.jar包的org.springframework.security.config.annotation.web.builders.FilterOrderRegistration类的构造函数中定义并确定了执行顺序。 FilterOrderRegistration() {Step order new Step(INITIAL_ORDER, ORDER_STEP);put(DisableEncodeUrlFilter.class, order.next());put(ForceEagerSessionCreationFilter.class, order.next());put(ChannelProcessingFilter.class, order.next());order.next(); // gh-8105put(WebAsyncManagerIntegrationFilter.class, order.next());put(SecurityContextHolderFilter.class, order.next());put(SecurityContextPersistenceFilter.class, order.next());put(HeaderWriterFilter.class, order.next());put(CorsFilter.class, order.next());put(CsrfFilter.class, order.next());put(LogoutFilter.class, order.next());this.filterToOrder.put(org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter,order.next());this.filterToOrder.put(org.springframework.security.saml2.provider.service.web.Saml2WebSsoAuthenticationRequestFilter,order.next());put(X509AuthenticationFilter.class, order.next());put(AbstractPreAuthenticatedProcessingFilter.class, order.next());this.filterToOrder.put(org.springframework.security.cas.web.CasAuthenticationFilter, order.next());this.filterToOrder.put(org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter,order.next());this.filterToOrder.put(org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter,order.next());put(UsernamePasswordAuthenticationFilter.class, order.next());order.next(); // gh-8105put(DefaultLoginPageGeneratingFilter.class, order.next());put(DefaultLogoutPageGeneratingFilter.class, order.next());put(ConcurrentSessionFilter.class, order.next());put(DigestAuthenticationFilter.class, order.next());this.filterToOrder.put(org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter,order.next());put(BasicAuthenticationFilter.class, order.next());put(RequestCacheAwareFilter.class, order.next());put(SecurityContextHolderAwareRequestFilter.class, order.next());put(JaasApiIntegrationFilter.class, order.next());put(RememberMeAuthenticationFilter.class, order.next());put(AnonymousAuthenticationFilter.class, order.next());this.filterToOrder.put(org.springframework.security.oauth2.client.web.OAuth2AuthorizationCodeGrantFilter,order.next());put(SessionManagementFilter.class, order.next());put(ExceptionTranslationFilter.class, order.next());put(FilterSecurityInterceptor.class, order.next());put(AuthorizationFilter.class, order.next());put(SwitchUserFilter.class, order.next()); }3. 注册SecurityFilterChain private final String[] permitUrlArr new String[]{xxx};/*** 配置Spring Security安全链。*/Beanpublic SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {//初始化jwt过滤器并设置jwt公钥var jwtTokenFilter new JwtTokenFilter();//Security6.x关闭默认登录页httpSecurity.removeConfigurers(DefaultLoginPageConfigurer.class);logger.info(注册JWT认证SecurityFilterChain);var chain httpSecurity// 自定义权限拦截规则.authorizeHttpRequests((requests) - {//requests.anyRequest().permitAll(); //放行所有请求!!!//允许匿名访问requests//自定可匿名访问地址放到permitAllUrl中即可.requestMatchers(permitUrlArr).permitAll()//除上面声明的可匿名访问地址其它所有请求全部需要进行认证.anyRequest().authenticated();})// 禁用HTTP响应标头.headers(headersCustomizer - {headersCustomizer.cacheControl(cache - cache.disable()).frameOptions(options - options.sameOrigin());})//会话设为无状态,基于token所以不需要session.sessionManagement(session - session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))//添加自定义的JWT认证筛选器验证header中jwt有效性将插入到UsernamePasswordAuthenticationFilter之前 .addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class)//禁用表单登录.formLogin(formLogin - formLogin.disable())//禁用httpBasic登录.httpBasic(httpBasic - httpBasic.disable())//禁用rememberMe.rememberMe(rememberMe - rememberMe.disable())// 禁用CSRF因为不使用session.csrf(csrf - csrf.disable())//允许跨域请求.cors(Customizer.withDefaults()).build();return chain;}六、基于OncePerRequestFilter自定义JWT认证筛选器 使用OncePerRequestFilter的优点是能保证一个请求只过一次筛选器。可以在filter中实现对jwt的校验验证成功后需要对Security上下文进行标注。标记认证已经通过这点非常重要。如果认证完了不标注后边的过滤器还是认为未认证导致无权限失败。 1. 标记认证成功 //接入Spring Security6.x上下文标记为已认证状态 JwtAuthenticationToken jwtToken new JwtAuthenticationToken(null); jwtToken.setAuthenticated(true); //标记认证通过 SecurityContextHolder.getContext().setAuthentication(jwtToken);七、遇到的问题 1. 加入Security6后一直出现登录页 关闭默认登录页有两个设置可以完成可以删除DefaultLoginPageConfigurer类的加载或者调用formLogin()函数具体如下 Beanpublic SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {//Security6.x关闭默认登录页httpSecurity.removeConfigurers(DefaultLoginPageConfigurer.class);var chain httpSecurity//禁用表单登录.formLogin(formLogin - formLogin.disable()).build();return chain;}2. 配置完匿名访问的URL后仍然执行自定的筛选器 如果出现配置完匿名访问的URL后仍然执行自定的筛选器的问题。那原因就在于这个自定义筛选器上了 只通过requests.requestMatchers(…).permitAll(); 配置的匿名访问只能对默认筛选器起效如果想 对自定义删除器起效还需要构建WebSecurityCustomizer Bean对象基于匿名函数配置要匿名访问的地址。 一下是官网推荐的一个写法这里建议把两个位置配置的匿名访问地址使用一个公共数组进行管理这样 能保证两个位置配置的一致性。 /** 其它不需要认证的地址 */private final String[] permitUrlArr new String[]{/login,/error//静态资源,/static/**.ico,/static/**.js,/static/**.css//匹配springdoc,/doc.html,/webjars/**//匹配swagger路径默认, /swagger-ui.html, /swagger-ui/index.html, /v3/api-docs/**, /swagger-ui/**//监控检测, /actuator/**};Beanpublic WebSecurityCustomizer ignoringCustomize(){return (web) - web.ignoring().requestMatchers(permitUrlArr);}Beanpublic SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {//初始化jwt过滤器并设置jwt公钥var jwtTokenFilter new JwtTokenFilter();//Security6.x关闭默认登录页httpSecurity.removeConfigurers(DefaultLoginPageConfigurer.class);logger.info(注册JWT认证SecurityFilterChain);var chain httpSecurity// 自定义权限拦截规则.authorizeHttpRequests((requests) - {//允许匿名访问requests//自定可匿名访问地址放到permitAllUrl中即可.requestMatchers(permitUrlArr).permitAll()//除上面声明的可匿名访问地址其它所有请求全部需要进行认证.anyRequest().authenticated();}).build();return chain;} 八、完成JWT认证的主要代码 目前是对已有jwt的认证下发的jwt是基于RSA加密的内容需要使用公钥进行解密公钥一般配置在yml文件里。关键逻辑设计3部分SecuritConfig、JwtTokenFilter、JwtUtil。 1. JwtUtil 公钥是统一认证中心下发的目前写在yml中格式如下 jwt.keyValue: |-----BEGIN PUBLIC KEY-----xxxxxxxx-----END PUBLIC KEY-----JwtUtil类提供了验证方法出于性能考虑使用了单例模式验证器只需要实例化一次。 public class JwtUtil {private static JwtUtil instance new JwtUtil();private static JWTVerifier jwtVerifier;//配置文件中公钥的key值private static final String jwtPublicKeyConfigjwt.keyValue;private JwtUtil() {}/*** 基于固定配置文件的公钥初始化JWT验证器* return*/public static JwtUtil getInstance(){if (jwtVerifier null){String publicKey SpringUtil.getConfig(jwtPublicKeyConfig);return getInstance(publicKey);}return instance;}/*** 基于自定义公钥初始化JWT验证器* return*/public static JwtUtil getInstance(String publicKey) {if (jwtVerifier null){initVerifier(publicKey);}return instance;}// 静态的初始化函数private static synchronized void initVerifier(String publicKey) {if (jwtVerifier ! null)return;//替换为实际的Base64编码的RSA公钥字符串String publicKeyStr publicKey.replaceAll(\\s, ) // 去除所有空白字符包括换行符.replace(-----BEGINPUBLICKEY-----, ).replace(-----ENDPUBLICKEY-----, );// 将Base64编码的公钥字符串转换为PublicKey对象byte[] encodedPublicKey Base64.getDecoder().decode(publicKeyStr);X509EncodedKeySpec keySpec new X509EncodedKeySpec(encodedPublicKey);KeyFactory keyFactory null;try {keyFactory KeyFactory.getInstance(RSA);PublicKey pubKey keyFactory.generatePublic(keySpec);// 使用公钥创建一个Algorithm对象用于验证token的签名Algorithm algorithm Algorithm.RSA256((RSAPublicKey) pubKey, null);// 解析和验证tokenjwtVerifier JWT.require(algorithm).build();} catch (NoSuchAlgorithmException e) {throw new RuntimeException(e);} catch (InvalidKeySpecException e) {throw new RuntimeException(e);}catch (Exception e){throw new RuntimeException(e);}}/*** 解析和验证JWT token。** param token JWT token字符串* return 解码后的JWT对象* throws Exception 如果解析或验证失败抛出异常*/public DecodedJWT verifyToken(String token) {return jwtVerifier.verify(token);} }2. JwtTokenFilter 该类是校验的主要逻辑完成了jwt校验、已认证的标注。 public class JwtTokenFilter extends OncePerRequestFilter {private static Logger logger LoggerFactory.getLogger(JwtTokenFilter.class);private JwtUtil jwtUtil;//获取yml中的配置public String getConfig(String configKey) {var bean applicationContext.getBean(Environment.class);var val bean.getProperty(configKey);return val;}public JwtTokenFilter() throws ServletException {String jwtPubliKey getConfig(jwt.keyValue);initTokenFilter(jwtPubliKey);}public JwtTokenFilter(String jwtPubliKey) throws ServletException {initTokenFilter(jwtPubliKey);}Overrideprotected void initFilterBean() throws ServletException {}Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {var pass doTokenFilter(request,response,filterChain);if(!pass){return;}filterChain.doFilter(request,response);}/*** 初始化Token过滤器。* throws ServletException 如果在初始化过程中发生错误则抛出ServletException异常*/public void initTokenFilter(String publicKey) throws ServletException {logger.info(初始化TokenFilter);if(StringUtils.isBlank(publicKey)){throw new ServletException(jwtPublicKey is null);}logger.info(jwtPublicKey:{},publicKey);jwtUtil JwtUtil.getInstance(publicKey);logger.info(初始化JwtUtil完成);}protected Boolean doTokenFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {HttpServletRequest request (HttpServletRequest) servletRequest;HttpServletResponse response (HttpServletResponse) servletResponse;// 从请求头中获取tokenString token request.getHeader(Authorization);if(StringUtils.isBlank(token)){logger.info(jwt token为空,{} {},request.getMethod(),request.getRequestURI());// 验证失败返回401状态码response.sendError(HttpServletResponse.SC_UNAUTHORIZED, Invalid token);return false;}// 假设token是以Bearer 开头的需要去掉这个前缀if (token.startsWith(Bearer)) {token token.replaceAll(Bearer\s,);}logger.debug(request.getRequestURI());try {// 调用JwtUtils进行token验证DecodedJWT jwtDecode jwtUtil.verifyToken(token);//接入Spring Security6.x上下文标记为已认证状态JwtAuthenticationToken jwtToken new JwtAuthenticationToken(null);jwtToken.setAuthenticated(true);SecurityContextHolder.getContext().setAuthentication(jwtToken);//将登录信息写入spring security上下文} catch (JWTVerificationException ex) {logger.info(jwt token 非法);response.sendError(HttpServletResponse.SC_UNAUTHORIZED, 非法token:ex.getMessage());return false;} catch (Exception ex) {throw ex;}logger.debug(token验证通过);return true;}public static class JwtAuthenticationToken extends AbstractAuthenticationToken {private User userInfo;public JwtAuthenticationToken(User user) {super(null);this.userInfo user;}Overridepublic User getPrincipal() {return userInfo;}Overridepublic Object getCredentials() {throw new UnsupportedOperationException();}Overridepublic boolean implies(Subject subject) {return super.implies(subject);}}} 3. SecuritConfig 该类完成了对需要匿名访问的地址的配置还有自定义filter的注入。 Configuration public class SecurityConfig {private static final Logger logger LoggerFactory.getLogger(SecurityConfig.class);/** 其它不需要认证的地址 */private final String[] permitUrlArr new String[]{/login,/error//静态资源,/static/**.ico,/static/**.js,/static/**.css//匹配springdoc,/doc.html,/webjars/**//匹配swagger路径默认, /swagger-ui.html, /swagger-ui/index.html, /v3/api-docs/**, /swagger-ui/**//监控检测, /actuator/**};Beanpublic WebSecurityCustomizer ignoringCustomize(){return (web) - web.ignoring().requestMatchers(permitUrlArr);}Beanpublic SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {//初始化jwt过滤器并设置jwt公钥var jwtTokenFilter new JwtTokenFilter();//Security6.x关闭默认登录页httpSecurity.removeConfigurers(DefaultLoginPageConfigurer.class);logger.info(注册JWT认证SecurityFilterChain);var chain httpSecurity// 自定义权限拦截规则.authorizeHttpRequests((requests) - {//requests.anyRequest().permitAll(); //放行所有请求!!!//允许匿名访问requests//自定可匿名访问地址放到permitAllUrl中即可.requestMatchers(permitUrlArr).permitAll()//除上面声明的可匿名访问地址其它所有请求全部需要进行认证.anyRequest().authenticated();})// 禁用HTTP响应标头.headers(headersCustomizer - {headersCustomizer.cacheControl(cache - cache.disable()).frameOptions(options - options.sameOrigin());})//会话设为无状态,基于token所以不需要session.sessionManagement(session - session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))//添加自定义的JWT认证筛选器验证header中jwt有效性将插入到UsernamePasswordAuthenticationFilter之前 .addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class)//禁用表单登录.formLogin(formLogin - formLogin.disable())//禁用httpBasic登录.httpBasic(httpBasic - httpBasic.disable())//禁用rememberMe.rememberMe(rememberMe - rememberMe.disable())// 禁用CSRF因为不使用session.csrf(csrf - csrf.disable())//允许跨域请求.cors(Customizer.withDefaults()).build();return chain;}Beanpublic FilterRegistrationBean disableSpringBootErrorFilter(ErrorPageFilter filter){FilterRegistrationBean filterRegistrationBean new FilterRegistrationBean();filterRegistrationBean.setFilter(filter);filterRegistrationBean.setEnabled(false);return filterRegistrationBean;} } 总结 以上支持介绍了对于已有JWT统一认证系统的接入JWT解析和认证不涉及JWT生成和管理相关内容。 目前的用户信息是基于JWT动态解析的所以暂时没有基于AbstractAuthenticationToken在Security上下文中存放用户信息JwtAuthenticationToken已经支持自定义用户信息的存储只需要按需传入即可。基于Security上下文获取用户信息使用SecurityContextHolder.getContext().getAuthentication().getPrincipal();方法。
http://www.dnsts.com.cn/news/114545.html

相关文章:

  • nodejs的网站开发网站公司开发
  • 网站的设计费用海南省生态文明村建设促进会网站
  • 网上效果代码网站可以下载吗wordpress 分类页模板
  • 汕头如何建设网站设计wordpress和淘宝客程序
  • 南平做网站联通套餐
  • 天津个人网站制作郑州网站建设模板
  • 中国建设银行网站慢网站建设项目组织结构图
  • 淄博市建设工程质量协会网站西宁高端网站制作公司
  • 网站空间站如何进行网站维护
  • 烟台网站建设专业臻动传媒珠海斗门建设局网站
  • 公众号授权网站wordpress不跳转页面
  • 郑州做网站公司有哪些网站建设费用申请报告
  • 网站翻页零基础网站建设教学培训
  • 网站设计怎么做才好看wordpress 家园
  • 上海网站建设域名搜索推广
  • 安徽省住房和城乡建设厅网站上海市建筑业官网
  • 智库网站建设方案网盘做电子书下载网站
  • 全国建设注册中心网站网站长尾关键词优化
  • php网站开发专业背景徐州手机网站开发公司电话
  • 哪个网站可以做代码题目长治做网站哪里不错
  • 无锡网站建设价格深圳网站设计哪家快
  • 夏天做那些网站能致富广州微网站制作
  • dns网站建设wordpress安装教程 linux
  • 海南建设网网站软件外包学院
  • 网站首页 关键词wordpress微博登入获取头像
  • 开封府景点网站及移动端建设情况app制作平台排行
  • 电商平台介绍网站模板学校语言文字网站建设
  • 比较厉害的网站制作公司佛山北京网站建设
  • 建设部网站 测绘规章网站建设的可用性
  • 外贸建站与推广如何做人体内脉搏多少是标准的?wordpress 登陆 443