Springboot1.5.9升级2.7.x 梳理要点 Springboot+jwt+SpringSecurity+Cors

前言:springboot2.x以下的版本已经很老了,随着漏洞频发和不支持新特性迟早是要弃用的,况且现在3.0已经出了,升级到2.7以上是势在必行。

目录

 开始升级:

SpringSecurity 


引用github: 1273700934/spring-boot-spring-security-jwt-authentication: Spring Boot + Security: Token Based Authentication example with JWT, Authorization, Spring Data & MySQL (github.com)

文章解决的痛点,升级过程中遇到的SpringSecurity验证问题,接口访问问题,跨域问题Cors,kafka组件升级等;

 开始升级:

首先,升级springboot项目POM.xml文件:<spring.version>2.7.10</spring.version>,等待maven升级完成。

贴一下我的pom.xml:

 <dependencies>
     
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>       
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

问题如果你项目使用https+http,那么你将会得到报错:

EmbeddedServletContainerFactory 在老版本2.X以下已经废弃,使用新的代码实现https+http:
 @Bean
    public TomcatContextCustomizer tomcatContextCustomizer() {
        return context -> context.addServletContainerInitializer(new WsSci(), null);
    }

    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
        connector.setPort(port);
        tomcat.addAdditionalTomcatConnectors(connector);
        return tomcat;
    }

SpringSecurity 

老版本 WebSecurityConfigurerAdapter 已过期,新的配置过滤验证使用@Bean实现,

示例代码:

 /**
     * 授权
     * @param
     * @return
     * @throws Exception
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        // 认证失败处理类
        httpSecurity.cors().and().csrf().disable()
                .exceptionHandling().authenticationEntryPoint(customAuthenticationEntryPoint).and()
                // 基于 token,不需要 session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests().antMatchers("/login/**","/download/**","/websocket/**","/agent/**","/rest/**").permitAll()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated()
                ;
        httpSecurity.authenticationProvider(authenticationProvider());
        httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter,UsernamePasswordAuthenticationFilter.class);

        httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(customLogoutSuccessHandler);

        return httpSecurity.build();
    }

详讲SpringSecurity配置,其中结构图为(请理解):

 SpringSecurity 目录结构

 1.   实现LoginUser

package com.duplicall.imam.server.app.config.security.bean;

import com.duplicall.imam.model.User;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * @Description LoginUser
 * @Author ding
 * @Date 2021/2/7 16:09
 * @Version 1.0
 */
public class LoginUser implements UserDetails {

    /**
     * 用户唯一标识
     */
    private String token;

    /**
     * 登录时间
     */
    private Long loginTime;

    /**
     * 过期时间
     */
    private Long expireTime;

    private User user;

    /**
     * 角色列表
     */
    private Set<String> roles;
    /**
     * 权限列表
     */
    private Set<String> permissions;

    public Set<String> getRoles() {
        return roles;
    }

    public void setRoles(Set<String> roles) {
        this.roles = roles;
    }

