在Spring boot和spring security中登录后无法访问页面

问题描述 投票:0回答:0

我有一个实现 spring 安全的 spring boot 应用程序。在应用程序中,有一个导航栏和在 thymeleaf 中应用的片段。登录后,我无法使用导航栏访问给定的 url。我不知道为什么会这样。是否是由于 html 错误或 spring security 或地址故障。我想在登录后查看 userdetails.html 做什么。我的主页有登录部分。正确重定向到 uprojects.html。但是使用导航栏链接我无法检索“uprojects”和“userdetails”。任何帮助将不胜感激。我的代码如下,

最后,我收到错误“whitelabel error page”404。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <meta charset="UTF-8">
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
          integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
    <title>CrossCheck</title>
</head>
<body>
<div th:fragment="header">
  <nav class="navbar navbar-expand-lg navbar-light bg-light">
    <a class="navbar-brand" href="#">
      <img src="/assets/img/crosscheck_navbar_logo.png" width="30" height="30" alt="">
    </a>
    <a class="navbar-brand" th:href="@{/home}">CROSSCHECK</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
      <div class="navbar-nav">
        <a class="nav-item nav-link active" th:href="@{/home}">Home <span class="sr-only">(current)</span></a>
        <a class="nav-item nav-link" th:href="@{/nfeatures}">Features</a>
        <a class="nav-item nav-link" th:href="@{/pricing}">Pricing</a>
        <a sec:authorize="isAuthenticated()" class="nav-item nav-link" th:href="@{/uprojects}">Projects</a>
        <a sec:authorize="isAuthenticated()" class="nav-item nav-link" th:href="@{/userdetails}">User</a>
        <a sec:authorize="isAuthenticated()" class="nav-item nav-link" th:href="@{/logout}">Logout</a>
      </div>
    </div>
  </nav>
</div>
</body>
</html>

安全设置如下,

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Bean
    SecurityFilterChain defaultSecurityFilterChain (HttpSecurity http) throws Exception{
        http.authorizeHttpRequests((requests) -> requests
                .requestMatchers("/registration/**").permitAll()
                .requestMatchers("/home/**").permitAll()
                        .requestMatchers("/fragments/**").permitAll()
                        .requestMatchers("/nfeatures/**").permitAll()
                        .requestMatchers("/pricing/**").permitAll()
                        .requestMatchers("/assets/**").permitAll()
                        .requestMatchers("/forgotpass/**").permitAll()
                        .requestMatchers("/resetpass/**").permitAll()
                .requestMatchers("/user/**", "/uprojects/**", "/userdetails/**").hasAnyRole("ROLE_USER", "ROLE_ADMIN")
                .requestMatchers("/admin/**").hasAnyRole("ADMIN")
                .anyRequest().authenticated()
        )
                .formLogin((form) -> form
                        .loginPage("/home")
                        .loginProcessingUrl("/login")
                        .defaultSuccessUrl("/uprojects")
                        .usernameParameter("email")
                        .permitAll()
                )
                .logout((logout) -> logout
                        .logoutSuccessUrl("/home")
                        .invalidateHttpSession(true)
                        .permitAll())
                .exceptionHandling().accessDeniedPage("/access-denied");
        return http.build();
    }
}

