把其中一个服务端,进行用户权限控制的案例步骤:
1.添加相关依赖jar
<!--权限控制-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
2.把公钥文件放进数据配置包
3.把用户权限控制的配置类复制进去
ResourceServerConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
/**
* @author Administrator
* @version 1.0
**/
@Configuration
@EnableResourceServer
//激活方法上的PreAuthorize注解
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
//公钥
private static final String PUBLIC_KEY = "publickey.txt";
//定义JwtTokenStore,使用jwt令牌
@Bean
public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {
return new JwtTokenStore(jwtAccessTokenConverter);
}
//定义JJwtAccessTokenConverter,使用jwt令牌
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setVerifierKey(getPubKey());
return converter;
}
/**
* 获取非对称加密公钥 Key
* @return 公钥 Key
*/
private String getPubKey() {
Resource resource = new ClassPathResource(PUBLIC_KEY);
try {
InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream());
BufferedReader br = new BufferedReader(inputStreamReader);
return br.lines().collect(Collectors.joining("\n"));
} catch (IOException ioe) {
return null;
}
}
//Http安全配置,对每个到达系统的http请求链接进行校验
@Override
public void configure(HttpSecurity http) throws Exception {
//所有请求必须认证通过
http.authorizeRequests()
//下边的路径放行
.antMatchers("/v2/api-docs", "/swagger-resources/configuration/ui",
"/swagger-resources","/swagger-resources/configuration/security",
"/swagger-ui.html","/webjars/**").permitAll()
.anyRequest().authenticated();
}
}
4.再要进行权限控制的方法上,加注解:
//当用户拥有course_teachplan_list权限时候方可访问此方法
@PreAuthorize("hasAuthority('course_teachplan_list')")
再我们自定义的项目总异常中,再次自定义一个,其中微服务的单个异常
import com.xuecheng.framework.exception.ExceptionCatch;
import com.xuecheng.framework.model.response.CommonCode;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
/**课程管理自定义的异常类,其中定义异常类型所对应的错误代码
* @author Administrator
* @version 1.0
**/
@ControllerAdvice//控制器增强
//这个自定义异常类,继承于,我们自定义的总异常ExceptionCatch
public class CustomExceptionCatch extends ExceptionCatch {
static {
//只要这个异常类,有触发,就捕获这个异常,并返回权限不足的代码
builder.put(AccessDeniedException.class, CommonCode.UNAUTHORISE);
}
}
自定义的总异常:
import com.google.common.collect.ImmutableMap;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.model.response.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 统一异常捕获类
* @author Administrator
* @version 1.0
* @create 2018-09-14 17:32
**/
@ControllerAdvice//控制器增强,springAOP的切面功能
public class ExceptionCatch {
// 产生异常,让日志类,接收异常情况
private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);
//定义map,配置异常类型所对应的错误代码
private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;
//定义map的builder对象,去构建ImmutableMap
protected static ImmutableMap.Builder<Class<? extends Throwable>,ResultCode> builder = ImmutableMap.builder();
//捕获CustomException此类异常
@ExceptionHandler(CustomException.class)
//想异常通过JSON的格式响应回去
@ResponseBody
public ResponseResult customException(CustomException customException){
//记录日志
LOGGER.error("catch exception:{}",customException.getMessage());
//把捕获到的异常代码,通过规范响应回去
ResultCode resultCode = customException.getResultCode();
return new ResponseResult(resultCode);
}
//捕获Exception此类异常
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseResult exception(Exception exception){
//记录日志
LOGGER.error("catch exception:{}",exception.getMessage());
//先判断,预定异常集合中有没有,预定异常数据
if(EXCEPTIONS == null){
//没有异常数据,就构建异常数据进入map
EXCEPTIONS = builder.build();//EXCEPTIONS构建成功
}
//从EXCEPTIONS中找异常类型所对应的错误代码,如果找到了将错误代码响应给用户,如果找不到给用户响应99999异常
ResultCode resultCode = EXCEPTIONS.get(exception.getClass());
if(resultCode !=null){
//返回找到的异常代码
return new ResponseResult(resultCode);
}else{
//返回99999异常,也就是超出预定范围的异常
return new ResponseResult(CommonCode.SERVER_ERROR);
}
}
static {
//定义异常类型所对应的错误代码详情
builder.put(HttpMessageNotReadableException.class,CommonCode.INVALID_PARAM);
}
}