    public LoginUser(User user, Set<String> roles,Set<String> permissions) {
        this.user = user;
        this.roles = roles;
        this.permissions = permissions;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        if (CollectionUtils.isNotEmpty(roles)) {
            List<SimpleGrantedAuthority> simpleGrantedAuthorities = Lists.newArrayList();
            for (String permission : roles) {
                simpleGrantedAuthorities.add(new SimpleGrantedAuthority("ROLE_" + permission));
            }
            return simpleGrantedAuthorities;
        }
        return null;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getLoginId();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public Long getLoginTime() {
        return loginTime;
    }

    public void setLoginTime(Long loginTime) {
        this.loginTime = loginTime;
    }

    public Long getExpireTime() {
        return expireTime;
    }

    public void setExpireTime(Long expireTime) {
        this.expireTime = expireTime;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Set<String> getPermissions() {
        return permissions;
    }

    public void setPermissions(Set<String> permissions) {
        this.permissions = permissions;
    }
}

2. 实现UserTokenService,注意我这里使用了缓存存放用户数据

package com.duplicall.imam.server.app.config.security.auth;

import com.duplicall.imam.constants.Constants;
import com.duplicall.imam.server.app.config.security.bean.LoginUser;
import com.duplicall.imam.server.app.service.auth.IUserAuth;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Description UserTokenService
 * @Author Sean
 * @Date 2021/2/7 16:01
 * @Version 1.0
 */
@Component
public class UserTokenService {
    private final Logger logger = LoggerFactory.getLogger(UserTokenService.class);

    protected static final long MILLIS_SECOND = 1000;

    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;

    private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;

    /**
     * 用户登录缓存类
     */
    @Autowired
    private IUserAuth ehcacheService;

    @Autowired
    private AuthenticationManager authenticationManager;
    // 令牌自定义标识
    @Value("${token.header}")
    private String header;

    // 令牌秘钥
    @Value("${token.secret}")
    private String secret;

    // 令牌有效期(默认30分钟)
    @Value("${token.expireTime:30}")
    private int expireTime;

    public LoginUser getLoginUser(HttpServletRequest request) {
        String token = getToken(request);
        logger.debug(" request token [{}]",token);
        if (StringUtils.isNotEmpty(token)) {
           try {
               Claims claims = parseToken(token);
               String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
               String userKey = getTokenKey(uuid);
               logger.debug("start get token key [{}] user key [{}] info from cache",token,userKey);
               return (LoginUser) ehcacheService.getCacheObject(userKey);
           }catch (Exception e){
               logger.error("get login user info by token [{}] error as [{}]",token,e.getMessage(),e);
           }
        }
        return null;
    }

    public String login(String userName, String passWord) {
        if (StringUtils.isNotEmpty(userName) && StringUtils.isNotEmpty(passWord)) {
            Authentication authenticate;
            try {
                logger.info("user [{}] login ", userName);
                authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userName, passWord));
            } catch (Exception e) {
                throw e;
            }
            LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
            return createToken(loginUser);
        } else {
            throw new BadCredentialsException("User Bad Credentials");
        }
    }

    /**
     * 创建令牌
     *
     * @param loginUser 用户信息
     * @return 令牌
     */
    public String createToken(LoginUser loginUser) {
        String token = UUID.randomUUID().toString();
        loginUser.setToken(token);
        refreshToken(loginUser);
        Map<String, Object> claims = new HashMap<>(1);
        claims.put(Constants.LOGIN_USER_KEY, token);
        return createToken(claims);
    }


    /**
     * 刷新令牌有效期
     *
     * @param loginUser 登录信息
     */
    public void refreshToken(LoginUser loginUser) {
        loginUser.setLoginTime(System.currentTimeMillis());
        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
        // 根据uuid将loginUser缓存
        String userKey = getTokenKey(loginUser.getToken());
        ehcacheService.setObject(userKey, loginUser);
    }

    /**
     * 从数据声明生成令牌
     *
     * @param claims 数据声明
     * @return 令牌
     */
    private String createToken(Map<String, Object> claims) {
        return Jwts.builder()
                .setClaims(claims)
                .signWith(SignatureAlgorithm.HS512, secret).compact();
    }


    /**
     * 验证令牌有效期,相差不足20分钟,自动刷新缓存
     *
     * @param loginUser
     */
    public void verifyToken(LoginUser loginUser) {
        long expireTime = loginUser.getExpireTime();
        long currentTime = System.currentTimeMillis();
        if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
            refreshToken(loginUser);
        }
    }



    /**
     * 删除用户身份信息
     */
    public void delLoginUser(String token) {
        if (StringUtils.isNotEmpty(token)) {
            String userKey = getTokenKey(token);
            ehcacheService.deleteCache(userKey);
        }
    }


    /**
     * 获取请求token
     *
     * @param request
     * @return token
     */
    private String getToken(HttpServletRequest request) {
        String token = request.getHeader(header);
        if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) {
            token = token.replace(Constants.TOKEN_PREFIX, "");
        }
        return token;
    }

    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    private Claims parseToken(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }

    private String getTokenKey(String uuid) {
        return Constants.LOGIN_TOKEN_KEY + uuid;
    }


}

3. 实现CustomUserDetailService,获取用户时,我添加了用户的角色权限信息

package com.duplicall.imam.server.app.config.security.auth;

import com.duplicall.imam.model.Permission;
import com.duplicall.imam.model.Role;
import com.duplicall.imam.model.User;
import com.duplicall.imam.server.app.config.security.bean.LoginUser;
import com.duplicall.imam.server.app.service.permission.IPermission;
import com.duplicall.imam.server.app.service.user.IUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Description CustomUserDetailService
 * @Author Sean
 * @Date 2021/1/18 15:24
 * @Version 1.0
 */
@Component
public class CustomUserDetailService implements UserDetailsService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private IUser userService;
    @Autowired
    private IPermission permission;

    // 添加用户角色信息 权限信息
    @Override
    public UserDetails loadUserByUsername(String s) {
        logger.info("login id [{}] start login ", s);
        User user = userService.getUserByLoginId(s);
        if(Objects.isNull(user)){
            logger.warn("user [{}] is not exists ", s);
            throw new BadCredentialsException("User Bad Credentials");
        }
        List<Role> roles = userService.getUserRoles(user.getId());
        List<String> roleNames = roles.stream().map(Role::getName).collect(Collectors.toList());
        Set<String> roleSet = new HashSet<>(roleNames);
        Set<String> permissionNameSet=null;
        if(roleSet.contains("admin")){
            permissionNameSet = new HashSet<>();
            permissionNameSet.add("admin");
        }else {
            List<Short> ids = roles.stream().map(Role::getId).collect(Collectors.toList());
            Set<Permission> permissions = permission.getPermissions(ids);
            List<String> permissionNames = permissions.stream().map(Permission::getName).collect(Collectors.toList());
            permissionNameSet = new HashSet<>(permissionNames);
            permissionNames.addAll(roleSet);
        }
        return new LoginUser(user, roleSet,permissionNameSet);
    }
}

4. 实现验证失败处理 CustomAuthenticationEntryPoint

package com.duplicall.imam.server.app.config.security.auth;

import com.alibaba.fastjson.JSON;
import com.duplicall.imam.common.bo.Result;
import com.duplicall.imam.server.app.utils.ServletUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Description CustomAuthenticationEntryPoint
 * @Author Sean
 * @Date 2021/2/4 11:04
 * @Version 1.0
 */
@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    private final Logger logger = LoggerFactory.getLogger(CustomAuthenticationEntryPoint.class);

    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        logger.debug("auth failed as [{}]", e.getMessage(), e);
        ServletUtil.renderString(response, JSON.toJSONString(Result.error(HttpStatus.UNAUTHORIZED.value(), "auth failed")));
    }
}

5 .实现登出处理 CustomLogoutSuccessHandler

package com.duplicall.imam.server.app.config.security.auth;

import com.alibaba.fastjson.JSON;
import com.duplicall.imam.common.bo.Result;
import com.duplicall.imam.server.app.config.security.bean.LoginUser;
import com.duplicall.imam.server.app.utils.ServletUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * @Description CustomLogoutSuccessHandler
 * @Author Sean
 * @Date 2021/1/18 18:07
 * @Version 1.0
 */
@Component
public class CustomLogoutSuccessHandler implements LogoutSuccessHandler {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private UserTokenService userTokenService;

    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        LoginUser loginUser = userTokenService.getLoginUser(httpServletRequest);
        if (Objects.nonNull(loginUser)) {
            logger.info("user [{}] logout success ", loginUser.getUsername());
            userTokenService.delLoginUser(loginUser.getToken());
        }
        ServletUtil.renderString(httpServletResponse, JSON.toJSONString(Result.success( "log out success")));
    }
}

6 .实现 JwtAuthenticationTokenFilter 过滤

package com.duplicall.imam.server.app.config.security.filter;

import com.duplicall.imam.server.app.config.security.auth.UserTokenService;
import com.duplicall.imam.server.app.config.security.bean.LoginUser;
import lombok.SneakyThrows;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
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.Objects;

/**
 * @Description JwtAuthenticationTokenFilter
 * @Author Sean
 * @Date 2021/2/7 17:17
 * @Version 1.0
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Resource
    private UserTokenService tokenService;

    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        String tokenHeader = httpServletRequest.getHeader("Authorization");
        if (!StringUtils.hasLength(tokenHeader)) {
            filterChain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }
        LoginUser loginUser = tokenService.getLoginUser(httpServletRequest);
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (Objects.nonNull(loginUser) && Objects.isNull(authentication)) {
            String url = httpServletRequest.getRequestURI();
            if (!url.contains("home/mapDate")) {
                tokenService.verifyToken(loginUser);
            }
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }
}

7. 添加验证过滤SecurityConfig

package com.duplicall.imam.server.app.config.security;

import com.duplicall.imam.server.app.config.security.auth.CustomAuthenticationEntryPoint;
import com.duplicall.imam.server.app.config.security.auth.CustomLogoutSuccessHandler;
import com.duplicall.imam.server.app.config.security.auth.CustomUserDetailService;
import com.duplicall.imam.server.app.config.security.filter.JwtAuthenticationTokenFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import javax.annotation.Resource;

/**
 * 安全过滤 使用jwt
 */
