.antMatchers("/**").access("#oauth2.hasScope('scope1')")
上面这行代码,只是控制大范围的访问权限,具体到方法级的访问 还得看permission
以上教程代码顺序如下:
网关服务:
1.application.properties
#zuul不传递cookie和head信息
#方法1:这个设置是开启全局的cookie和head传递
zuul.sensitive-headers=
2.application.yml
server:
port: 5001
spring:
application:
name: zuul
cloud:
client:
ipAddress: 127.0.0.1
eureka:
instance:
prefer-ip-address: false
instance-id: ${spring.cloud.client.ipAddress}:${server.port}
hostname: ${spring.cloud.client.ipAddress}
client:
serviceUrl:
#eurekaServers
defaultZone: http://127.0.0.1:2001/eureka
zuul:
routes:
authorization_server: /uaa/**
order_server: /order/**
sensitive-headers:
3.网关资源服务:
/**
* 网关资源类
*/
@Configuration
public class ResourceServerConfig {
public static final String RESOURCE_ID="res1";
//1 uaa认证授权服务资源 配置
@Configuration
@EnableResourceServer
public class UAAServerConfig extends ResourceServerConfigurerAdapter{
@Autowired
private TokenStore tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources
//设置我这个resource的id
.resourceId(RESOURCE\_ID)
.tokenStore(tokenStore)
//这个貌似是配置要不要把token信息记录在session中
.stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/uaa/\*\*").permitAll();//放行所有授权验证请求
}
}
//2 order\_server……等等微服务资源
@Configuration
@EnableResourceServer
public class orderServerConfig extends ResourceServerConfigurerAdapter{
@Autowired
private TokenStore tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources
.resourceId(RESOURCE\_ID)
.tokenStore(tokenStore)
.stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//本项目所需要的授权范围,这个scope是写在auth服务的配置里的
.antMatchers("/order/\*\*").access("#oauth2.hasScope('scope1')");
}
}
}
TokenConfig
@Configuration
public class TokenConfig {
//配置如何把普通token转换成jwt token
@Bean
public JwtAccessTokenConverter tokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
//使用对称秘钥加密token,resource那边会用这个秘钥校验token
converter.setSigningKey("uaa123");
return converter;
}
//配置token的存储方法
@Bean
public TokenStore tokenStore() {
//把用户信息都存储在token当中,相当于存储在客户端,性能好很多
return new JwtTokenStore(tokenConverter());
}
}
网关约束WebSecurityConfig
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/\*\*").permitAll();
// .and()
// .formLogin()
// .and()
// .logout();
}
@Override
@Bean
public UserDetailsService userDetailsService() {
/\*\*
\* 基于内存创建用户
\*/
InMemoryUserDetailsManager manager=new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("zhangsan").password(passwordEncoder().encode("123")).authorities("admin").build());
manager.createUser(User.withUsername("lisi").password(passwordEncoder().encode("123")).authorities("user").build());
return manager;
}
}
配置网关过滤器ZuulConfig、AuthFilter
/**
* @Autor zhangjiawen
* @Date: 2020/5/29 9:56
*/
@Configuration
public class ZuulConfig {
@Bean
public AuthFilter preAuthFilter(){
return new AuthFilter();
}
@Bean
public FilterRegistrationBean corsFilter(){
final UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource();
final CorsConfiguration config=new CorsConfiguration();
config.setAllowCredentials(true);
List<String> ruleList=new ArrayList<>();
ruleList.add("\*");
config.setAllowedOrigins(ruleList);
config.setAllowedHeaders(ruleList);
config.setAllowedMethods(ruleList);
config.setMaxAge(1800L);
source.registerCorsConfiguration("/\*\*",config);
CorsFilter corsFilter=new CorsFilter(source);
FilterRegistrationBean bean=new FilterRegistrationBean(corsFilter);
bean.setOrder(Ordered.HIGHEST\_PRECEDENCE);
return bean;
}
}
@Slf4j
public class AuthFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";//表示请求之前拦截
}
@Override
public int filterOrder() {
return -1;
}
@Override
public boolean shouldFilter() {
return true;//如果想要过滤器生效必须改成true
}
/\*\*
\* 转发解析token
\* @return
\* @throws ZuulException
\*/
@Override
public Object run() throws ZuulException {
//1获取当前用户身份信息
RequestContext ctx=RequestContext.getCurrentContext();
//从上下文拿到身份对象
Authentication authentication= SecurityContextHolder.getContext().getAuthentication();
if(!(authentication instanceof OAuth2Authentication)){
log.error("-----!(authentication instanceof OAuth2Authentication)");
return null;//如果不是oauth2.0格式的对象 直接返回;
}
OAuth2Authentication oAuth2Authentication=(OAuth2Authentication) authentication;
Authentication userAuthentication = oAuth2Authentication.getUserAuthentication();
//取出用户身份
String principal = userAuthentication.getName();
//2获取当前用户权限信息
List<String> authorities=new ArrayList<>();
//采用stream流的方式遍历
userAuthentication.getAuthorities().stream().forEach(c-> authorities.add(c.getAuthority()));
//将原请求参数重新放回
OAuth2Request oAuth2Request = oAuth2Authentication.getOAuth2Request();
Map<String, String> requestParameters = oAuth2Request.getRequestParameters();
Map<String, Object> jsonToken =new HashMap<>(requestParameters);
//3把用户身份权限信息放入json,存入http的header中
if(userAuthentication!=null){
jsonToken.put("principal",principal);
jsonToken.put("authorities",authorities);
}
ctx.addZuulRequestHeader("json-token", Base64.encode(JSON.toJSONString(jsonToken)));
//4转发给微服务
return null;
}
}
授权服务uaa:
资源order服务:
用户权限过滤器TokenAuthenticationFilter
/
* @Autor zhangjiawen
* @Date: 2020/5/29 10:16
*/
@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//解析出头中的token
String token = request.getHeader("json-token");
if(!StringUtils.isEmpty(token)){
String json= Base64.decodeStr(token);
//将token转成json对象
JSONObject jsonObject= JSON.parseObject(json);
//获取身份信息
String principal = jsonObject.getString("principal");
UserDTO userDTO=new UserDTO();
userDTO.setUsername(principal);
//获取权限信息
JSONArray authoritiesArray = jsonObject.getJSONArray("authorities");
String\[\] authorities=authoritiesArray.toArray(new String\[authoritiesArray.size()\]);
//将用户身份权限信息填充到用户token对象中
UsernamePasswordAuthenticationToken authenticationToken
=new UsernamePasswordAuthenticationToken(userDTO,null, AuthorityUtils.createAuthorityList(authorities));
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
//将authenticationToken填充到安全上下文
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
filterChain.doFilter(request,response);
}
}
}
所有项目源码本人结合网友提供的代码整理了最后一部分 分布式的权限控制 参考:
https://gitee.com/jiawenzhang/Oauth-cloud
感谢哔哩哔哩提供的视频,地址:https://www.bilibili.com/video/BV1VE411h7aL?p=45
测试效果:
将用户信息转成json对象放到username中
手机扫一扫
移动阅读更方便
你可能感兴趣的文章