springboot + springSecurity + jwt 實現用戶訪問認證和授權


本文講述的是springboot集成springSecurity和JWT的實現。

前后端分離目前已成為互聯網項目開發的業界標准,其核心思想就是前端(APP、小程序、H5頁面等)通過調用后端的API接口,提交及返回JSON數據進行交互。
在前后端分離項目中,首先要解決的就是登錄及授權的問題。傳統的session認證限制了應用的擴展能力,無狀態的JWT認證方法應運而生,該認證機制特別適用於分布式站點的單點登錄(SSO)場景。

  

一,導入SpringSecurity與JWT的相關依賴

 

       <!--Security框架-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        
        <!-- jwt -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.10.6</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.10.6</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.10.6</version>
        </dependency>

  

二,定義SpringSecurity需要的基礎處理類

  application-dev.properties 加入jwt配置信息  

##jwt
# 令牌key
jwt.header = Authorization
# 令牌前綴
jwt.token-start-with = Bearer
# 使用Base64對該令牌進行編碼
jwt.base64-secret = U2FsdGVkX1/3Ox76xzrqllLe1lIgoHycDTgwVYrFQTPhG9V1lQPnLerFS/tmN1PzrQmx5243Nu9/iJf88neqOA==
# 令牌過期時間 此處單位/毫秒
jwt.token-validity-in-seconds = 14400000

  創建一個jwt的配置類,並注入Spring,便於程序中調用

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @ProjectName: git-dev
 * @Package: com.lq.pys.base.config
 * @ClassName: JwtSecurityProperties
 * @Author: xxx
 * @Description: JWT配置類
 * @Date: 2021/2/18 10:55 上午
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "jwt")
public class JwtSecurityProperties {

    /** Request Headers : Authorization */
    private String header;

    /** 令牌前綴,最后留個空格 Bearer */
    private String tokenStartWith;

    /** Base64對該令牌進行編碼 */
    private String base64Secret;

    /** 令牌過期時間 此處單位/毫秒 */
    private Long tokenValidityInSeconds;

    /**返回令牌前綴 */
    public String getTokenStartWith() {
        return tokenStartWith + " ";
    }

}

  定義無權限訪問類

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lq.pys.base.core.BDic;
import com.lq.pys.base.core.BaseOut;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

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

/**
 * @ProjectName: git-dev
 * @Package: com.lq.pys.base.common
 * @ClassName: JwtAccessDeniedHandler
 * @Author: xxx
 * @Description: jwt無權限訪問類
 * @Date: 2021/2/18 11:28 上午
 */
@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        // 這個是自定義的返回對象,看各自需求
        BaseOut baseOut = new BaseOut();
        baseOut.setCode(BDic.FAIL);
        baseOut.setMessage("無權限查看此頁面,請聯系管理員!");
        baseOut.setTimestamp(Long.valueOf(System.currentTimeMillis()).toString());
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_OK);
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.writeValue(response.getOutputStream(), baseOut);
        } catch (Exception e) {
            throw new ServletException();
        }
    }
}    

 

  定義認證失敗處理類

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lq.pys.base.core.BDic;
import com.lq.pys.base.core.BaseOut;
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;

/**
 * @ProjectName: git-dev
 * @Package: com.lq.pys.base.common
 * @ClassName: JwtAuthenticationEntryPoint
 * @Author: xxx
 * @Description: JWT認證失敗處理類
 * @Date: 2021/2/18 11:31 上午
 */
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response,
                         AuthenticationException authException) throws IOException, ServletException {
        BaseOut baseOut = new BaseOut();
        baseOut.setCode(BDic.FAIL);
        baseOut.setMessage("無權限查看此頁面,請聯系管理員");
        baseOut.setTimestamp(Long.valueOf(System.currentTimeMillis()).toString());
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_OK);
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.writeValue(response.getOutputStream(), baseOut);
        } catch (Exception e) {
            throw new ServletException();
        }
    }
}

 

三,構建JWT token工具類

  工具類實現創建token與校驗token功能

import com.lq.pys.base.config.JwtSecurityProperties;
import com.lq.pys.base.core.UserInfo;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ProjectName: git-dev
 * @Package: com.lq.pys.util
 * @ClassName: JwtTokenUtils
 * @Author: xxx
 * @Description: JWT
 * @Date: 2021/2/18 11:01 上午
 */
@Slf4j
@Component
public class JwtTokenUtils implements InitializingBean {

    private final JwtSecurityProperties jwtSecurityProperties;
    private static final String AUTHORITIES_KEY = "auth";
    private Key key;

    public JwtTokenUtils(JwtSecurityProperties jwtSecurityProperties) {
        this.jwtSecurityProperties = jwtSecurityProperties;
    }

    @Override
    public void afterPropertiesSet() {

        byte[] keyBytes = Decoders.BASE64.decode(jwtSecurityProperties.getBase64Secret());
        this.key = Keys.hmacShaKeyFor(keyBytes);
    }


    public String createToken (Map<String, Object> claims) {
        return Jwts.builder()
                .claim(AUTHORITIES_KEY, claims)
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(new Date())
                .setExpiration(new Date((new Date()).getTime() + jwtSecurityProperties.getTokenValidityInSeconds()))
                .compressWith(CompressionCodecs.DEFLATE)
                .signWith(key, SignatureAlgorithm.HS512)
                .compact();
    }

    public Date getExpirationDateFromToken(String token) {
        Date expiration;
        try {
            final Claims claims = getClaimsFromToken(token);
            expiration = claims.getExpiration();
        } catch (Exception e) {
            expiration = null;
        }
        return expiration;
    }

    public Authentication getAuthentication(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(key)
                .parseClaimsJws(token)
                .getBody();

        Collection<? extends GrantedAuthority> authorities =
                Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
                        .map(SimpleGrantedAuthority::new)
                        .collect(Collectors.toList());

        HashMap map =(HashMap) claims.get("auth");

        UserInfo principal = new UserInfo(map);

        return new UsernamePasswordAuthenticationToken(principal, token, authorities);
    }

    public boolean validateToken(String authToken) {
        try {
            Jwts.parser().setSigningKey(key).parseClaimsJws(authToken);
            return true;
        } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
            log.error("token失效",e);
        } catch (ExpiredJwtException e) {
            log.error("token過期",e);
        } catch (UnsupportedJwtException e) {
            log.error("無效的token",e);
        } catch (IllegalArgumentException e) {
            log.error("處理token異常.",e);
        }
        return false;
    }

    private Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(key)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            claims = null;
        }
        return claims;
    }
}

 

四,實現token驗證的過濾器

  該類繼承OncePerRequestFilter,它能夠確保在一次請求中只通過一次filter。該類使用JwtTokenUtils工具類進行token校驗。

import com.lq.pys.base.common.SpringContextHolder;
import com.lq.pys.base.config.JwtSecurityProperties;
import com.lq.pys.util.JwtTokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

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

/**
 * @ProjectName: git-dev
 * @Package: com.lq.pys.base.filter
 * @ClassName: JwtAuthenticationTokenFilter
 * @Author: xxx
 * @Description: JWT過濾器
 * @Date: 2021/2/18 11:07 上午
 */
@Component
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    private JwtTokenUtils jwtTokenUtils;

    public JwtAuthenticationTokenFilter(JwtTokenUtils jwtTokenUtils) {
        this.jwtTokenUtils = jwtTokenUtils;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        JwtSecurityProperties jwtSecurityProperties = SpringContextHolder.getBean(JwtSecurityProperties.class);
        String requestRri = httpServletRequest.getRequestURI();
        //獲取request token
        String token = null;
        String bearerToken = httpServletRequest.getHeader(jwtSecurityProperties.getHeader());
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(jwtSecurityProperties.getTokenStartWith())) {
            token = bearerToken.substring(jwtSecurityProperties.getTokenStartWith().length());
        }

        if (StringUtils.hasText(token) && jwtTokenUtils.validateToken(token)) {
            Authentication authentication = jwtTokenUtils.getAuthentication(token);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            log.debug("set Authentication to security context for '{}', uri: {}", authentication.getName(), requestRri);
        } else {
            log.debug("no valid JWT token found, uri: {}", requestRri);
        }
        filterChain.doFilter(httpServletRequest, httpServletResponse);

    }
}

  根據SpringBoot官方讓重復執行的filter實現一次執行過程的解決方案,參見官網地址:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-disable-registration-of-a-servlet-or-filter
需在SpringBoot啟動類中,加入以下代碼:  

 /**
     * @Description:
     * @param filter:
     * @return: org.springframework.boot.web.servlet.FilterRegistrationBean
     * @author: xxx
     * @date: 2021/2/18 11:14 上午
     */
    @Bean
    public FilterRegistrationBean registration(JwtAuthenticationTokenFilter filter) {
        FilterRegistrationBean registration = new FilterRegistrationBean<>(filter);
        registration.setEnabled(false);
        return registration;
    }

 

五,SpringSecurity的關鍵配置

  SpringBoot推薦使用配置類來代替xml配置,該類中涉及了以上幾個bean來供security使用

  • JwtAccessDeniedHandler :無權限訪問
  • jwtAuthenticationEntryPoint :認證失敗處理
  • jwtAuthenticationTokenFilter :token驗證的過濾器
