spring boot security jwt

image.png
<dependencies>
     <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
        </dependency>
        <!-- jwt  json web token -->
        <dependency>
          <groupId>io.jsonwebtoken</groupId>
          <artifactId>jjwt</artifactId>
          <version>0.7.0</version>
        </dependency>
        <!-- spring boot security -->
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
            <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
<dependencies>
package cn.etstone.evm.configuration.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.authentication.UsernamePasswordAuthenticationFilter;

import cn.etstone.evm.configuration.jwt.JWTAuthenticationFilter;
import cn.etstone.evm.configuration.jwt.JWTLoginFilter;


@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 允许进入页面方法前检验
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private static final Logger LOGGER = LoggerFactory.getLogger(WebSecurityConfig.class);
    
    @Autowired
    private SecurityAuthenticationProvider securityAuthenticationProvider;
    
//  @Autowired
//  private AuthSuccessHandler authSuccessHandler;//登录成功跳转页面
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        LOGGER.debug("WebSecurityConfig.configure(HttpSecurity http)");
        http
            .exceptionHandling().accessDeniedPage("/error/403").and()
            .anonymous().and()
            .servletApi().and()
            .headers().cacheControl()
            .and().and()
            .authorizeRequests().antMatchers("/favicon.ico","/static/plugins/**","/static/css/**",
                        "/static/fonts/**","/static/login/**","/login").permitAll()
            
//          .antMatchers(HttpMethod.POST, "/login").permitAll() // 所有 /login 的POST请求 都放行
            
                .anyRequest().authenticated() //所有其他请求需要进行身份验证
            .and()
                .formLogin() // 基于 Form
                .loginPage("/login").permitAll()// 表单登录验证
                .and().logout().permitAll()
                
            .and()
                // 由于使用的是JWT,我们这里不需要csrf
                .csrf().disable().sessionManagement()
                // 基于token,所以不需要session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);    
            // 禁用缓存
            http.headers().cacheControl();
            
            http
                // 添加一个过滤器 所有访问 /login 的请求交给 JWTLoginFilter 来处理 这个类处理所有的JWT相关内容
                .addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),UsernamePasswordAuthenticationFilter.class)
                // 添加一个过滤器验证其他请求的Token是否合法
                .addFilterBefore(new JWTAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);
    }
    
     // 使用自定义身份验证组件
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        LOGGER.debug("使用自定义身份验证组件WebSecurityConfig.configure(AuthenticationManagerBuilder auth)");
        auth.authenticationProvider(securityAuthenticationProvider);
    }

}
package cn.etstone.evm.configuration.security;

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

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import cn.etstone.evm.navigation.mapper.NavigationMapper;
import cn.etstone.evm.system.entity.NavigationDTO;
import cn.etstone.evm.system.entity.RoleNavigationDTO;
import cn.etstone.evm.system.entity.UserRoleNavigationInfo;
import cn.etstone.evm.system.mapper.UserRoleMapper;

@Service
public class SecurityAuthenticationProvider implements AuthenticationProvider { //自定义UserDetailsService 接口
    
    private static final Logger LOGGER = LoggerFactory.getLogger(SecurityAuthenticationProvider.class);

    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private NavigationMapper navigationMapper;
    
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        if(authentication == null || StringUtils.isBlank(authentication.getName()) || StringUtils.isBlank((String)authentication.getCredentials())){
            return null;
        }
        
        LOGGER.debug("authentication:{}",authentication);
        
        String username = authentication.getName();
        LOGGER.debug("authentication.getName();:{}",authentication.getName());
        String password = (String) authentication.getCredentials();
        LOGGER.debug("password:{}",password);
        
        UserRoleNavigationInfo userRoleInfo = userRoleMapper.findLoginName(username);
        LOGGER.debug("userRoleInfo:{}",userRoleInfo);
        
        List<NavigationDTO> findAllNavigationDTO = navigationMapper.findAllNavigationDTO();
        LOGGER.debug("findAllNavigationDTO:{}",findAllNavigationDTO);
        
        if(userRoleInfo == null){
            LOGGER.debug("账户不存在userRoleInfo:{} ",userRoleInfo);
            throw new UsernameNotFoundException("账户不存在");
        }
        
