权限认证自动配置 spring-security-auth-starter

spring-security-auth-starter

  • 目标 基于Spring Security 封装权限认证自动配置,开箱即用,减少开发成本,简化集成
  • 支持动态续租token过期时间
  • 支持基于@PreAuthorize注解方式授权认证
  • 支持基于URL路径权限认证
  • 登录接口前端可对密码进行rsa加密(前端公钥加密,后端私钥解密)
  • 支持自定义登录接口(微信公众授权/小程序授权可选自定义登录接口)
  • @AuthIgnore 注解,用于标识接口是否需要认证

Spring Boot 版本

  • 基于Spring boot v3.x版本重构
  • 需要jdk17+

地址

快速开始

引入依赖

<dependency>
    <groupId>io.github.osinn</groupId>
    <artifactId>spring-security-auth-starter</artifactId>
    <version>最新版本</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

yml 简易配置

  • 如果都是使用默认的,以下配置都可以不用配,登陆接口匿名访问可直接使用@AuthIgnore注解
security:
  config:
    des-password: aMQBIx+Yta0= # 默认的des加密密码,建议换成自己的,可调用 CryptoUtils.generateDesKey() 方法生成
    expire-time: 14400 # 过期时间默认4小时
    expire-ratio: 0.5 # 过期时间剩余比例,0-1之间,默认 0.5 即时间过半时刷新token缓存过期时间
    dynamic-refresh-token: true # 开启启动刷新token,默认是关闭的,不会自动刷新token过期时间,开启后,token会根据 expire-ratio 比例阀值计算是否需求重置token过期时间
    # 匿名访问url
    ignoring-urls:
      - /login # 登录接口忽略认证
  • 这里的配置只是一部分的配置,更多配置请查看项目代码

启动类

  • 在启动类添加如下注解启用spring-security-auth-starter安全认证
@EnableSecurityAuth // 添加此注解启用权限认证
@SpringBootApplication
public class SpringSecurityAuthExampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringSecurityAuthExampleApplication.class, args);
    }
}

实现 ISecurityService 接口

  • ISecurityService接口是用来实现登录,获取用户权限等信息

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.github.osinn.example.entity.UserEntity;
import io.github.osinn.example.service.IUserService;
import io.github.osinn.security.enums.AuthHttpStatus;
import io.github.osinn.security.exception.SecurityAuthException;
import io.github.osinn.security.security.dto.*;
import io.github.osinn.security.service.ISecurityService;
import io.github.osinn.security.starter.SecurityProperties;
import io.github.osinn.security.utils.CryptoUtils;
import io.github.osinn.security.utils.StrUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * 示例
 *
 * @author wency_cai
 */
@Slf4j
@Service
public class SecurityServiceImpl implements ISecurityService {

    @Resource
    private IUserService userService;

    @Resource
    private SecurityProperties securityProperties;

    @Resource
    private PasswordEncoder passwordEncoder;

//    /**
//     * 自定义登录
//     * 如果是微信授权登录可以使用自定义登录接口 返回AuthUserInfo 信息即可
//     *
//     * @param principal 登录接口登录信息对象,由开发者自己定义传入
//     * @return
//     */
//    @Override
//    public AuthUserInfo customAuth(Object principal) {
//        AuthLoginParam authLoginParam = (AuthLoginParam) principal;
//
//        UserEntity userEntity = userService.getOne(Wrappers.lambdaQuery(UserEntity.class)
//                .eq(UserEntity::getAccount, authLoginParam.getAccount())
//        );
//
//        String password;
//        if (!StrUtils.isEmpty(securityProperties.getRsaPrivateKey())) {
//            try {
//                password = CryptoUtils.rsaDecrypt(authLoginParam.getPassword(), securityProperties.getRsaPrivateKey());
//            } catch (Exception e) {
//                log.error(e.getMessage(), e);
//                throw new SecurityAuthException(AuthHttpStatus.PASSWORD_ERROR.getCode(), AuthHttpStatus.TOKEN_UNAUTHORIZED.getMessage());
//            }
//        } else {
//            password = authLoginParam.getPassword();
//        }
//
//        if (!passwordEncoder.matches(password, userEntity.getPassword())) {
//            throw new BadCredentialsException(AuthHttpStatus.TOKEN_UNAUTHORIZED.getMessage());
//        }
//
//        AuthUserInfo authUserInfo = new AuthUserInfo();
//        authUserInfo.setId(userEntity.getId());
//        authUserInfo.setNickname(userEntity.getUserName());
//        authUserInfo.setAccount(userEntity.getAccount());
//
//        return authUserInfo;
//    }

    /**
     * 根据账号获取用户信息
     *
     * @param account
     * @return AuthUserInfo
     */
    @Override
    public AuthUserInfo loadUserByUsername(String account) {
        UserEntity userEntity = userService.getOne(Wrappers.lambdaQuery(UserEntity.class)
                .eq(UserEntity::getAccount, account)
        );
        if (userEntity == null) {
            return null;
        }

        return new AuthUserInfo(
                userEntity.getId(),
                userEntity.getAccount(),
                userEntity.getUserName(),
                userEntity.getPassword(),
                null, // 如果需要额外扩展用户信息,请自赋值一个对象即可, 从在线用户信息中获取 -> onlineUser.getExtendField() 即为此处传入的对象
                null, // 不需要赋值,内置会自行处理
                null, // 不需要赋值,内置会自行处理
                null, // 不需要赋值,内置会自行处理
                null // 不需要赋值,内置会自行处理
        );
    }

    /**
     * 获取用户的角色以及权限
     *
     * @param userId
     * @return
     */
    @Override
    public AuthRoleInfo fetchRolePermissionInfo(Object userId) {
        AuthRoleInfo jwtRoleInfo = new AuthRoleInfo();

        List<ResourcePermission> resourcePermissionList = new ArrayList<>();
        resourcePermissionList.add(new ResourcePermission(null, "sys:user:list", "用户管理"));

        AuthRoleInfo.BaseRoleInfo roleInfo = new AuthRoleInfo.BaseRoleInfo(1, "demo", "test", null, resourcePermissionList);

        jwtRoleInfo.setRoles(List.of(roleInfo));
        return jwtRoleInfo;
    }

    /**
     * 获取系统所有资源权限
     *
     * @return
     */
    @Override
    public List<ResourcePermission> getSysResourcePermissionAll() {
        List<ResourcePermission> resourcePermissionList = new ArrayList<>();
        resourcePermissionList.add(new ResourcePermission(null, "sys:user:list", "用户管理"));
        resourcePermissionList.add(new ResourcePermission(null, "sys:user:list2", "用户管理2"));
        return resourcePermissionList;
    }

}
posted @ 2025-05-24 18:19  程序员の奇妙冒险  阅读(46)  评论(0)    收藏  举报