Spring安全 - 为什么我无法登录我的应用程序?

时间:2016-05-12 04:33:51

标签: java spring spring-mvc spring-security

我尝试登录我的应用程序时遇到了一些令人尴尬的问题。

My Spring security protected void configure(HttpSecurity http) throws Exception定义为:

protected void configure(HttpSecurity http) throws Exception {
    System.out.println(http);
    http
        .formLogin()
            .loginPage("/login")
            .usernameParameter("ssoId")
            .passwordParameter("password")
            .and()

        .authorizeRequests()
            // I admit that this section needs some work
            .antMatchers("/", "/home/*", "/alert/*", "/scheduler/*", "/agent/*", "/ftp/*", "/smtp/*", "/sql/*").access("hasRole('USER')")
            .antMatchers("/benefit/*", "/client/*", "/contract/*", "/role/*", "/structure/*", "/term/*").access("hasRole('USER')")
            .antMatchers("/", "/home/*", "/alert/*", "/scheduler/*", "/agent/*", "/ftp/*", "/smtp/*", "/sql/*").access("hasRole('ADMIN')")
            .antMatchers("/benefit/*", "/client/*", "/contract/*", "/role/*", "/structure/*", "/term/*").access("hasRole('ADMIN')")
            .antMatchers("/admin/**").access("hasRole('ADMIN')")
            .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")

            .and()
                .rememberMe().rememberMeParameter("remember-me").tokenRepository(persistentTokenRepository()).tokenValiditySeconds(86400)
            .and()
                .csrf()
            .and()
                .exceptionHandling().accessDeniedPage("/accessDenied");
}

应用程序很好地加载并转到/login页面。但是当我尝试使用用户master进行登录并提供正确的密码时,它只会返回/login页面。

我的登录控制器是:

@Controller
public class LoginController {

    @Autowired
    UserProfileService userProfileService;

    @Autowired
    UserService userService;

    @RequestMapping(value = { "/", "/home", "/welcome" }, method = RequestMethod.GET)
    public String index(Principal principal) {
        return principal != null ? "home/homeSignedIn" : "home/homeNotSignedIn";
    }

    @RequestMapping(value = "/login")
    public String loginPage() {
        return "login";
    }

    @RequestMapping(value="/logout", method = RequestMethod.GET)
    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";
    }

    private String getPrincipal(){
        String userName = null;
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        if (principal instanceof UserDetails) {
            userName = ((UserDetails)principal).getUsername();
        } else {
            userName = principal.toString();
        }
        return userName;
    }

    @ModelAttribute("roles")
    public List<UserProfile> initializeProfiles() {
        return userProfileService.findAll();
    }
}

User

@Entity
@Table(name="user")
public class User extends BasePojo {

    @NotEmpty
    @Column(name="sso_id", unique=true, nullable=false)
    private String ssoId;

    @NotEmpty
    @Column(name="password", nullable=false)
    private String password;

    @NotEmpty
    @Column(name="first_name")
    private String firstName;

    @NotEmpty
    @Column(name="last_name")
    private String lastName;

    @Column(name="email", nullable=false)
    private String email;

    @Column(name="state", nullable=false)
    private String state=UserState.ACTIVE.getState();

    @ManyToMany(fetch = FetchType.EAGER)
    @Fetch(FetchMode.SELECT)
    @JoinTable(name = "hrm_user_user_profile", 
        joinColumns = { @JoinColumn(name = "id_user", referencedColumnName="id") },
        inverseJoinColumns = { @JoinColumn(name = "id_profile", referencedColumnName="id") })
    @Cascade(org.hibernate.annotations.CascadeType.ALL)
    private Set<UserProfile> userProfiles;

UserProfile

@Entity
@Table(name="user_profile")
public class UserProfile extends BasePojo {

private static final long serialVersionUID = 1L;

    @Column(name="type", length=15, unique=true, nullable=false)
    private String type = UserProfileType.USER.getUserProfileType();

    // Constructor used only for initial data loading, not used after
    public UserProfile() {
    }

    // Constructor used only for initial data loading, not used after
    public UserProfile(String type) {
        super();
        this.type = type;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

UserState

public enum UserState {

    LOCKED("state.locked"),
    INACTIVE("state.inactive"),
    ACTIVE("state.active");

    String state;

    private UserState(final String state){
        this.state = state;
    }

    public String getState(){
        return state;
    }

我迷失在这里。我可以得到一些帮助吗?

1 个答案:

答案 0 :(得分:2)

我相信您正确地对用户进行了身份验证。但是,您的/ login POST处理程序方法需要确保后续请求的标头中包含cookie或令牌。

这样,您将按以下方式设置的规则

        .antMatchers("/", "/home/*", "/alert/*", "/scheduler/*", "/agent/*", "/ftp/*", "/smtp/*", "/sql/*").access("hasRole('USER')")
        .antMatchers("/benefit/*", "/client/*", "/contract/*", "/role/*", "/structure/*", "/term/*").access("hasRole('USER')")
        .antMatchers("/", "/home/*", "/alert/*", "/scheduler/*", "/agent/*", "/ftp/*", "/smtp/*", "/sql/*").access("hasRole('ADMIN')")
        .antMatchers("/benefit/*", "/client/*", "/contract/*", "/role/*", "/structure/*", "/term/*").access("hasRole('ADMIN')")
        .antMatchers("/admin/**").access("hasRole('ADMIN')")
        .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")

例如,假设用户正在尝试访问/ home。由于用户未经过身份验证,因此会将其重定向到登录页面。用户输入他的用户名和密码,现在进行身份验证。完成此操作后,默认情况下,spring security会将用户重定向到返回URL / home。默认情况下,Spring安全性会将cookie添加到响应中,以便每个后续请求都在请求中包含该cookie。我相信在你的情况下不会发生这种情况。我想更多地了解您的弹簧安全配置。用户身份验证是如何进行的?它是内存认证吗?或数据源身份验证?