        if(!userRoleInfo.getUserPassword().equals(password)){
            LOGGER.debug("密码错误userRoleInfo:{} ",userRoleInfo);
            throw new UsernameNotFoundException("密码错误");
        }
        
        if(userRoleInfo.getUserState().equalsIgnoreCase("DISABLE")){
            LOGGER.debug("用户没启用userRoleInfo:{} ",userRoleInfo);
            throw new UsernameNotFoundException("用户没启用");
        }
        
        List<RoleNavigationDTO> roleNavigationDTOs = userRoleInfo.getRoleNavigationDTOs();
        if(roleNavigationDTOs == null || roleNavigationDTOs.isEmpty()){
            LOGGER.debug("用户没权限userRoleInfo:{} ",userRoleInfo);
            throw new UsernameNotFoundException("用户没权限");
        }
        
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        for (RoleNavigationDTO roleNavigationDTO : roleNavigationDTOs) {
            List<NavigationDTO> navigationDTOs = roleNavigationDTO.getNavigationDTOs();
            if(navigationDTOs == null || navigationDTOs.isEmpty()){
                LOGGER.debug("用户绑定访问权限为空userRoleInfo:{} ",userRoleInfo);
                throw new UsernameNotFoundException("用户绑定访问权限为空");
            }
            for (NavigationDTO navigationDTO : navigationDTOs) {
                if(navigationDTO.getNaviPId() == 0){
                    String roleName = "ROLE_" + navigationDTO.getNaviName();
                    authorities.add(new SimpleGrantedAuthority(roleName));
                }else{
                    for (NavigationDTO navigation : findAllNavigationDTO) {
                        if(navigationDTO.getNaviPId() == navigation.getNaviId()){
                            String roleName = "ROLE_" + navigation.getNaviName() + "." + navigationDTO.getNaviName();
                            authorities.add(new SimpleGrantedAuthority(roleName));
                        }
                    } 
                }
            }
            
        }
        
//      System.err.println(authorities);
        LOGGER.debug("登录成功");
        return new UsernamePasswordAuthenticationToken(userRoleInfo.getLoginName(),userRoleInfo.getUserPassword(), authorities);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
    
    
}
package cn.etstone.evm.configuration.jwt;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import cn.etstone.evm.configuration.EVMApplicationContext;
/**
 * 最先进入验证
 * @author feng
 *
 */
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {

    private static final Logger LOGGER = LoggerFactory.getLogger(JWTLoginFilter.class);
    
    public JWTLoginFilter(String url, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(url));
        LOGGER.debug("JWTLoginFilter.JWTLoginFilter(String url, AuthenticationManager authManager) ");
        setAuthenticationManager(authManager);
    }

    // 登录时需要验证时候调用
    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
            throws AuthenticationException, IOException, ServletException {
        LOGGER.debug("登录时需要验证时候调用JWTLoginFilter.attemptAuthentication(HttpServletRequest req, HttpServletResponse res)");
        String loginName = req.getParameter("username");
        String password = req.getParameter("password");
        LOGGER.debug("username:{};password:{}",loginName,password);
        if(StringUtils.isBlank(loginName) || StringUtils.isBlank(password)){
            LOGGER.warn("登录时需要验证时候调用:{}未获取到登录名或密码",loginName,password);
            String json = JSONResult.fillResultString(401, "没有登录名或密码", JSONObject.NULL);
            res.setCharacterEncoding("UTF-8");
            res.setContentType("application/json;charset=UTF-8");
            res.setStatus(HttpServletResponse.SC_OK);
            res.getOutputStream()
                    .write(json.getBytes("UTF-8"));
            return null;
        }
//      // 返回一个验证令牌
        return getAuthenticationManager()
                .authenticate(new UsernamePasswordAuthenticationToken(loginName, password));
    }

    // 登录验证成功后调用
    @Override
    protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
            Authentication auth) throws IOException, ServletException {
        LOGGER.debug("登录验证成功后调用JWTLoginFilter.successfulAuthentication:{},生成token");
        TokenAuthenticationService tokenAuthenticationService = EVMApplicationContext.getApplicationContext().getBean(TokenAuthenticationService.class);
        tokenAuthenticationService.createJWT(res, auth);
    }

    // 登录验证失败后调用,这里直接灌入500错误返回,由于同一JSON返回,HTTP就都返回200了
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException failed) throws IOException, ServletException {
        LOGGER.debug("登录验证失败后调用JWTLoginFilter.unsuccessfulAuthentication");
        String json = JSONResult.fillResultString(401, failed.getLocalizedMessage(), JSONObject.NULL);
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_OK);
        response.getOutputStream()
                .write(json.getBytes("UTF-8"));
    }

}
package cn.etstone.evm.configuration.jwt;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.GenericFilterBean;

