搜尋

首頁  >  問答  >  主體

成功登入後,Spring Boot Thymeleaf實現檔案下載功能

我想提供一個有 Spring Boot 的 Web 服務,它能夠從 MySQL 資料庫下載轉儲。

但下載不應該適合所有人。所以我需要一種登入。不太確定憑證將儲存在哪裡,有可能它們只是硬編碼在應用程式本身。

我有點迷失,不知道該如何實現。

這是我到目前為止得到的:

@Controller
public class EBMysqldumpController {

    private EBMysqldumpService mysqldumpService;

    @Autowired
    public EBMysqldumpController(EBMysqldumpService mysqldumpService) {
        this.mysqldumpService = mysqldumpService;
    }

    @GetMapping("/login")
    public String showLoginForm(Model model) {
        model.addAttribute("userDto", new UserDto());
        return "mysqldump-login";
    }

    @PostMapping(path = "/login")
    public String validateLoginForm(@Valid UserDto userDto, BindingResult result, HttpServletRequest request) {
        if (result.hasErrors()) {
            return "mysqldump-login";
        }

        if (!this.mysqldumpService.checkLogin(userDto)) {
            result.addError(new ObjectError("", "Wrong username and/or password"));
            return "mysqldump-login";
        }

        return "redirect:/file";
    }

    @PostMapping(path = "/file")
    public ResponseEntity<Resource> startMysqlDump(@Valid UserDto userDto, Model model) throws IOException, InterruptedException, MysqldumpException {
        if (!this.mysqldumpService.checkLogin(userDto)) {
            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
        }

        File mysqlDump = this.mysqldumpService.getMysqlDumpFile();
        ByteArrayResource byteArrayResource = this.mysqldumpService.getByteArrayResourceFromFile(mysqlDump);

        HttpHeaders headers = getMysqldumpHeaders(mysqlDump.getName());
        ResponseEntity<Resource> body = ResponseEntity.ok()
                .headers(headers)
                .contentLength(mysqlDump.length())
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(byteArrayResource);

        this.mysqldumpService.deleteFile(mysqlDump);

        return body;
    }

    private HttpHeaders getMysqldumpHeaders(String filename) {
        ContentDisposition contentDisposition = ContentDisposition.inline().filename(filename).build();

        HttpHeaders headers = new HttpHeaders();
        headers.setContentDisposition(contentDisposition);

        return headers;
    }

}

目前控制器在「/login」處顯示登入頁面。提交表單後,控制器會檢查憑證是否正確,如果不正確,則會再次顯示帶有錯誤訊息的登入頁面。

但我的問題是,登入成功後我不知道該做什麼。當我直接呼叫它時,下載工作正常,但使用重定向時它不起作用,因為我發出了發布請求以確保剛剛登入的使用者可以下載該檔案。如果我發出獲取請求,每個人都可以使用該連結。

我有種感覺,我處理問題的方式是錯的。你會推薦什麼?登入成功後如何開始下載?

P粉957661544P粉957661544272 天前382

全部回覆(1)我來回復

  • P粉574695215

    P粉5746952152024-03-29 00:48:53

    我建議將 Spring Security 添加到您的專案中,並在其中有一個硬編碼的用戶:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.crypto.password.NoOpPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    
    @Configuration
    public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private PasswordEncoder passwordEncoder;
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                    .passwordEncoder(passwordEncoder)
                .withUser("user1").password("my-secret-pwd").roles("USER");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests(
                        registry -> registry.mvcMatchers("/**").authenticated()
                )
                .formLogin();
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return NoOpPasswordEncoder.getInstance();
        }
    }

    回覆
    0
  • 取消回覆