import com.lq.pys.base.exception.JwtAccessDeniedHandler;
import com.lq.pys.base.exception.JwtAuthenticationEntryPoint;
import com.lq.pys.base.filter.JwtAuthenticationTokenFilter;
import com.lq.pys.util.JwtTokenUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @ProjectName: git-dev
 * @Package: com.lq.pys.base.config
 * @ClassName: WebSecurityConfig
 * @Author: xxx
 * @Description: SpringSecurity關鍵配置
 * @Date: 2021/2/18 11:20 上午
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
    private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    private final JwtTokenUtils jwtTokenUtils;

    public WebSecurityConfig(JwtAccessDeniedHandler jwtAccessDeniedHandler, JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint, JwtTokenUtils jwtTokenUtils) {
        this.jwtAccessDeniedHandler = jwtAccessDeniedHandler;
        this.jwtAuthenticationEntryPoint = jwtAuthenticationEntryPoint;
        this.jwtTokenUtils = jwtTokenUtils;
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // 禁用 CSRF
                .csrf().disable()
                // 授權異常
                .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .accessDeniedHandler(jwtAccessDeniedHandler)
                // 不創建會話
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                // 放行swagger
                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/*/api-docs").permitAll()
                // 跨域請求會先進行一次options請求 必須放行的OPTIONS請求
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                //允許匿名及登錄用戶訪問
                .antMatchers("/api/auth/**", "/error/**").permitAll()

                // 不需要token的訪問
                .antMatchers("/admin/**").permitAll()
                .antMatchers("/login/**").permitAll()
                .antMatchers("/sms/**").permitAll()
                .antMatchers("/membersTypeInfo/**").permitAll()
                .antMatchers("/membersClassInfo/**").permitAll()
                .antMatchers("/membersRightsInfo/**").permitAll()
                .antMatchers("/oss/**").permitAll()
                .antMatchers("/storeUser/**").permitAll()
                .antMatchers("/imgConfigure/**").permitAll()
                .antMatchers("/userMembersInfo/**").permitAll()

//                .antMatchers("/sms/**").permitAll()

                // 所有請求都需要認證
                .anyRequest().authenticated();

        // 禁用緩存
        httpSecurity.headers().cacheControl();

        // 添加JWT filter
        httpSecurity.apply(new TokenConfigurer(jwtTokenUtils));

    }

    public class TokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

        private final JwtTokenUtils jwtTokenUtils;

        public TokenConfigurer(JwtTokenUtils jwtTokenUtils){

            this.jwtTokenUtils = jwtTokenUtils;
        }

        @Override
        public void configure(HttpSecurity http) {
            JwtAuthenticationTokenFilter customFilter = new JwtAuthenticationTokenFilter(jwtTokenUtils);
            http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
        }
    }
}

 

六,編寫Controller/Service進行測試

  登錄后可以使用 LoginUserUtilV3.getLoginUser().getUserOperationId(); 獲取用戶信息

/**
 * @ProjectName: git-dev
 * @Package: com.lq.pys.system.controller
 * @ClassName: AdminLoginController
 * @Author: xxx
 * @Description: 后台登錄 控制器
 * @Date: 2021/2/8 1:23 下午
 */
@RestController
@RequestMapping("/admin/login/")
public class AdminLoginController extends ZyBaseController {

    @Autowired
    private LoginService loginService;

    /**
     * @param in:
     * @Description: Admin 密碼登錄
     * @return: com.lq.pys.base.core.BaseOut
     * @author: xxx
     * @date: 2021/2/8 10:18 上午
     */
    @PostMapping("password")
    public BaseOut password(@RequestBody @Validated(value = {PasswordLogin.class}) LoginIn in) {
        in.setLoginType(LoginDic.LOGIN_TYPE.PASSWORD);
        LoginAdminUserOut loginAdminUserOut = loginService.adminLogin(in);
        return setSuccessBaseOut(loginAdminUserOut);
    }
}
/**
 * @ProjectName: git-dev
 * @Package: com.lq.pys.system.service
 * @ClassName: LoginService
 * @Author: xxx
 * @Description: 登錄業務處理
 * @Date: 2021/2/8 9:33 上午
 */
@Slf4j
@Service
public class LoginService {

    @Autowired
    protected SysUserService sysUserService;
    @Autowired
    protected CaptchaService captchaService;
    @Autowired
    private JwtTokenUtils jwtTokenUtils;


    /**
     * @Description: Admin 用戶登錄
     * @param in:
     * @return: com.lq.pys.system.login.out.LoginAdminUserOut
     * @author: xxx
     * @date: 2021/2/8 10:44 上午
     */
    public LoginAdminUserOut adminLogin(LoginIn in) {

        /** 校驗用戶名/密碼/圖片驗證碼 */
        SysUser sysUser = sysUserService.getUserByAccount(in.getAccount());
        Optional.ofNullable(sysUser).orElseThrow(()->new BusinessException("用戶不存在,不允許登錄"));
        Optional.ofNullable(sysUser.getPassword()).filter(s->sysUser.getPassword().equals(SecurityUtil.pwdEncrypt(in.getPassword()))).orElseThrow(()->new BusinessException("登錄密碼錯誤,請重新輸入"));
//        captchaService.check(in.getImageCodekey(),in.getImageCode());

        LoginAdminUserOut loginAdminUserOut = new LoginAdminUserOut();
        /** 設置用戶信息 */
        AdminUserOut adminUserOut = new AdminUserOut();
        BeanUtils.copyProperties(sysUser,adminUserOut);
        loginAdminUserOut.setUserInfo(adminUserOut);
        /** 設置用戶權限 */

        /** 設置token */
        String token = jwtTokenUtils.createToken(convertToMap(adminUserOut));
        loginAdminUserOut.setToken(token);

        return loginAdminUserOut;
    }
}

  使用IDEA Rest Client測試如下:

 

 

  無token和token失效返回的錯誤信息:

 

 

 

 

  使用到的用戶對象的類:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.lq.pys.system.dto.sys.ZySysRole;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

@Data
public class LoginUserV3 implements UserDetails {

    /**
     * 業務ID
     */
    private String userOperationId;

    /**
     * 登錄帳戶
     */
    private String account;

    /**
     * 手機號
     */
    private String phone;

    /**
     * 密碼
     */
    private String password;

    /**
     * 邀請碼
     */
    private String invitation;

    /**
     * 創建時間
     */
    private Date createTime;

    /**
     * 是否是章魚管理員
     */
    private Boolean isZyAdmin = false;

    /**
     * 登陸UUID
     */
    private String loginUUID;

    private Set<ZySysRole> sysRoles;

    private Set<String> permissions;

    @JsonIgnore
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> collection = new HashSet<>();
        if (!CollectionUtils.isEmpty(sysRoles)) {
            sysRoles.parallelStream().forEach(role -> {
                if (role.getRole_name().startsWith("ROLE_")) {
                    collection.add(new SimpleGrantedAuthority(role.getRole_name()));
                } else {
                    collection.add(new SimpleGrantedAuthority("ROLE_" + role.getRole_name()));
                }
            });
        }

        if (!CollectionUtils.isEmpty(permissions)) {
            for (String per : permissions){
                collection.add(new SimpleGrantedAuthority(per));
            }
        }

        return collection;
    }

    @Override
    public String getUsername() {
        return getAccount();
    }

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

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

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

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

  全局獲取用戶對象的工具類

import com.alibaba.fastjson.JSONObject;
import com.lq.pys.base.core.UserInfo;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

public class LoginUserUtilV3 {

    /**
     * @Description: 獲取登錄信息
     * @param :
     * @return: com.lq.pys.system.login.LoginUserV3
     * @author: xxx
     * @date: 2021/2/21 19:04 上午
     */
    public static LoginUserV3 getLoginUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication instanceof UsernamePasswordAuthenticationToken) {
            UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) authentication;
            Object str = authenticationToken.getPrincipal();
            UserInfo userInfo = (UserInfo) str;
            LoginUserV3 loginUserV3 = JSONObject.parseObject(JSONObject.toJSONString(userInfo), LoginUserV3.class);
            return loginUserV3;
        }
        return null;
    }
}

  用戶實體類:

/**
 * @ProjectName: git-dev
 * @Package: com.lq.pys.util
 * @ClassName: UserInfo
 * @Author: xxx
 * @Description: 用戶信息類
 * @Date: 2021/2/18 11:01 上午
 */
@Data
public class UserInfo implements Serializable{

    private static final long serialVersionUID = 4768132985889604776L;

    /** 用戶ID */
    private Long id;
    /** 用戶業務id */
    private String userOperationId;
    /**  用戶賬號 */
    private String account;
    /**  用戶密碼 */
    private String password;

    public UserInfo(HashMap map){
        this.userOperationId =  map.get("operationId").toString();
        this.account =  map.get("account").toString();
        this.password = map.get("password").toString();
    }

}

 

解決跨域問題:

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;

/**
 * @ProjectName: git-dev
 * @Package: com.lq.pys.base.config
 * @ClassName: CorsConfig
 * @Author: xxx
 * @Description: 解決跨域問題
 * @Date: 2021/2/18 1:39 下午
 */
@Configuration
public class CorsConfig {

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();

        /**
         * 你需要跨域的地址  注意這里的 127.0.0.1 != localhost
         * 表示只允許http://localhost:8080地址的訪問(重點哦!!!!)
         * corsConfiguration.addAllowedOrigin("http://localhost:8080");
         */
        //允許所有域名進行跨域調用
        corsConfiguration.addAllowedOrigin("*");
        //放行全部原始頭信息
        corsConfiguration.addAllowedHeader("*");
        //允許所有請求方法跨域調用
        corsConfiguration.addAllowedMethod("*");
        //允許跨越發送cookie
        corsConfiguration.setAllowCredentials(true);

        return corsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        //配置 可以訪問的地址
        source.registerCorsConfiguration("/**", buildConfig()); // 4
        return new CorsFilter(source);
    }

 

麻麻思day.

 

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM