Rumah >Java >javaTutorial >Cara menggunakan Spring AOP untuk melaksanakan pengesahan antara muka dalam SpringBoot

Cara menggunakan Spring AOP untuk melaksanakan pengesahan antara muka dalam SpringBoot

WBOY
WBOYke hadapan
2023-05-19 18:13:121305semak imbas

Pengaturcaraan berorientasikan aspek

Pengaturcaraan berorientasikan aspek boleh mengekstrak logik yang tiada kaitan dengan perniagaan tetapi perlu dipanggil bersama oleh pelbagai modul perniagaan, dan memotongnya ke dalam kod dalam bentuk aspek , dengan itu mengurangkan gandingan kod dalam darjah sistem, mengurangkan kod pendua.

Spring AOP melaksanakan pengaturcaraan berorientasikan aspek melalui prakompilasi dan proksi dinamik semasa masa jalan

Pelaksanaan prinsip asas AOP

Penggunaan asas dinamik AOP Proksi selesai keperluan dan menjana kelas proksi untuk kelas yang perlu dipertingkatkan Terdapat dua cara untuk menjana kelas proksi (iaitu kelas yang perlu dipertingkatkan), jika:

  • melaksanakan antara muka dan menggunakan proksi dinamik JDK Kelas proksi yang dijana akan menggunakan antara mukanya Jika ia tidak melaksanakan antara muka,

  • menggunakan CGlib. proksi dinamik dan kelas proksi yang dijana akan menggunakannya

istilah berkaitan AOP

  • Titik sambungan: Dalam Kaedah kelas proksi (dipertingkatkan)

  • Titik masuk: Kaedah yang sebenarnya perlu dipertingkatkan

  • Pemberitahuan: Kod logik untuk dipertingkatkan

    • Pra-pemberitahuan: Dilaksanakan sebelum fungsi utama dilaksanakan

    • Pemberitahuan siaran: Dilaksanakan selepas pelaksanaan fungsi utama

    • Pemberitahuan keliling: Dilaksanakan sebelum dan selepas pelaksanaan fungsi utama

    • Pemberitahuan pengecualian: Dilaksanakan apabila pengecualian berlaku dalam pelaksanaan fungsi tema

    • Pemberitahuan akhir: Fungsi utama akan dilaksanakan tanpa mengira sama ada pelaksanaan berjaya

  • Aspek: Gabungan titik masuk dan aspek , iaitu kaedah yang dipertingkatkan dan fungsi yang dipertingkatkan membentuk aspek

Ulasan dan ungkapan titik potong yang berkaitan

Anotasi:

  • @Aspect: Isytiharkan bahawa kelas ialah aspek , tulis pemberitahuan dan titik masuk

  • @Sebelum: Sesuai pra-pemberitahuan

  • @AfterReturning: Sesuai dengan post-notification

  • @Sekitar: Sepadan dengan pemberitahuan sekeliling

  • @AfterThrowing: Pemberitahuan pengecualian sepadan

  • @Selepas: Surat pemberitahuan akhir

  • @Pointcut: Pointcut Penyata, menandakannya pada kaedah boleh menjadikan ungkapan lebih ringkas

Gunakan ungkapan pointcut untuk mengisytiharkan pointcut

  • execution([permission modifier][return type][full class path].[nama kaedah][parameter list type] )

pelaksanaan(* com.xxx.ABC. add()), tingkatkan kaedah kelas ABC

Laksanakan pengesahan antara muka

1. Konfigurasikan fail yml

Konfigurasikan akaun pengesahan antara muka

account:
  infos:
    - account: xinchao
      secret: admin
2 Baca konfigurasi akaun

@Data
public class SecretInfo {
    private String account;
    private String secret;
}

3. Tulis kaedah pengesahan antara muka

@Configuration
@ConfigurationProperties("account")
public class SecretConfig {
    private List<SecretInfo> infos;

    private Map<String, SecretInfo> map;

    private Map<String, TokenInfo> tokenMap = new HashMap<>();

    public void setInfos(List<SecretInfo> infos) {
        this.infos = infos;
        map = infos.stream().collect(Collectors.toMap(SecretInfo::getAccount, Function.identity()));
    }

    public synchronized String getToken(String account, String secret) {
        SecretInfo info = map.get(account);
        if (info == null) {
            throw new BusinessException("无效账号");
        }
        if (!StringUtils.equals(info.getSecret(), secret)) {
            throw new BusinessException("无效密码");
        }
        TokenInfo tokenInfo = tokenMap.get(account);
        if (tokenInfo != null && tokenInfo.getToken() != null) {
            return tokenInfo.getToken();
        }
        tokenInfo = new TokenInfo();
        String uuid = UUID.randomUUID().toString();
        tokenInfo.setToken(uuid);
        tokenInfo.setCreateDate(LocalDateTime.now());
        tokenInfo.setExpireDate(LocalDateTime.now().plusHours(2));
        tokenMap.put(account,tokenInfo);
        return tokenInfo.getToken();
    }

    public boolean checkCaptcha(String captcha) {
        return tokenMap.values().stream().anyMatch(e->StringUtils.equals(e.getToken(),captcha));
    }
}
@Data
public class TokenInfo {
    private LocalDateTime createDate;
    private LocalDateTime expireDate;
    private String token;

    public String getToken() {
        if (LocalDateTime.now().isBefore(expireDate)) {
            return token;
        }
        return null;
    }

    public boolean verification(String token) {
        return Objects.equals(this.token, token);
    }
}

4. Tulis AOP

Mula-mula, tulis anotasi untuk menunjukkan bahawa pengesahan tidak diperlukan

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CaptchaIgnoreAop {
}
@Slf4j
@Aspect
@Component
@Order(2)
public class CaptchaAop {

    @Value("${spring.profiles.active:dev}")
    private String env;

    @Autowired
    private SecretConfig config;

    @Pointcut("execution(public * com.herenit.phsswitch.controller.impl..*.*(..))" +
            "&&@annotation(org.springframework.web.bind.annotation.PostMapping)" +
            "&&!@annotation(com.herenit.phsswitch.aop.CaptchaIgnoreAop)")
    public void tokenAop() {
    }

    @Around("tokenAop()")
    public Object doBefore(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        if (args.length == 0 || !(args[0] instanceof RequestWrapper)
                || "test,dev".contains(env)) {
            log.info("当前环境无需校验token");
            return joinPoint.proceed();
        }
        String captcha = ((RequestWrapper) joinPoint.getArgs()[0]).getCaptcha();
        if (!config.checkCaptcha(captcha)) {
            throw new BusinessException("captcha无效");
        }
        return joinPoint.proceed();
    }

}
5 >Gunakan antara muka ini untuk mencipta token dalam ingatan dan mengembalikannya ke bahagian hadapan. Kemudian, kita boleh menghantar token ini untuk pengesahan apabila melaraskan antara muka lain. Kedudukan masuk ialah medan captcha

@PostMapping("/login")
@CaptchaIgnoreAop
public ResponseWrapper login(@RequestBody JSONObject userInfo) {
    String token = config.getToken(userInfo.getString("loginName")
            , userInfo.getString("password"));
    JSONObject result = new JSONObject();
    result.put("platformAccessToken", token);
    return ResponseWrapper.success(result);
}

Atas ialah kandungan terperinci Cara menggunakan Spring AOP untuk melaksanakan pengesahan antara muka dalam SpringBoot. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam