springcloud+gateway+springsecurity+vue前后端登錄

搭建微服務(wù)還是異常的艱難呀.....
本來(lái)想就在web_portal下整合springsecurity 但是又想既然搭建了gateway(網(wǎng)關(guān)),又為何不直接集成到網(wǎng)關(guān)當(dāng)中呢
說(shuō)干就干

引入maven

    <!-->spring-boot 整合security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
<!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
        <!-- redis依賴(lài)需要 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
 <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

創(chuàng)建SecurityConfig主配置文件

package com.mysb.core.config;

import com.mysb.core.server.AuthenticationFaillHandler;
import com.mysb.core.server.AuthenticationSuccessHandler;
import com.mysb.core.server.CustomHttpBasicServerAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig{
    @Autowired
    private AuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private AuthenticationFaillHandler authenticationFaillHandler;
    @Autowired
    private CustomHttpBasicServerAuthenticationEntryPoint customHttpBasicServerAuthenticationEntryPoint;

    //security的鑒權(quán)排除列表
    private static final String[] excludedAuthPages = {
            "/login",
            "/logout",
            "/home/**",
            "/user/**",
            "/category/**"
    };

    @Bean
    SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception {
        http
                .cors()
                .and()
                .authorizeExchange()
                .pathMatchers(excludedAuthPages).permitAll()  //無(wú)需進(jìn)行權(quán)限過(guò)濾的請(qǐng)求路徑
                .pathMatchers(HttpMethod.OPTIONS).permitAll() //option 請(qǐng)求默認(rèn)放行
                .anyExchange().authenticated()
                .and()
                .httpBasic()
                .and()
                .formLogin()
                .authenticationSuccessHandler(authenticationSuccessHandler) //認(rèn)證成功
                .authenticationFailureHandler(authenticationFaillHandler) //登陸驗(yàn)證失敗
                .and().exceptionHandling().authenticationEntryPoint(customHttpBasicServerAuthenticationEntryPoint)  //基于http的接口請(qǐng)求鑒權(quán)失敗
                .and() .csrf().disable()//必須支持跨域

                .logout().disable();

        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return  NoOpPasswordEncoder.getInstance(); //默認(rèn)
    }

}

}

這個(gè)寫(xiě)法是springwebFlux而不是springMVC,因?yàn)間ateway底層是用netty,基于webFlux的,跟SpringMVC傳統(tǒng)方式是不兼容的,詳細(xì)看下這位大神https://blog.csdn.net/tiancao222/article/details/104375924

配置spring security還是跟以前一樣

創(chuàng)建成功攔截器

因?yàn)榍昂蠖朔蛛xaxios異步不能有重定向 就只能用攔截器來(lái)返回給前端參數(shù)

package com.mysb.core.server;

import com.alibaba.csp.ahas.shaded.com.alibaba.acm.shaded.com.google.gson.JsonObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mysb.core.utils.MessageCode;
import com.mysb.core.utils.WsResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.server.WebFilterExchange;
import org.springframework.security.web.server.authentication.WebFilterChainServerAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.UUID;
import java.util.concurrent.TimeUnit;


@Component
public class AuthenticationSuccessHandler extends WebFilterChainServerAuthenticationSuccessHandler   {
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication){
        System.out.println("success");
        ServerWebExchange exchange = webFilterExchange.getExchange();
        ServerHttpResponse response = exchange.getResponse();
        //設(shè)置headers
        HttpHeaders httpHeaders = response.getHeaders();
        httpHeaders.add("Content-Type", "application/json; charset=UTF-8");
        httpHeaders.add("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
        httpHeaders.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "Authorization");
        //設(shè)置body
        WsResponse wsResponse = WsResponse.success();
        byte[] dataBytes={};
        ObjectMapper mapper = new ObjectMapper();
        try {
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            httpHeaders.add(HttpHeaders.AUTHORIZATION, uuid);
            wsResponse.setResult(authentication.getName());
            //保存token
            redisTemplate.boundValueOps(uuid).set(authentication.getName(), 2*60*60, TimeUnit.SECONDS);
            dataBytes=mapper.writeValueAsBytes(wsResponse);
        }
        catch (Exception ex){
            ex.printStackTrace();
            JsonObject result = new JsonObject();
            result.addProperty("status", MessageCode.COMMON_FAILURE.getCode());
            result.addProperty("message", "授權(quán)異常");
            dataBytes=result.toString().getBytes();
        }
        DataBuffer bodyDataBuffer = response.bufferFactory().wrap(dataBytes);
        System.out.println(wsResponse);
        return response.writeWith(Mono.just(bodyDataBuffer));
    }

}

