首页 > 解决方案 > 基于角色的登录后,Spring Boot 应用程序显示“白级错误”

问题描述

我是 Spring Boot 的新手,我正在尝试创建将执行基于角色的登录的登录应用程序。我的应用程序显示“此应用程序没有 /error 的显式映射,因此您将此视为后备。” 在我尝试登录之后。但是当我调试时,我可以看到它正在正确验证用户。我正在发布我的应用程序结构和我编写的代码,

在此处输入图像描述

在此处输入图像描述

驱动程序/主类

@SpringBootApplication
public class ApplicationInitilizer {
public static void main(String[] args) {
    SpringApplication.run(ApplicationInitilizer.class, args);
   }
  }

网络安全配置

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

@Autowired
private UserDetailsServiceImpl userDetailsService;

@Autowired
private DataSource dataSource;

@Bean
public BCryptPasswordEncoder passwordEncoder() {
    BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
    return bCryptPasswordEncoder;
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    // Setting Service to find User in the database.
    // And Setting PassswordEncoder
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {

      http.csrf().disable();
    // The pages does not require login
      http.authorizeRequests().antMatchers("/", "/login", "/logout").permitAll();

      // /userInfo page requires login as ROLE_USER or ROLE_ADMIN.
      // If no login, it will redirect to /login page.
      http.authorizeRequests().antMatchers("/userInfo").access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')");

      // For ADMIN only.
      http.authorizeRequests().antMatchers("/admin").access("hasRole('ROLE_ADMIN')");

      // When the user has logged in as XX.
      // But access a page that requires role YY,
      // AccessDeniedException will be thrown.
      http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/403");

   // Config for Login Form
      http.authorizeRequests().and().formLogin()//
              // Submit URL of login page.
              .loginProcessingUrl("/j_spring_security_check") // Submit URL
              .loginPage("/login")//
              .defaultSuccessUrl("/userAccountInfo")//
              .failureUrl("/login?error=true")//
              .usernameParameter("username")//
              .passwordParameter("password")
              // Config for Logout Page
              .and().logout().logoutUrl("/logout").logoutSuccessUrl("/logoutSuccessful");
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
    JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
    db.setDataSource(dataSource);
    return db;
  }
}

控制器

@Controller
public class MainController {

@RequestMapping(value = "/admin", method = RequestMethod.GET)
public String adminPage(Model model, Principal principal) {

User loginedUser = (User) ((Authentication) principal).getPrincipal();

String userInfo = WebUtils.toString(loginedUser);
model.addAttribute("userInfo", userInfo);

return "adminPage";
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginPage(Model model) {

return "Login";
}

@RequestMapping(value = "/logoutSuccessful", method = RequestMethod.GET)
public String logoutSuccessfulPage(Model model) {
model.addAttribute("title", "Logout");
return "logoutSuccessfulPage";
 }

@RequestMapping(value = "/userInfo", method = RequestMethod.GET)
  public String userInfo(Model model, Principal principal) {

  // After user login successfully.
  String userName = principal.getName();

  System.out.println("User Name: " + userName);

 User loginedUser = (User) ((Authentication) principal).getPrincipal();

 String userInfo = WebUtils.toString(loginedUser);
 model.addAttribute("userInfo", userInfo);

    return "userInfoPage";
  }

   @RequestMapping(value = "/403", method = RequestMethod.GET)
   public String accessDenied(Model model, Principal principal) {

 if (principal != null) {
    User loginedUser = (User) ((Authentication) principal).getPrincipal();

    String userInfo = WebUtils.toString(loginedUser);

    model.addAttribute("userInfo", userInfo);

    String message = "Hi " + principal.getName() //
            + "<br> You do not have permission to access this page!";
    model.addAttribute("message", message);

  }

      return "403Page";
      }
   }

DAO

 @Repository
 @Transactional
public class AppRoleDAO {

@Autowired
private EntityManager entityManager;

public List<String> getRoleNames(Long userId){
     String sql = "Select ur.appRole.roleName from " + UserRole.class.getName() + " ur " //
                + " where ur.appUser.userId = :userId ";
     Query query = this.entityManager.createQuery(sql, String.class);
        query.setParameter("userId", userId);
        return query.getResultList();
   }    
 }



@Repository
@Transactional
public class AppUserDAO {
@Autowired
private EntityManager entityManager;

public AppUser findUserAccount(String userName) {
    try {
        String sql = "Select e from " + AppUser.class.getName() + " e " //
                + " Where e.userName = :userName ";

        Query query = entityManager.createQuery(sql, AppUser.class);
        query.setParameter("userName", userName);

        return (AppUser) query.getSingleResult();
    } catch (NoResultException e) {
        return null;
    }
   }
  }

实体类

 @Repository
 @Transactional
 public class AppUserDAO {
@Autowired
private EntityManager entityManager;

public AppUser findUserAccount(String userName) {
    try {
        String sql = "Select e from " + AppUser.class.getName() + " e " //
                + " Where e.userName = :userName ";

        Query query = entityManager.createQuery(sql, AppUser.class);
        query.setParameter("userName", userName);

        return (AppUser) query.getSingleResult();
    } catch (NoResultException e) {
        return null;
    }
   }
  }



  @Entity
  @Table(name = "App_User", //
    uniqueConstraints = { //
            @UniqueConstraint(name = "APP_USER_UK", columnNames = 
"User_Name") })
 public class AppUser {

@Id
@GeneratedValue
@Column(name = "User_Id", nullable = false)
private Long userId;

@Column(name = "User_Name", length = 36, nullable = false)
private String userName;

@Column(name = "Encryted_Password", length = 128, nullable = false)
private String encrytedPassword;

@Column(name = "Enabled", length = 1, nullable = false)
private boolean enabled;

public Long getUserId() {
    return userId;
}

public void setUserId(Long userId) {
    this.userId = userId;
}

public String getUserName() {
    return userName;
}

public void setUserName(String userName) {
    this.userName = userName;
}

public String getEncrytedPassword() {
    return encrytedPassword;
}

public void setEncrytedPassword(String encrytedPassword) {
    this.encrytedPassword = encrytedPassword;
}

public boolean isEnabled() {
    return enabled;
}

  public void setEnabled(boolean enabled) {
    this.enabled = enabled;
     }
  }

  @Entity
  @Table(name = "User_Role", //
    uniqueConstraints = { //
            @UniqueConstraint(name = "USER_ROLE_UK", columnNames = { 
"User_Id", "Role_Id" }) })
public class UserRole {

@Id
@GeneratedValue
@Column(name = "Id", nullable = false)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "User_Id", nullable = false)
private AppUser appUser;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "Role_Id", nullable = false)
private AppRole appRole;

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public AppUser getAppUser() {
    return appUser;
}

public void setAppUser(AppUser appUser) {
    this.appUser = appUser;
}

public AppRole getAppRole() {
    return appRole;
}

public void setAppRole(AppRole appRole) {
    this.appRole = appRole;
  }

 }

服务实现类

 @Service
 public class UserDetailsServiceImpl implements UserDetailsService{

@Autowired
private AppUserDAO appUserDAO;

@Autowired
private AppRoleDAO appRoleDAO;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

    AppUser appUser=this.appUserDAO.findUserAccount(username);
    if(appUser==null) {
        System.out.println("User not  found! "+username);
        throw new UsernameNotFoundException("User "+username+" was not found in the database");
    }
    System.out.println("Found User :"+appUser);

    List<String> roleNames=this.appRoleDAO.getRoleNames(appUser.getUserId());
    List<GrantedAuthority> grantList = new ArrayList<GrantedAuthority>();

    if(roleNames!=null) {
        for(String role:roleNames){
            GrantedAuthority authority = new SimpleGrantedAuthority(role);
            grantList.add(authority);
        }
    }
    UserDetails userDetails=(UserDetails)new User(appUser.getUserName(),appUser.getEncrytedPassword(),grantList);
    return userDetails;
   }
}

实用类

   public class EncrytedPasswordUtils {

// Encryte Password with BCryptPasswordEncoder
public static String encrytePassword(String password) {
    BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    return encoder.encode(password);
}

public static void main(String[] args) {
    String password = "123";
    String encrytedPassword = encrytePassword(password);

    System.out.println("Encryted Password: " + encrytedPassword);
  }    
}






 public class WebUtils {

public static String toString(User user) {
    StringBuilder sb = new StringBuilder();

    sb.append("UserName:").append(user.getUsername());

    Collection<GrantedAuthority> authorities = user.getAuthorities();
    if (authorities != null && !authorities.isEmpty()) {
        sb.append(" (");
        boolean first = true;
        for (GrantedAuthority a : authorities) {
            if (first) {
                sb.append(a.getAuthority());
                first = false;
            } else {
                sb.append(", ").append(a.getAuthority());
            }
        }
        sb.append(")");
    }
    return sb.toString();
    }

  }

管理页面

  <!DOCTYPE HTML>
  <html xmlns:th="http://www.thymeleaf.org">
  <head>
  <title th:utext="${title}"></title>
  </head>
  <body>
  <!-- Include _menu.html -->


  <h2>Admin Page</h2>
  <h3>Welcome :

  </h3>
  <b>This is protected page!</b>  

  <br/><br/>    

