springcloud如何做权限管理(springsecurity)

springcloud如何做权限管理(springsecurity+auth2)?

先看一张脉络图:
在这里插入图片描述
现在呢一步一步开始做:

第一步:配置zuul网关

在zuul网关里带上请求头,不做拦截

@Component
@Slf4j
public class AuthFilter extends ZuulFilter {

	/**
     * 具体的过滤逻辑
     * 本例中,检查请求的参数中是否传了token这个参数,如果没传,则请求不被路由到具体的服务实例,
     * 直接返回响应,状态码为401
     * @return
     */
	@Override
	public Object run() {
		//过滤器过滤
		System.out.println("………preHandle……………");

		RequestContext requestContext = RequestContext.getCurrentContext();
		HttpServletRequest request = requestContext.getRequest();
		String header = request.getHeader("Authorization");
		if (null != header && !"".equals(header)) {
			requestContext.addZuulRequestHeader("header", header);

		}
		return null;
	}

	 /**
     * 表示该过滤器是否过滤逻辑,如果是ture,则执行run()方法;如果是false,则不执行run()方法.
     * @return
     */
	@Override
	public boolean shouldFilter() {
		return true;
	}

	/**
     * 过滤顺序,值越小,越早执行该过滤器
     * @return
     */
	@Override
	public int filterOrder() {
		// 过滤的顺序
		return 0;
	}

	/**
     * Zuul有一下四种过滤器
     * "pre":是在请求路由到具体的服务之前执行,这种类型的过滤器可以做安全校验,例如身份校验,参数校验等
     * "routing":它用于将请`在这里插入代码片`求路由到具体的微服务实例,在默认情况下,它使用Http Client进行网络请求
     * "post":它是在请求已被路由到微服务后执行,一般情况下,用作收集统计信息,指标,以及将响应传输到客户端
     * "error":它是在其他过滤器发生错误时执行
     */
	@Override
	public String filterType() {
		return "pre";
	}

}

注意:requestContext.addZuulRequestHeader(“header”, header);这句需要避开敏感词汇,例如Authorization等。

第二步:配置具体微服务(两个微服务都差不多,这里以其中一个为例)

①导包:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

②写一个类WebSecurityConfig放开所有请求,因为导包后所有请求都不通过了。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
                authorizeRequests().
                antMatchers("/**").
                permitAll().
                anyRequest().
                authenticated().
                and().
                csrf().
                disable();

    }
}

③写拦截器配置类,放开部分不需要的拦截:

@Configuration
@EnableWebSecurity
public class InterceptorConfig extends WebMvcConfigurationSupport {
    @Autowired
    private JwtInterceptor jwtInterceptor;
    protected void addInterceptors(InterceptorRegistry registry) {
        //注册拦截器要声明拦截器对象和要拦截的请求
        System.out.println("进入InterceptorConfig类的addInterceptors方法!");
        registry.addInterceptor(jwtInterceptor)
                .addPathPatterns("/**").
                excludePathPatterns("/**/login/**").
                excludePathPatterns("/**/regist/**").
                excludePathPatterns("/**/captcha/**");
    }
}

④配置拦截器,做真正核心拦截内容

@Component
public class JwtInterceptor implements HandlerInterceptor {
    @Autowired
    private JwtUtil jwtUtil;
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("………preHandle……………");
        //拦截器只是负责把头请求头中包含token的令牌进行一个解析验证。
        if (null == request ||
                null == request.getHeader("header") ||
                !request.getHeader("header").startsWith("Bearer ")) {
            outPutErrorResult(response);
            return false;

        }
        String token = request.getHeader("header").substring(7);
        System.out.println("token:" + token);
        if (StringUtils.isEmpty(token)) {
            outPutErrorResult(response);
            return false;
        }
        try {
            Claims claims = jwtUtil.parseJwt(token);
        } catch (Exception e) {
            e.printStackTrace();
            outPutErrorResult(response);
            return false;
        }

        return true;
    }

    public void outPutErrorResult(HttpServletResponse response) {
        ServletOutputStream output = null;
        try {
            output = response.getOutputStream();
            output.write(("{\"status\":\"error\",\"msg\":\"请登录账号@!\",\"code\":\"500\"}").getBytes());
            output.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != output) {
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

这里需要指出,
Claims claims = jwtUtil.parseJwt(token);
之所以可以这么判断token,是因为这里的token生成方式是采用jjwt方式生成的,所以可以按此方式解析。
参看token生成方法:
导包:

<dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>
  public String createJWT(String id, String subject, String roles) {
        long nowMinius = System.currentTimeMillis();
        JwtBuilder builder = Jwts.
                builder().setId(id).
                setSubject(subject).
                setIssuedAt(new Date()).
                signWith(SignatureAlgorithm.HS256, key).claim("roles", roles);
        if (ttl > 0) {
            builder.setExpiration(new Date(nowMinius + ttl));
        }
        return builder.compact();
    }

    public void setTtl(long ttl) {
        this.ttl = ttl;
    }

    /**
     * 解析JWT
     *
     * @param jwtStr
     * @return
     */
    public Claims parseJwt(String jwtStr) {
        return Jwts.parser().setSigningKey(key).parseClaimsJws(jwtStr).getBody();
    }
第三步:写一个类SecuringRequestInterceptor,在微服务相互调用时带上请求头,要不然会被拦截(每个业务微服务都要写)。
@Component
public class SecuringRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        获取上一个请求保存的RequestAttributes,能获取到当前的HttpServletRequest
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        //获取request域
        HttpServletRequest request = attributes.getRequest();
        //获取头部信息
        Enumeration<String> headerNames = request.getHeaderNames();
        //把头部信息里面的信息装进去requestTemplate
        if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                String name = headerNames.nextElement();
                System.out.println("name:"+name);
                String values = request.getHeader(name);
                System.out.println("values:"+values);
                requestTemplate.header(name, values);
            }
        }
    }
}

到这里基本没问题了,

第四步 再写一个抽象类AbstractController.java方便其他类使用用户名用户id用户角色等内容。(非必须)
 @Autowired
    protected HttpServletRequest request;
    @Autowired
    private JwtUtil jwtUtil;
    
public abstract class AbstractController {

    @Autowired
    protected HttpServletRequest request;
    @Autowired
    private JwtUtil jwtUtil;

    public SysLogUserVo UserInfo(){
        SysLogUserVo svuv = new SysLogUserVo();
        String header = request.getHeader("header");
        String token = header.substring(7);
        try {
            Claims claims = jwtUtil.parseJwt(token);
            svuv.setAccounts(claims.getSubject());
            svuv.setId(Integer.parseInt(claims.getId()));
            svuv.setRole_name((String) claims.get("roles"));

        } catch (Exception e) {
            e.printStackTrace();
        }
        return svuv;
    }
}

其他类想获取用户信息只需继承这个类就可以了

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SpringSecuritySpringCloud是两个独立的框架,但它们可以一起使用来构建安全的分布式系统SpringSecurity是一个用于身份验证和授权的框架,可以帮助我们保护应用程序的安全性。而SpringCloud是一个用于构建分布式系统的框架,它提供了一系列的工具和组件,用于处理分布式系统的各种问题,例如服务发现、负载均衡、配置管理等。 在引用[1]提到的文章,作者介绍了他对SpringSecurity的深入研究和源码分析的经历。他从最初只会简单接入SpringSecurity,到深入了解整个体系,深入源码,逐步提升了自己的技能。这也说明了SpringSecurity的重要性和价值。 在引用[2]提到了SpringSecurity OAuth2的默认过滤器链和自定义过滤器链。默认的过滤器链只处理特定的请求,而自定义的过滤器链则处理其他请求。需要注意的是,自定义过滤器并没有解析Token的过滤器,这可能导致即使加了Token,权限满足的情况下,仍然返回403未授权的错误。在SpringSecurity OAuth2体系SpringSecurity主要负责授权操作,而认证操作通常由资源服务器处理。 在引用[3]提到了整合SpringCloudSpringSecurity OAuth2的搭建流程。作者通过这篇文章梳理了整个流程,帮助读者理清思路。这对于那些想要构建安全的分布式系统的开发者来说是非常有价值的。 综上所述,SpringSecuritySpringCloud是两个独立的框架,但可以一起使用来构建安全的分布式系统SpringSecurity负责身份验证和授权,而SpringCloud提供了一系列工具和组件来处理分布式系统的各种问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神雕大侠mu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值