@Configuration
@EnableGlobalMethodSecurity(
        // securedEnabled = true,
        // jsr250Enabled = true,
        prePostEnabled = true)
public class SecurityConfig {
    @Resource
    private CustomUserDetailService customUserDetailService;

    @Resource
    private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
    @Resource
    private CustomLogoutSuccessHandler customLogoutSuccessHandler;

    @Resource
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(customUserDetailService);
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        return authenticationProvider;
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 获取AuthenticationManager(认证管理器),登录时认证使用
     * @param authenticationConfiguration
     * @return
     * @throws Exception
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        // 设置访问源地址
        config.addAllowedOriginPattern("*");
        // 设置访问源请求头
        config.addAllowedHeader("*");
        // 设置访问源请求方法
        config.addAllowedMethod("*");
        config.setMaxAge(3600L);
        // 对接口配置跨域设置
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);

    }

    /**
     * 授权
     * @param
     * @return
     * @throws Exception
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        // 认证失败处理类
        httpSecurity.cors().and().csrf().disable()
                .exceptionHandling().authenticationEntryPoint(customAuthenticationEntryPoint).and()
                // 基于 token,不需要 session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests().antMatchers("/login/**","/download/**","/websocket/**","/agent/**","/rest/**").permitAll()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated()
                ;
        httpSecurity.authenticationProvider(authenticationProvider());
        httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter,UsernamePasswordAuthenticationFilter.class);

        httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(customLogoutSuccessHandler);

        return httpSecurity.build();
    }
}

以上 Security 配置完成。

如果你需要开放Cros跨域访问,则添加如下配置,使用@Bean:

 @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        // 设置访问源地址
        config.addAllowedOriginPattern("*");
        // 设置访问源请求头
        config.addAllowedHeader("*");
        // 设置访问源请求方法
        config.addAllowedMethod("*");
        config.setMaxAge(3600L);
        // 对接口配置跨域设置
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);

    }

升级需要注意的点,如果遇到循环引用注册bean不成功,则添加配置

spring:
  profiles:
    active: dev
  main:
    allow-circular-references: true
    allow-bean-definition-overriding:  true

另外还需要注意的一个地方:

springboot2.0以上context-path的配置改成了如下,这也是需要注意的要点:

server:
  port: 8080
  servlet:
    context-path: /app

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot 1.5.9中解决跨域问题可以通过实现WebMvcConfigurer接口来配置。首先,创建一个配置类并实现WebMvcConfigurer接口。然后,在该类中重写addCorsMappings方法,使用CorsRegistry对象来添加跨域配置。具体来说,可以通过调用CorsRegistry对象的addMapping方法来指定需要处理跨域的请求路径,并使用allowedOrigins、allowedMethods、allowedHeaders和allowCredentials方法来配置允许的源、方法、头部和凭据。 以下是一个示例配置类的代码片段,用于解决跨域问题: @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 指定需要处理跨域的请求路径,这里是所有路径 .allowedOrigins("*") // 允许所有源 .allowedMethods("*") // 允许所有方法 .allowedHeaders("*") // 允许所有头部 .allowCredentials(true); // 允许发送凭据信息 } } 这段代码中,addMapping("/**")表示将所有请求路径都进行跨域处理,allowedOrigins("*")表示允许所有源,allowedMethods("*")表示允许所有方法,allowedHeaders("*")表示允许所有头部,allowCredentials(true)表示允许发送凭据信息。 通过以上配置,SpringBoot 1.5.9可以成功解决跨域问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [SpringBoot教程(七) | SpringBoot解决跨域问题](https://blog.csdn.net/lsqingfeng/article/details/122614630)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [关于SpringBoot 项目跨域问题的几种解决方法](https://blog.csdn.net/2301_76607156/article/details/130485123)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值