import cn.etstone.evm.configuration.EVMApplicationContext;

/**
 * 登录之后验证
 * @author feng
 *
 */
public class JWTAuthenticationFilter extends GenericFilterBean {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {
        LOGGER.debug("登录后验证令牌");
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse)response;
        System.err.println("Evm-Authorization");
        String header = req.getHeader("Evm-Authorization");
        LOGGER.debug("登录后验证令牌TOKEN:{}",header);
        if(StringUtils.isBlank(header)){
            LOGGER.debug("登录后验证令牌TOKEN有误:{}",header);
            String json = JSONResult.fillResultString(401, "令牌错误或失效", JSONObject.NULL);
            resp.setCharacterEncoding("UTF-8");
            resp.setContentType("application/json;charset=UTF-8");
            resp.setStatus(HttpServletResponse.SC_OK);
            resp.getOutputStream()
                    .write(json.getBytes("UTF-8"));
            resp.getOutputStream().flush();
            resp.getOutputStream().close();
            return;
        }
        
        TokenAuthenticationService tokenAuthenticationService = EVMApplicationContext.getApplicationContext().getBean(TokenAuthenticationService.class);
        Authentication authentication = tokenAuthenticationService.parseJWT(header);
        LOGGER.debug("登录后验证令牌TOKEN解析为:{}",authentication);
        if(authentication == null){
            LOGGER.warn("登录后验证令牌TOKEN错误或失效",authentication);
            String json = JSONResult.fillResultString(401, "令牌错误或失效", JSONObject.NULL);
            resp.setCharacterEncoding("UTF-8");
            resp.setContentType("application/json;charset=UTF-8");
            resp.setStatus(HttpServletResponse.SC_OK);
            resp.getOutputStream()
                    .write(json.getBytes("UTF-8"));
            resp.getOutputStream().flush();
            resp.getOutputStream().close();
            return;
        }
        
        
        SecurityContextHolder.getContext().setAuthentication(authentication);
        resp.addHeader("Evm-Authorization", header);
        LOGGER.debug("验证令牌TOKEN成功,验证令牌TOKEN重新返回客户端");
        filterChain.doFilter(request, response);
    }
}
package cn.etstone.evm.configuration.jwt;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.security.sasl.AuthenticationException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
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.Service;

import cn.etstone.evm.configuration.properties.TokenPropertie;
import cn.etstone.evm.navigation.mapper.NavigationMapper;
import cn.etstone.evm.system.entity.NavigationDTO;
import cn.etstone.evm.system.entity.RoleNavigationDTO;
import cn.etstone.evm.system.entity.UserRoleNavigationInfo;
import cn.etstone.evm.system.mapper.UserRoleMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

/**
 * 添加构造jwt及解析jwt的帮助类JwtHelper.java
 * 
 * @author feng
 *
 */
@Service
public class TokenAuthenticationService {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(TokenAuthenticationService.class);

    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private NavigationMapper navigationMapper;
    @Autowired
    private TokenPropertie tokenPropertie;
    
    
    /**
     * 解析jwt 获取登录名
     * 
     * @param jsonWebToken
     * @return
     * @throws ServletException
     * @throws AuthenticationException
     */
    @Cacheable(value="system", keyGenerator="evmKeyGenerator")
    public  Authentication parseJWT(String jsonWebToken) {
        LOGGER.debug("解析jwt:{}",jsonWebToken);
        if (jsonWebToken == null || jsonWebToken.isEmpty()) {
            return null;
        }
        try {
            Claims claims = null;
            claims = Jwts.parser().setSigningKey(tokenPropertie.getSecret()) // 验签
                    .parseClaimsJws(jsonWebToken).getBody();
            if ("EVM".equals(claims.getIssuer())) {
                String loginName = claims.getAudience();
                LOGGER.debug("解析jwt成功获取登录名:{}",loginName);
                if(StringUtils.isBlank(loginName)){
                    LOGGER.debug("解析jwt未获取到登录名");
                    return null;
                }
                UserRoleNavigationInfo userRoleNavigationInfo = userRoleMapper.findLoginName(loginName);
                if(userRoleNavigationInfo == null){
                    LOGGER.debug("解析jwt未找到用户");
                    return null;
                }
                List<NavigationDTO> findAllNavigationDTO = navigationMapper.findAllNavigationDTO();//获取全部权限
                List<RoleNavigationDTO> roleNavigationDTOs = userRoleNavigationInfo.getRoleNavigationDTOs();
                if(roleNavigationDTOs == null || roleNavigationDTOs.isEmpty()){
                    LOGGER.debug("解析jwt未找到用户权限");
                    return null;
                }
                
                List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
                for (RoleNavigationDTO roleNavigationDTO : roleNavigationDTOs) {
                    List<NavigationDTO> navigationDTOs = roleNavigationDTO.getNavigationDTOs();
                    if(navigationDTOs == null || navigationDTOs.isEmpty()){
                        LOGGER.debug("解析jwt未找到用户权限");
                        return null;
                    }
                    for (NavigationDTO navigationDTO : navigationDTOs) {
                        if(navigationDTO.getNaviPId() == 0){
                            String roleName = "ROLE_" + navigationDTO.getNaviName();
                            authorities.add(new SimpleGrantedAuthority(roleName));
                        }else{
                            for (NavigationDTO navigation : findAllNavigationDTO) {
                                if(navigationDTO.getNaviPId() == navigation.getNaviId()){
                                    String roleName = "ROLE_" + navigation.getNaviName() + "." + navigationDTO.getNaviName();
                                    authorities.add(new SimpleGrantedAuthority(roleName));
                                }
                            } 
                        }
                    }
                    
                }
                LOGGER.debug("解析jwt令牌成功登录名:{},权限:{}",loginName,authorities);
                return loginName != null ? new UsernamePasswordAuthenticationToken(loginName, null, authorities) : null;
            } else {
                LOGGER.warn("解析jwt令牌错误失败");
                return null;
            }
        } catch (Exception e) {
            LOGGER.warn("解析jwt失败:{}");
            return null;
        }
    }

    /**
     * 生成jwt
     * 
     * @param authentication
     * @return
     */
    public void createJWT(HttpServletResponse response, Authentication authentication) {
        // 权限
        /*  Collection<? extends GrantedAuthority> authorities =
          authentication.getAuthorities(); List<String> roles = new
          ArrayList<String>(); 
          for (GrantedAuthority grantedAuthority : authorities)
          { roles.add(grantedAuthority.getAuthority()); }*/
          
        // 生成JWT
        LOGGER.debug("生成jwt authentication:{}",authentication);
        String jwt = Jwts.builder().setId(UUID.randomUUID().toString()) // ID
                .setIssuer(tokenPropertie.getIssuer()) // 发布者
                .setAudience(authentication.getName()) // 用户名
                // .claim("roles", roles) // 权限
                .setExpiration(new Date(tokenPropertie.getExpirationtime())) // 有效期设置
                .signWith(SignatureAlgorithm.HS256, tokenPropertie.getSecret()).compact(); // 签名设置
        LOGGER.debug("生成jwt jwt成功:{}",jwt);
        try {
            response.setContentType("application/json");
            response.setStatus(HttpServletResponse.SC_OK);
            response.getOutputStream().println(JSONResult.fillResultString(0, "", jwt));
            response.getOutputStream().flush();
            response.getOutputStream().close();
        } catch (IOException e) {
            e.printStackTrace();
        }

//      return jwt;
    }
}
package cn.etstone.evm.configuration.jwt;

import org.json.JSONObject;

public class JSONResult {
    public static String fillResultString(Integer status, String message, Object result){
        JSONObject jsonObject = new JSONObject(){{
            put("status", status);
            put("message", message);
            put("result", result);
        }};
        return jsonObject.toString();
    }
}
package cn.etstone.evm.configuration;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class EVMApplicationContext implements ApplicationContextAware {
    
    private static ApplicationContext applicationContext = null;

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        EVMApplicationContext.applicationContext = applicationContext;
    }

}
package cn.etstone.evm.interceptor;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;