這里的寫(xiě)法也是webfulx的,這里不展開(kāi)討論 wsResponse則是自定義返回前端的參數(shù) 參考的是這篇文章https://blog.csdn.net/MongolianWolf/article/details/94329980

失敗攔截器

@Component
public class AuthenticationFaillHandler  implements ServerAuthenticationFailureHandler {

    @Override
    public Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException e) {
        System.out.println("fail");
        ServerWebExchange exchange = webFilterExchange.getExchange();
        ServerHttpResponse response = exchange.getResponse();
        //設(shè)置headers
        HttpHeaders httpHeaders = response.getHeaders();
        httpHeaders.add("Content-Type", "application/json; charset=UTF-8");
        httpHeaders.add("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
        //設(shè)置body
        WsResponse<String> wsResponse = WsResponse.failure(MessageCode.COMMON_AUTHORIZED_FAILURE);
        byte[]   dataBytes={};
        try {
            ObjectMapper mapper = new ObjectMapper();
            dataBytes=mapper.writeValueAsBytes(wsResponse);
        }
        catch (Exception ex){
            ex.printStackTrace();
        }
        DataBuffer bodyDataBuffer = response.bufferFactory().wrap(dataBytes);
        return response.writeWith(Mono.just(bodyDataBuffer));
    }
}

http的接口請(qǐng)求鑒權(quán)失敗

package com.mysb.core.server;

import com.alibaba.csp.ahas.shaded.com.alibaba.acm.shaded.com.google.gson.JsonObject;
import com.mysb.core.utils.MessageCode;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.server.authentication.HttpBasicServerAuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class CustomHttpBasicServerAuthenticationEntryPoint extends HttpBasicServerAuthenticationEntryPoint /* implements ServerAuthenticationEntryPoint */{


    private static final String WWW_AUTHENTICATE = "WWW-Authenticate";
    private static final String DEFAULT_REALM = "Realm";
    private static String WWW_AUTHENTICATE_FORMAT = "Basic realm=\"%s\"";
    private String headerValue = createHeaderValue("Realm");
    public CustomHttpBasicServerAuthenticationEntryPoint() {
    }



    public void setRealm(String realm) {
        this.headerValue = createHeaderValue(realm);
    }

    private static String createHeaderValue(String realm) {
        Assert.notNull(realm, "realm cannot be null");
        return String.format(WWW_AUTHENTICATE_FORMAT, new Object[]{realm});
    }

    @Override
    public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException e) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().add("Content-Type", "application/json; charset=UTF-8");
        response.getHeaders().set(HttpHeaders.AUTHORIZATION, this.headerValue);
        JsonObject result = new JsonObject();
        result.addProperty("status", MessageCode.COMMON_AUTHORIZED_FAILURE.getCode());
        result.addProperty("message", MessageCode.COMMON_AUTHORIZED_FAILURE.getMsg());
        byte[] dataBytes=result.toString().getBytes();
        DataBuffer bodyDataBuffer = response.bufferFactory().wrap(dataBytes);
        return response.writeWith(Mono.just(bodyDataBuffer));
    }
}

這個(gè)貼過(guò)去就完事 哈哈哈哈哈

授權(quán)

package com.mysb.core.server;

import com.mysb.core.interfac.LoginFeignClient;
import com.mysb.core.pojo.customer.Customer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.*;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

@Component
public class UserDetailServiceImpl implements ReactiveUserDetailsService {

    @Autowired
    private LoginFeignClient loginFeignClient;