我想在使用导航栏登录后查看的用户详细信息页面。

    <!doctype html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="utf-8">
        <meta content="width=device-width, initial-scale=1" name="viewport">
        <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
              integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
                integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
                crossorigin="anonymous"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
        <script type="text/javascript" src="/assets/js/jquery.input-allow.js"></script>
    
        <title>User Details</title>
    </head>
    <body>
    <div th:replace="~{fragments/header :: header}"></div>
    
    <div class="container">
        <div class="row mt-5 align-items-center">
            <div class="d-flex flex-row justify-content-center">
                <img th:src="@{/assets/img/crosscheck_login_logo.png}" class="img-fluid mx-auto">
            </div>
            <div class="card-body register-card-body">
    
                <div class="mx-auto" style="width: 400px;">
                    <form
                            method="post"
                            role="form"
                            th:action="@{/userdetails}"
                            th:object="${userd}"
                    >
                        <div class="alert alert-success" role="alert" th:if="${registrationMsg != null}">
                            <p th:text="${registrationMsg}"></p>
                        </div>
                        <div class="alert alert-warning" role="alert" th:if="${#fields.hasErrors('global')}">
                            <p th:each="err : ${#fields.errors('global')}" th:text="${err}"></p>
                        </div>
                        <div th:if="${registrationMsg == null}">
                            <p class="login-box-msg"><b>Update your details</b></p>
                            <div class="mb-3">
                                <label class="col-sm-2 col-form-label col-form-label-sm" for="name">Name</label>
                                <input class="form-control" id="name" name="name" type="text" th:value="${name}">
                                <p class="text-danger" th:errors="*{name}"
                                   th:if="${#fields.hasErrors('name')}"></p>
                            </div>
                            <div class="mb-2">
                                <label class="col-sm-2 col-form-label col-form-label-sm" for="surname">Surname</label>
                                <input class="form-control" id="surname" name="surname" type="text" th:value="${surname}">
                                <p class="text-danger" th:errors="*{surname}"
                                   th:if="${#fields.hasErrors('surname')}"></p>
                            </div>
                            <div class="mb-2">
                                <label class="col-sm-2 col-form-label col-form-label-sm" for="country">Country</label>
                                <select name="country" id="country" class="form-select form-select-mb">
                                    <option value="" th:selected="${country}"></option>
                                </select>
                                <p class="text-danger" th:errors="*{country}"
                                   th:if="(${'country'} == 'Select country') OR ${#fields.hasErrors('country')}"></p>
                            </div>
                            <div class="mb-2">
                                <label class="col-mb-2 col-form-label col-form-label-sm" for="idNumber">Turkish National ID (Other countries, 11111111111)</label>
                                <input class="form-control inputfilter" id="idNumber" name="idNumber" type="text" maxlength="11" allow="[0-9]" th:value="${idNumber}">
                                <p class="text-danger" th:errors="*{idNumber}"
                                   th:if="${#fields.hasErrors('idNumber')}"></p>
                            </div>
                            <label class="col-mb-2 col-form-label col-form-label-sm" for="gsmNumber">Mobile Phone</label>
                            <div class="input-group sm-3">
                                <span class="input-group-text" id="code"></span>
                                <input class="form-control inputfilter" id="gsmNumber" name="gsmNumber" type="text" maxlength="13" allow="[0-9]" th:value="${gsmNumber}">
                                <p class="text-danger" th:errors="*{gsmNumber}"
                                   th:if="${#fields.hasErrors('gsmNumber')}"></p>
                            </div>
                            <div class="mb-2">
                                <label class="col-sm-2 col-form-label col-form-label-sm" for="regAdress">Adress</label>
                                <textarea class="form-control" id="regAdress" name="regAdress" rows="3" th:value="${regAdress}"></textarea>
                                <p class="text-danger" th:errors="*{regAdress}"
                                   th:if="${#fields.hasErrors('regAdress')}"></p>
                            </div>
                            <div class="mb-2">
                                <label class="col-sm-2 col-form-label col-form-label-sm" for="zipcode">Zipcode</label>
                                <input class="form-control inputfilter" id="zipcode" name="zipcode" type="text" maxlength="8" allow="[0-9]" th:value="${zipcode}">
                                <p class="text-danger" th:errors="*{zipcode}"
                                   th:if="${#fields.hasErrors('zipcode')}"></p>
                            </div>
                            <div class="mb-2">
                                <label class="col-mb-2 col-form-label col-form-label-sm" for="city">City or State</label>
                                <input class="form-control" id="city" name="city" type="text" th:value="${city}">
                                <p class="text-danger" th:errors="*{city}"
                                   th:if="${#fields.hasErrors('city')}"></p>
                            </div>
                            <div class="mb-2">
                                <button class="btn btn-secondary mb-2" type="submit">Save</button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
    <footer th:replace="~{fragments/footer :: footer}"></footer>
    </body>
<script>
    $(document).ready(function () {
        var countryOptions = '';
        $.getJSON('/assets/json/countries.json', function (data) {
            countryOptions += '<option value="">Select country</option>';
            $.each(data, function (key, country) {
                countryOptions += '<option value="' + country.name + '">' + country.name + '</option>';
            });
            $('#country').html(countryOptions);
        });

        var country_name = $(this).val();
        if (country_name != '') {
            $.getJSON('/assets/json/countries.json', function (data) {
                $.each(data, function (key, country) {
                    if (country_name == country.name) {
                        $("#code").text(country.dialCode);
                    }
                });
            });
        }

        if (country_name != 'Turkey') {
            $('#idNumber').val('11111111111');
            $('#idNumber').prop('disabled', true);
        } else {
            $('#idNumber').prop('disabled', false);
        }
    });



</script>
    </html>

和控制器查看用户详情页面,

@Controller
@RequestMapping("/userdetails")
public class UserDetailsController {

    @Autowired
    private UserService userService;

    @Resource
    private MessageSource messageSource;

    @GetMapping
    public String userDetails(Model model){

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        Object principal = auth.getPrincipal();
        String email = principal.toString();
        CCUser user = userService.findUserByEmail(email);
        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(userDto, user);

        model.addAttribute("userd", userDto);

        return "userdetails";
    }
}

主控,

@Controller
public class MainController {

    @GetMapping("/home")
    public String displayHomePage (Model model){

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        List<GrantedAuthority> grantedRoles = new ArrayList<GrantedAuthority>();
        grantedRoles.addAll(auth.getAuthorities());
        if(grantedRoles.stream().anyMatch(r -> r.getAuthority().equals("ROLE_USER"))){
            return "uprojects";
        }
        return "home";
    }
    @GetMapping("/nfeatures")
    public String displayNFeaturesPage (Model model){
        return "nfeatures";
    }

    @GetMapping("/uprojects")
    public String displayUProjectsPage (Model model){
        return "uprojects";
    }
    @GetMapping("/pricing")
    public String displayPricingPage (Model model){
        return "pricing";
    }

    @GetMapping(value="/logout")
    public String logoutPage (HttpServletRequest request, HttpServletResponse response) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null){
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        return "redirect:/login?logout";//You can redirect wherever you want, but generally it's a good practice to show login screen again.
    }

}
mysql spring-boot spring-security thymeleaf
© www.soinside.com 2019 - 2024. All rights reserved.