import com.google.gson.Gson;

import cn.etstone.evm.common.BizException;
import cn.etstone.evm.configuration.jwt.JSONResult;
import cn.etstone.evm.status.entity.Status;
import cn.etstone.evm.status.enums.BizCode;

/**
 * 异常拦截<br/>
 * 拦截所有未处理的异常
 * @author cpc
 *
 */
@RestControllerAdvice
public class ExceptionInterceptor {

    private static final Logger LOG = LoggerFactory.getLogger(ExceptionInterceptor.class);
    private static final Gson GSON = new Gson();
    
    private static final BizCode DEFAULT_CODE = BizCode.SERVER_EXCEPTION;
    
    private static final String DEFAULT_ERROR_PAGE = "/500";

    @Autowired
    private MessageSource messageSource;
    
    /**
     * 异常处理器
     */
    @ExceptionHandler(value={Exception.class})
    public ModelAndView exceptionHandler(Exception exception, WebRequest request){
        LOG.error("捕获到未处理异常, 异常: {}, {}, {}", exception.getMessage(), request.getContextPath(), request.getDescription(true));
        if(LOG.isDebugEnabled()){
            exception.printStackTrace();
        }
        
        String messageCode = String.format("%s.%s", DEFAULT_CODE.getPrefix(), DEFAULT_CODE.getMessage());
        String message = this.messageSource.getMessage(messageCode, null, null, LocaleContextHolder.getLocale());
        ModelAndView errorView = new ModelAndView("redirect:" + DEFAULT_ERROR_PAGE);
        errorView.addObject("message", message);
        return errorView;
    }
    
    @ExceptionHandler(value={AccessDeniedException.class})
    public void accessDeniedExceptionHandler(Exception exception, WebRequest request, HttpServletResponse response) throws Exception, IOException{
        LOG.error("未授权...");
        LOG.error("捕获到未处理异常, 异常: {}", exception.getMessage());
        if(LOG.isDebugEnabled()){
//          exception.printStackTrace();
        }
        response.setContentType("application/json;charset=UTF-8");
        String json = JSONResult.fillResultString(302, "权限不够", JSONObject.NULL);
        response.getOutputStream()
        .write(json.getBytes("UTF-8"));
        response.flushBuffer();
    }
    
    
    /**
     * 自定义BizException异常处理器
     * @throws IOException 
     */
    @ExceptionHandler(value={BizException.class})
    public void bizExceptionHandler(Exception exception, HttpServletRequest request, HttpServletResponse response) throws IOException{
        if(LOG.isDebugEnabled()){
            exception.printStackTrace();
        }
        BizException bizException = (BizException)exception;
        int code = bizException.getCode();
        Optional<BizCode> bizCode = BizCode.of(code);
        String message = null;
        if(bizCode.isPresent()){
            String messageCode = String.format("%s.%s", bizCode.get().getPrefix(), bizCode.get().getMessage());
            message = this.messageSource.getMessage(messageCode, null, null, LocaleContextHolder.getLocale());
        }
        
        if(message == null){
            LOG.error("自定义BizException异常处理器: 未找到异常信息中的BizCode信息. 使用默认BizCode: {}", DEFAULT_CODE);
            String messageCode = String.format("%s.%s", DEFAULT_CODE.getPrefix(), DEFAULT_CODE.getMessage());
            message = this.messageSource.getMessage(messageCode, null, null, LocaleContextHolder.getLocale());
            if(message == null){
                LOG.error("自定义BizException异常处理器: 未找到默认BizCode信息. 默认BizCode: {}", DEFAULT_CODE);
                message = "";
            }
        }
        
        Status<Object> status = new Status<Object>(HttpStatus.OK, code, message, null);
        LOG.debug("自定义BizException异常处理器: {}", status);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(GSON.toJson(status));
        response.flushBuffer();
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,841评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,415评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,904评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,051评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,055评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,255评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,729评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,377评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,517评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,420评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,467评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,144评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,735评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,812评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,029评论 1 256
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,528评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,126评论 2 341

推荐阅读更多精彩内容