简体   繁体   中英

Spring Security two roles implementation

I'm new to spring security method. I'm trying to implement two user's in my web application. (Admin Role & User Role) I have two re-directions pages using thymeleaf for admin it should drop to /admin/** and for users it should be /user/**

I've tried adding two spring security class using @order(1) and order(2) but still not working.. my aim is if the user logins and has roles in my security it should redirect to the correct pages.

Please see my code below

spring.queries.users-query=select email, password, enabled from user where email=?
spring.queries.roles-query=select u.email, r.role from user u inner join user_role ur on (u.id=ur.user_id) inner join role r on(ur.role_id=r.role_id) where u.email=?

    @Override
protected void configure(AuthenticationManagerBuilder auth)
        throws Exception {
    auth.
        jdbcAuthentication()
            .usersByUsernameQuery(usersQuery)
            .authoritiesByUsernameQuery(rolesQuery)
            .dataSource(dataSource)
            .passwordEncoder(bCryptPasswordEncoder);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/").permitAll()
        .antMatchers("/login").permitAll()
        .antMatchers("/register").permitAll()
        .antMatchers("/confirm").permitAll()
        .antMatchers("/forgotpassword").permitAll()
        .antMatchers("/criminal/getAllWantedCriminal").permitAll()
        .antMatchers("/criminal/viewCriminal").permitAll()
        .antMatchers("/admin/**").hasAuthority("ADMIN")
        .antMatchers("/user/**").hasAuthority("USER")
        .anyRequest()
        .authenticated().and().csrf().disable().formLogin()
        .loginPage("/login").failureUrl("/login?error=true")
        .defaultSuccessUrl("/admin/home")
        .usernameParameter("email")
        .passwordParameter("password")
        .and().logout()
        .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
        .logoutSuccessUrl("/").and().exceptionHandling()
        .accessDeniedPage("/access-denied");
}

The easiest way to achieve this is creating a custom org.springframework.security.web.authentication.AuthenticationSuccessHandler

There, once the user has correctly logged in, you could just check wether the Authentication object has ROLE_ADMIN to redirect to default configured success url (the default user success url) or to the admin one. This is a working sample, extending org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler :

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;

public class RoleBasedAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler
        implements AuthenticationSuccessHandler {

    private String adminRoleTargetUrl;

    private String adminRoleAuthority;

    /**
     * @param defaultTargetUrl
     */
    public RoleBasedAuthenticationSuccessHandler(String defaultTargetUrl, String adminRoleTargetUrl, String adminRoleAuthority) {
        super(defaultTargetUrl);
        this.adminRoleTargetUrl = adminRoleTargetUrl;
        this.adminRoleAuthority = adminRoleAuthority;
    }

    /* (non-Javadoc)
     * @see org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler#onAuthenticationSuccess(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.Authentication)
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {
        if(isAdmin(authentication)){
            this.getRedirectStrategy().sendRedirect(request, response, this.getAdminRoleTargetUrl());
            return;
        }
        super.onAuthenticationSuccess(request, response, authentication);
    }

    /**
     * @param authentication
     */
    protected boolean isAdmin(Authentication authentication) {
        for(GrantedAuthority authority : authentication.getAuthorities()){
            if(authority.getAuthority().equals(this.getAdminRoleAuthority())){
                return true;
            }
        }
        return false;
    }

    /**
     * @return the adminRoleTargetUrl
     */
    public String getAdminRoleTargetUrl() {
        return adminRoleTargetUrl;
    }

    /**
     * @return the adminRoleAuthority
     */
    public String getAdminRoleAuthority() {
        return adminRoleAuthority;
    }   

}

Then, change your security config class in order to set the RoleBasedAuthenticationSuccessHandler instance in method successHandler instead of using defaultSuccessUrl :

@Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.
        jdbcAuthentication()
        .usersByUsernameQuery(usersQuery)
        .authoritiesByUsernameQuery(rolesQuery)
        .dataSource(dataSource)
        .passwordEncoder(bCryptPasswordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
        .antMatchers("/").permitAll()
        .antMatchers("/login").permitAll()
        .antMatchers("/register").permitAll()
        .antMatchers("/confirm").permitAll()
        .antMatchers("/forgotpassword").permitAll()
        .antMatchers("/criminal/getAllWantedCriminal").permitAll()
        .antMatchers("/criminal/viewCriminal").permitAll()
        .antMatchers("/admin/**").hasAuthority("ADMIN")
        .antMatchers("/user/**").hasAuthority("USER")
        .anyRequest()
        .authenticated().and().csrf().disable().formLogin()
        .loginPage("/login").failureUrl("/login?error=true")
        .successHandler(this.getSuccessHandler())
        .usernameParameter("email")
        .passwordParameter("password")
        .and().logout()
        .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
        .logoutSuccessUrl("/").and().exceptionHandling()
        .accessDeniedPage("/access-denied");
    }

    private AuthenticationSuccessHandler getSuccessHandler() {
        return new RoleBasedAuthenticationSuccessHandler(
                    "/user/home",
                    "/admin/home",
                    "ROLE_ADMIN"                
                );

    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM