springcloud security 登录

1.我们将表单传过来的用户名称和密码封装成UsernamePasswordAuthenticationToken对象,而UsernamePasswordAuthenticationToken又继承了AbstractAuthenticationToken,而AbstractAuthenticationToken又是Authentication的实现类,因此我们满足了封装成Authentication对象的条件,可以往后进行authenticate()方法的认证

2.在authenticate()方法的认证的过程中,我们分析,先通过ProviderManager调DaoAuthenticationProvider的authentication()进行认证。而DaoAuthenticationProvider又会去调用UserDetialService当中的loadUserByUsername方法查询用户。

3.我们默认的实现类是InMemoryUserDetailsManager,意思是从内存中查询用户,它内部拥有自己的UserDetail实现类对象,封装的是我们配置的用户值亦或是SpringSecurity默认的用户值。而我们的开发需求肯定是从数据库中查询用户信息,而后封装成UserDetial对象.因此我们要自定义UserDetailService的实现类以及要自定义UserDetial的实现类

                        
原文链接:https://blog.csdn.net/m0_69261651/article/details/129506369
导入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>3.0.5</version>
</dependency>

gateway 实现filter

1.思路

(1)开放白名单url

(2)非白名单通过自定义方法判断是否为系统用户

(3)取出某些字段方便接口调用直接从header中获取

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    ServerHttpRequest request = exchange.getRequest();
    String url = request.getPath().value();
    url = org.apache.commons.lang.StringUtils.removeStart(url, "/api");
    String path = url.substring(url.indexOf("/", 1));

    //请求路径在访问白名单中则放行
    PathMatcher pathMatcher = new AntPathMatcher();
    if (Stream.of(this.urlwhitelist.split(",")).anyMatch(value -> pathMatcher.match(value, path))) {
        return chain.filter(exchange);
    }

    String token = request.getHeaders().getFirst(CommonConstant.TOKEN);
    String userType = request.getHeaders().getFirst(CommonConstant.userType);
    String method = request.getMethodValue();
    String remoteAddr = gainIPUtil.getIpAddress(request);

    log.info("url:{},ip:{},method:{},headers:{}", url, remoteAddr, method, request.getHeaders());
        //token为空
        if (StringUtils.isBlank(token)) {
            return loginTimeout(exchange);
        }
        //校验token及权限信息-----------实现方法在这里
        ApproveVo approveVo = authService.checktoken(token, path, remoteAddr, userType);
        if (null == approveVo || StringUtils.isEmpty(approveVo.getUserId())){
            return unauthorized(exchange);
        }
        //增加权限参数
        request.mutate().header("tenantId",approveVo.getTrnantId())
                .header("userId",approveVo.getUserId())
                .header("superAdmin",approveVo.getSuperAdmin()).build();
        if (approveVo.getSuperAdmin().equals(CommonConstant.SYSTEM_ROLE_YES)){
                   request.mutate().header("dataScope",CommonConstant.SYSTEM_ROLE_YES).build();
        }else {
            request.mutate().header("dataScope",approveVo.getDataScope()).build();
        }
    
    return  chain.filter(exchange);
}

 auth服务完成登录逻辑

1.loadUserByUsername方法

UserDetailsService接口里有且仅有一个方法,它就是及其巧妙的loadUserByUsername(),为什么说它巧妙?答曰:见名知意,功能甚好。它通过用户名加载用户信息到Security内置容器UserDetails中,认证时通过注入的形式需要的提供数据。

重写它的loadUserByUsername方法,在里面自定义登陆逻辑(通常来说:通过用户名查询数据库,获取到用户对象信息)。

UserDetails

把这些信息取出来,然后包装成一个对象交由框架去认证,认证包括密码、是否过期、是否锁定、权限等等。

loadUserByUsername的回参是UserDetails接口类型的数据。查看UserDetails源码,它里面有很多的方法,方法名称就是对功能的最简单的描述

package org.springframework.security.core.userdetails;
实现UserDetailsService
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    //根据自己业务需要定义查询接口
    @Resource
    private ManagementService managementService;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        //TODO
        //查询用户信息 根据自己业务需要定义查询接口
        TokenUserVo userName = managementService.findByUserName(s);
        if (null == userName || StringUtils.isEmpty(userName.getId())){
            throw new BasicException(ResultCode.USER_NOT_EXIST);
        }
        TenantUserEntity tenantUserEntity = new TenantUserEntity();
        BeanUtils.copyProperties(userName, tenantUserEntity);
        return tenantUserEntity;
    }
}

TenantUserEntity

TenantUserEntity 是UserDetails的默认实现类,把UserDetails里面的方法中待获取的数据实际的构造出来。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class TenantUserEntity implements UserDetails, Serializable {

    /**
     * 用户id
     */
    private String id;

    /**
     * 租户ID
     */
    private String tenantId;

    /**
     * 是否为系统管理租户
     */
    private String SysTenant;

    /**
     * 是否为系统管理租户
     */
    private String SysUser;

    /**
     * 过期时间
     */
    @JsonFormat(shape = JsonFormat.Shape.STRING,pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private LocalDate expireTime;

    /**
     * 用户平台(后台管理系统:sys,小程序:mini,移动端:app,多平台用逗号连接)
     */
    private String userType;

    /**
     * 用户名
     */
    private String userName;

    /**
     * 密码
     */
    private String passWord;

    /**
     * 手机号
     */
    private String phone;

    /**
     * 状态:(0:禁用,1:正常)
     */
    private Boolean status;

    /**
     * 创建人
     */
    private String createBy;

    /**
     * 组织机构ID
     */
    private Long organizationId;

    /**
     * 岗位id
     */
    private Long postId;
    /**
     * 角色id
     */
    private Long roleId;

    /**
     * 权限集合(用来存从数据库查到的用户权限))
     */
    private List<String> permissions;

    //忽略序列化   SpringSecrity权限校验需要的格式的权限集合
    @JSONField(serialize = false)
    private List<SimpleGrantedAuthority> authorities;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        if (!CollectionUtils.isEmpty(authorities)){
            return authorities;
        }
        //把 permissions 中的String类型权限信息,封装成SimpleGrantedAuthority对象
        authorities = permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
        return authorities;
    }

    @Override
    public String getPassword() {
        return passWord;
    }

    @Override
    public String getUsername() {
        return userName;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return status;
    }
}

AuthenticationManager

用来认证

//AuthenticationManager authenticate 进行用户认证
UsernamePasswordAuthenticationToken authenticationToken =
        new UsernamePasswordAuthenticationToken(loginParam.getUserName(),password);
Authentication authenticate;
try {
    authenticate = authenticationManager.authenticate(authenticationToken);

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值