登录.html

  <html>
 <head>
<title>Login Page</title>
  </head>
  <body>
      <form name="loginForm" method="post" th:action="@{/j_spring_security_check}">
   <table width="20%" bgcolor="0099CC" align="center">

  <tr>
  <td colspan=2><center><font size=4><b>HTML Login Page</b></font></center> 
  </td>
 </tr>

  <tr>
 <td>Username:</td>
 <td><input type="text" size=25 name="username"></td>
 </tr>

 <tr>
<td>Password:</td>
<td><input type="Password" size=25 name="password"></td>
</tr>

<tr>
 <td ><input type="Reset"></td>
 <td><input type="submit" onclick="return check(this.form)" value="Login"> 
  </td>
   </tr>

  </table>
  </form>



 403.html





   <!DOCTYPE HTML>
   <html xmlns:th="http://www.thymeleaf.org">
   <head>
   <title>Access Denied</title>
   </head>

   <body>
   <!-- Include _menu.html -->



 eerror


  </body>

 </html>

用户信息页面.html

   <!DOCTYPE HTML>
   <html xmlns:th="http://www.thymeleaf.org">
   <head>
  <title>User Info</title>
 </head>
  <body>
   <!-- Include _menu.html -->



    <h2>User Info Page</h2>

   <b>This is protected page!</b>  

  <br/><br/>



  </body>

</html>

pom.xml

      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
    <groupId>com.jeet.starter</groupId>
   <artifactId>LifeCycleActivityLoaderSpringBoot</artifactId>
  <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>


  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
    </parent>

     <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    </properties>

      <dependencies>
       <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
       <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>


    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
 <build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

输入用户名和密码后,应用程序显示以下错误

 Whitelabel Error Page
  This application has no explicit mapping for /error, so you are seeing this as a fallback.

 Wed Jan 30 00:17:21 IST 2019
 There was an unexpected error (type=Not Found, status=404).
 No message available

有人请帮忙,我是弹簧靴的新手

标签: javaspringspring-bootspring-mvcspring-security

解决方案


似乎您没有userAccountInfoURL 映射。像这样修改现有的userInfo映射方法。

 @RequestMapping(value = "/userAccountInfo", method = RequestMethod.GET)
 public String userInfo(Model model, Principal principal) {

 // After user login successfully.
 String userName = principal.getName();

 System.out.println("User Name: " + userName);

 User loginedUser = (User) ((Authentication) principal).getPrincipal();

 String userInfo = WebUtils.toString(loginedUser);
 model.addAttribute("userInfo", userInfo);

return "userInfoPage";
}

如下更改 SecurityConfig。

    http.authorizeRequests().antMatchers("/userAccountInfo").access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')");

添加 CustomSuccessHandler 如下。

 public class MySimpleUrlAuthenticationSuccessHandler
implements AuthenticationSuccessHandler {

protected Log logger = LogFactory.getLog(this.getClass());

private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

@Override
public void onAuthenticationSuccess(HttpServletRequest request, 
  HttpServletResponse response, Authentication authentication)
  throws IOException {

    handle(request, response, authentication);
    clearAuthenticationAttributes(request);
}

protected void handle(HttpServletRequest request, 
  HttpServletResponse response, Authentication authentication)
  throws IOException {

    String targetUrl = determineTargetUrl(authentication);

    if (response.isCommitted()) {
        logger.debug(
          "Response has already been committed. Unable to redirect to "
          + targetUrl);
        return;
    }

    redirectStrategy.sendRedirect(request, response, targetUrl);
}

protected String determineTargetUrl(Authentication authentication) {
    boolean isUser = false;
    boolean isAdmin = false;
    Collection<? extends GrantedAuthority> authorities
     = authentication.getAuthorities();
    for (GrantedAuthority grantedAuthority : authorities) {
        if (grantedAuthority.getAuthority().equals("ROLE_USER")) {
            isUser = true;
            break;
        } else if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) {
            isAdmin = true;
            break;
        }
    }

    if (isUser) {
        return "/userInfoPage.html";
    } else if (isAdmin) {
        return "/adminPage.html";
    } else {
        throw new IllegalStateException();
    }
}

protected void clearAuthenticationAttributes(HttpServletRequest request) {
    HttpSession session = request.getSession(false);
    if (session == null) {
        return;
    }
    session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}

public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
    this.redirectStrategy = redirectStrategy;
}
protected RedirectStrategy getRedirectStrategy() {
    return redirectStrategy;
}

}


推荐阅读