After successful login, Spring Boot Thymeleaf implements the file download function
P粉957661544
P粉957661544 2024-03-28 09:54:29
0
1
389

I want to provide a web service with Spring Boot that is able to download dumps from a MySQL database.

But downloading shouldn't be suitable for everyone. So I need a kind of login. Not quite sure where the credentials will be stored, it's possible they are just hardcoded in the application itself.

I'm a bit lost and don't know how to implement this.

This is what I've got so far:

@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;
    }

}

Currently the controller displays the login page at "/login". After submitting the form, the controller checks if the credentials are correct and if not, displays the login page again with an error message.

But my problem is, I don't know what to do after logging in successfully. The download works fine when I call it directly, but it doesn't work when using a redirect because I make a post request to ensure that the user who just logged in can download the file. If I make a get request, everyone can use the link.

I have a feeling that the way I'm approaching the problem is wrong. What would you recommend? How to start downloading after successful login?

P粉957661544
P粉957661544

reply all(1)
P粉574695215

I recommend adding Spring Security to your project and having a hardcoded user in it:

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();
    }
}
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template