    @Override
    public Mono<UserDetails> findByUsername(String username) {
        /*定義權(quán)限集合*/
        List<GrantedAuthority> authority = new ArrayList<>();
        SimpleGrantedAuthority role_seller = new SimpleGrantedAuthority("ROLE_USER");
        authority.add(role_seller);
        if (username == null) {
            return null;
        }
        Customer customer = loginFeignClient.findUserByUsername(username);
        if(customer != null){
            if (customer.getUsername().equals(username)) {
                UserDetails user = User.withUsername(customer.getUsername())
                        .password(customer.getPassword())
                        .roles("USER")
                        .build();
                return Mono.just(user);
            }
        }
        return Mono.error(new UsernameNotFoundException("User Not Found"));
    }


}

在Vue中登錄form表單發(fā)送請(qǐng)求必須是post 而且 input當(dāng)中的name 必須是username和password
用表單提交時(shí) 后端能接收并返回參數(shù) 但是用axios提交就跨域就在main.js加了

axios.defaults.withCredentials = true;

后來(lái)發(fā)現(xiàn)沒(méi)用,經(jīng)過(guò)對(duì)比兩個(gè)請(qǐng)求的區(qū)別 最終我準(zhǔn)備試著使用把參數(shù)用form Data的樣子進(jìn)行傳參
就需要引入qs和用修改header發(fā)現(xiàn)竟然行

  onSubmit(value) {
                let vm = this;
                console.log(value);
                vm.axios.post(vm.API.LOGIN_URL,qs.stringify(value),
                    {headers: {'Content-Type':'application/x-www-form-urlencoded'}}
                ).then(res=>{
                    console.log(res);
                    if(res.data.status){
                        vm.StorageUtil.Session.set("token", res.headers.authorization);
                        vm.StorageUtil.Session.set("username", res.data.result);
                        this.$router.push("/dashboard/home");
                        vm.StorageUtil.Session.setItem('tabBarActiveIndex',0);
                    }
                });
            },

回到后端,在授權(quán)時(shí),訪問(wèn)數(shù)據(jù)庫(kù)所以用fegin連接service記住要加給啟動(dòng)類(lèi)

@EnableFeignClients

配置文件yml fegin連接的時(shí)間可以設(shè)置長(zhǎng)點(diǎn) 否則會(huì)報(bào)超時(shí)異常

ribbon:
  eager-load:
    enabled: true
    clients: service-portal #ribbon饑餓加載  多個(gè)服務(wù)逗號(hào)分離
  ReadTimeout: 60000
  ConnectTimeout: 60000
feign:
  sentinel:
    enabled: true
    # feign調(diào)用超時(shí)時(shí)間配置
  client:
    config:
      default:
        connectTimeout: 10000
        readTimeout: 600000

設(shè)置全局過(guò)濾器

在成功攔截器設(shè)置了token頭信息 那么在前端訪問(wèn)的都會(huì)帶有token,所以需要配置過(guò)濾器

package com.mysb.core.filter;

import com.mysb.core.server.UserDetailServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

//自定義全局過(guò)濾器
@Component
@Order(Ordered.HIGHEST_PRECEDENCE + 1)
public class TokenGlobalFilter implements GlobalFilter {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserDetailServiceImpl userDetailService;
    private static final String AUTHORIZE_TOKEN = "token";

    @Override
    //執(zhí)行過(guò)濾器邏輯
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("執(zhí)行過(guò)濾器邏輯");
        String token = exchange.getRequest().getHeaders().getFirst(AUTHORIZE_TOKEN);
        System.out.println(token);
        if (!StringUtils.isEmpty(token)) {//判斷token是否為空
            String username = (String) redisTemplate.boundValueOps(token).get();
            System.out.println(username);
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {//判斷Security的用戶認(rèn)證信息
                Mono<UserDetails> byUsername = userDetailService.findByUsername(username);
                // 將用戶信息存入 authentication棺蛛,方便后續(xù)校驗(yàn)
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(byUsername.block(), null, byUsername.block().getAuthorities());
                authentication.setDetails(byUsername.block());
                // 將 authentication 存入 ThreadLocal怔蚌,方便后續(xù)獲取用戶信息
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        //放行
        return chain.filter(exchange);
    }

}

跨域

package com.mysb.core.filter;

import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import java.util.Collections;


@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsWebFilter implements WebFilter {
  private static final String ALL = "*";

  private static final String MAX_AGE = "86400";

  @Override

  public Mono<Void> filter(ServerWebExchange ctx, WebFilterChain chain) {
      ServerHttpRequest request = ctx.getRequest();
      String path = request.getPath().value();
      System.out.println("跨域驗(yàn)證");
      ServerHttpResponse response = ctx.getResponse();
      if ("/favicon.ico".equals(path)) {
          response.setStatusCode(HttpStatus.OK);
          return Mono.empty();
      }
      if (!CorsUtils.isCorsRequest(request)) {
          return chain.filter(ctx);
      }
      HttpHeaders requestHeaders = request.getHeaders();
      HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();
      HttpHeaders headers = response.getHeaders();
      headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());
      headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, Collections.singletonList("Origin, No-Cache, X-Requested-With, If-Modified-Since,x_requested_with," +
              " Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,Authorization,token"));
      if (requestMethod != null) {
          headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "PUT,DELETE,POST,GET,OPTIONS");
      }
      headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
      headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL);
      headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);

      if (request.getMethod() == HttpMethod.OPTIONS) {
          System.out.println("option");
          response.setStatusCode(HttpStatus.OK);
          return Mono.empty();
      }
      return chain.filter(ctx);
  }
}

強(qiáng)調(diào):要給每個(gè)過(guò)濾器配置Order(排序) 因?yàn)閟pringsecurity中內(nèi)置的過(guò)濾器的order很低 所以我就把跨域的過(guò)濾器設(shè)置最大,而token過(guò)濾器+1,跨域必須要比他們兩過(guò)濾器的順序要放在前面

最后用Fegin來(lái)調(diào)用數(shù)據(jù)庫(kù)查詢(xún)用戶的話可能會(huì)報(bào)這樣一個(gè)錯(cuò)

feign.codec.DecodeException: No qualifying bean of type 'org.springframework.boot.autoconfigure.http.HttpMessageConverters' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

這個(gè)就需要加上

package com.mysb.core.config;

import feign.Logger;
import feign.codec.Decoder;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class FeignConfig {

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }


    @Bean
    public Decoder feignDecoder() {
        return new ResponseEntityDecoder(new SpringDecoder(feignHttpMessageConverter()));
    }

    public ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
        final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(new PhpMappingJackson2HttpMessageConverter());
        return new ObjectFactory<HttpMessageConverters>() {
            @Override
            public HttpMessageConverters getObject() throws BeansException {
                return httpMessageConverters;
            }
        };
    }

    public class PhpMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
        PhpMappingJackson2HttpMessageConverter(){
            List<MediaType> mediaTypes = new ArrayList<>();
            mediaTypes.add(MediaType.valueOf(MediaType.TEXT_HTML_VALUE + ";charset=UTF-8")); //關(guān)鍵
            setSupportedMediaTypes(mediaTypes);
        }
    }

}

這是因?yàn)?strong>feign中對(duì)返回的數(shù)據(jù)進(jìn)行解析時(shí),缺少依賴(lài)對(duì)象導(dǎo)致旁赊。詳細(xì)可以去看看https://blog.csdn.net/lizz861109/article/details/105707590
最后貼上wsRespsoneUtil吧

package com.mysb.core.utils;

import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.List;

public class WsResponse<T> {

    private MessageCode status;
    private List<String> messages;
    private T result;

    public WsResponse() {
        messages = new ArrayList<>();
    }

    public WsResponse(MessageCode status, T result) {
        messages = new ArrayList<>();
        this.status = status;
        this.result = result;
    }

    public MessageCode getStatus() {
        return status;
    }

    public void setStatus(MessageCode status) {
        this.status = status;
    }

    public List<String> getMessages() {
        return messages;
    }

    public void setMessages(List<String> messages) {
        this.messages = messages;
    }

    public T getResult() {
        return result;
    }

    public void setResult(T result) {
        this.result = result;
    }

    @Override
    public String toString() {
        return "code:" + status + " result:" + result;
    }

    public static WsResponse failure(String msg) {
        WsResponse resp = new WsResponse();
        resp.status = MessageCode.COMMON_FAILURE;
        resp.getMessages().add(msg);
        return resp;
    }

    public static WsResponse failure(MessageCode messageCode) {
        WsResponse resp = new WsResponse();
        resp.status = messageCode;
        resp.getMessages().add(messageCode.getMsg());
        return resp;
    }

    public static WsResponse failure(MessageCode messageCode, String message) {
        WsResponse resp = new WsResponse();
        resp.status = messageCode;
        if(StringUtils.isNotBlank(messageCode.getMsg())){
            resp.getMessages().add(messageCode.getMsg());
        }
        if (StringUtils.isNotBlank(message)) {
            resp.getMessages().add(message);
        }
        return resp;
    }

    public static WsResponse success() {
        WsResponse resp = new WsResponse();
        resp.status = MessageCode.COMMON_SUCCESS;
        resp.getMessages().add(MessageCode.COMMON_SUCCESS.getMsg());
        return resp;
    }

    public static <K> WsResponse<K> success(K t) {
        WsResponse<K> resp = new WsResponse<>();
        resp.status = MessageCode.COMMON_SUCCESS;
        resp.getMessages().add(MessageCode.COMMON_SUCCESS.getMsg());
        resp.result = t;

        return resp;
    }

    /**
     * 判斷字符串是否已經(jīng)是 WsResponse返回格式
     *
     * @param json
     * @return
     */
    public static boolean isWsResponseJson(String json) {
        if (json != null && json.indexOf("\"status\":") != -1
                && json.indexOf("\"messages\":") != -1
                && json.indexOf("\"result\":") != -1) {
            return true;
        } else {
            return false;
        }
    }
}


package com.mysb.core.utils;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;


public enum MessageCode {

    COMMON_SUCCESS("200","執(zhí)行成功"),
    COMMON_FAILURE("400", "執(zhí)行失敗"),
    COMMON_AUTHORIZED_FAILURE("300", "身份鑒權(quán)失敗");

    //Message 編碼
    private String code;
    //Message 描敘
    private String message;

    MessageCode(String code){
        this.code = code;
    }

    MessageCode(String code, String message){
        this.code = code;
        this.message = message;
    }

    @JsonValue
    public String getCode() {
        return code;
    }

    public String getMsg() {
        return message;
    }

    public void setMsg(String message) {
        this.message = message;
    }

    @JsonCreator
    public static MessageCode getStatusCode(String status) {
        for (MessageCode unit : MessageCode.values()) {
            if (unit.getCode().equals(status)) {
                return unit;
            }
        }

        return null;
    }

    @Override
    public String toString() {
        return "{code:'" + code + '\'' +
                ", message:'" + message + '\'' +
                '}';
    }
}

完工~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末桦踊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子终畅,更是在濱河造成了極大的恐慌籍胯,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件离福,死亡現(xiàn)場(chǎng)離奇詭異杖狼,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)妖爷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)拒炎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)邑狸,“玉大人,你說(shuō)我怎么就攤上這事≈呵常” “怎么了膛薛?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵寂屏,是天一觀的道長(zhǎng)词顾。 經(jīng)常有香客問(wèn)我,道長(zhǎng)垃它,這世上最難降的妖魔是什么鲜屏? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任烹看,我火速辦了婚禮,結(jié)果婚禮上洛史,老公的妹妹穿的比我還像新娘惯殊。我一直安慰自己,他們只是感情好也殖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布土思。 她就那樣靜靜地躺著,像睡著了一般忆嗜。 火紅的嫁衣襯著肌膚如雪己儒。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,578評(píng)論 1 305
  • 那天捆毫,我揣著相機(jī)與錄音闪湾,去河邊找鬼。 笑死绩卤,一個(gè)胖子當(dāng)著我的面吹牛途样,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播濒憋,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼何暇,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了凛驮?” 一聲冷哼從身側(cè)響起赖晶,我...
    開(kāi)封第一講書(shū)人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辐烂,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體捂贿,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纠修,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了厂僧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扣草。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖颜屠,靈堂內(nèi)的尸體忽然破棺而出辰妙,到底是詐尸還是另有隱情,我是刑警寧澤甫窟,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布密浑,位于F島的核電站,受9級(jí)特大地震影響粗井,放射性物質(zhì)發(fā)生泄漏尔破。R本人自食惡果不足惜街图,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望懒构。 院中可真熱鬧餐济,春花似錦、人聲如沸胆剧。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)秩霍。三九已至篙悯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間前域,已是汗流浹背辕近。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留匿垄,地道東北人移宅。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像椿疗,于是被迫代替她去往敵國(guó)和親漏峰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355