首页  >  问答  >  正文

成功登录后,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粉957661544205 天前318

全部回复(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
  • 取消回复