从零开始,手打一个权限管理系统(第十六章 认证与拦截)

从零开始,手打一个权限管理系统(第十六章 认证与拦截)

第十六章 认证与拦截


前言

认证拦截还是跟之前单机版的一样,代码没多少不一样的地方,唯一有点区别的就是引入了feign来查询用户信息。


一、远程服务调用Feign

  1. auth/pom.xm引入依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-openfeign</artifactId>
 </dependency>
  1. 定义远程服务调用接口
@FeignClient(contextId = "feignUpmsService", value = ServiceNameConstants.UMPS_API_SERVICE)
public interface FeignUpmsService {
    /**
     * 通过用户名查询用户、角色信息
     * @param username 用户名
     * @return R
     */
    @GetMapping(value = "/user/getInfo/{username}")
    Result<JwtUserDTO> getInfo(@PathVariable("username") String username);

}
  1. 开启Fegin
@SpringBootApplication
@EnableFeignClients("com.ailot.cloud.auth.feign")
public class ServiceAuthApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceAuthApplication.class, args);
    }
}

二、配置普通服务的拦截规则

之前我们讲过我们的权限拦截是放到每个服务的,所以还需要配置一个针对每个服务的安全配置类,这个安全配置类跟service-auth服务的大同小异,只不过只有会话拦截的功能。

  1. 在不配置的情况下访问第三方服务接口,会重定向到此界面
    在这里插入图片描述
  2. 配置后访问第三方服务接口
    在这里插入图片描述
  3. 第三方接口加白名单后访问
    在这里插入图片描述
    在这里插入图片描述
  4. 安全配置代码

/**
 * 普通服务的安全配置
 */
@Configuration
@EnableConfigurationProperties({PermitUrlProperties.class})
public class SpringSecurityServiceConfigurer {


    private final PermitUrlProperties permitUrlProperties;

    public SpringSecurityServiceConfigurer(PermitUrlProperties permitUrlProperties) {
        this.permitUrlProperties = permitUrlProperties;
    }

    /**
     * Configuration using lambdas
     *
     * @param http
     * @return
     * @throws Exception
     */
    @Bean
    @ConditionalOnMissingBean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.authorizeRequests();
        permitUrlProperties.getUrls()
                .forEach(url -> registry.antMatchers(url).permitAll());
        registry.anyRequest().authenticated();
        http
                //禁用表单登录
                .formLogin().disable()
                // 关闭csrf
                .csrf((csrf) -> csrf.disable())
                //禁用session,JWT校验不需要session
                .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .exceptionHandling((exception) -> exception
                        // 未授权异常处理
                        .accessDeniedHandler(new JwtAccessDeniedHandler()));
        http.addFilterAfter(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

    JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
        return new JwtAuthenticationTokenFilter(permitUrlProperties);
    }

三、配置Fegin调用免认证

前面的远程服务调用是通过加白名单来放行的,但是内部服务之间调用应该是免认证,所以还需要配置一个内部服务调用的标记,用来放行服务间的调用。
具体思路就是在feign调用的时候,在其请求的headr中添加一个标记;每次请求的时候先通过gateway清洗掉这个标记(fegin调用不通过gateway,清洗的目是为了防止非法请求),然后在具体服务里面拦截这个请求,验证是否为内部服务调用,部分代码如下:

# feign 配置
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: FULL
        # 内部调用的header标记
        defaultRequestHeaders:
          X-FROM-INTERNAL-XXX: WOW
 // 清洗请求头中的内部调用标记,防止非法请求
        ServerHttpRequest request = exchange.getRequest().mutate()
                .headers(httpHeaders -> httpHeaders.remove(SecurityConstant.FROM))
                .build();
 /**
     * 判断是否内部调用
     * @param request
     * @return
     */
    public boolean isInner(HttpServletRequest request) {
        return request.getHeader(SecurityConstant.FROM) != null
                && request.getHeader(SecurityConstant.FROM).equalsIgnoreCase(SecurityConstant.FROM_IN);
    }

将这个方法加到权限拦截和token验证的两个类中,就可以实现内部服务免认证访问了。

测试可以发现直接访问服务接口会提示未登录,但通过feign访问则可以正常返回数据。
在这里插入图片描述
在这里插入图片描述

当前版本tag:2.0.1
代码仓库


四、 体验地址

后台数据库只给了部分权限,报错属于正常!
想学的老铁给点点关注吧!!!
欢迎留言交流!!!

我是阿咕噜,一个从互联网慢慢上岸的程序员,如果喜欢我的文章,记得帮忙点个赞哟,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值