How to restrict routes in spring security dynamically?

半城伤御伤魂 提交于 2021-02-08 08:57:18

问题


Good day,

I am using spring security to restrict user, and i am using mongodb.

I have created UserDetail and userDetail Services.

her is my webSecurity config.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Bean
    public UserDetailsService mongoUserDetails() {
        return new CustomUserDetailsService();
    }

    @Bean
    public DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(mongoUserDetails());
        authProvider.setPasswordEncoder(new BCryptPasswordEncoder());
        return authProvider;
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authProvider());
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home", "/static/unsecure/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();

    }

}

I am storing permissions in database like this.

"permissions" : [
    "/reports/report1", 
    "/reports/report2"
]

and here is userDetail service.

public class MongoUserDetails implements UserDetails {

    private final String username;
    private final String password;
    private final List<GrantedAuthority> grantedAuthorities;
    private final boolean enabled;

    public MongoUserDetails(String username, String password, String[] authorities, boolean isEnabled) {
        this.username = username;
        this.password = password;
        this.grantedAuthorities = AuthorityUtils.createAuthorityList(authorities);
        this.enabled = isEnabled;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return grantedAuthorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }
}

in private final List grantedAuthorities; I have successfully stored authorites. which are "/reports/report1", "/reports/report2"

When i run my web application it is redirecting my to login page and after valid credentials it redirects my to /hello page.

Now i am creating controllers and actions like

@Controller
@ResponseBody
public class MyController {

    @GetMapping("/user/greeting")
    public String greeting(HttpServletRequest request){
        return "welcome secure";
    }

    @GetMapping("/login1")
    public String greeting1(HttpServletRequest request){

    }

}

so since List grantedAuthorities; does not contains this route it should not allowed the user for this action

how can i achieve this. assuming all authorities are dynamic.

thanks.


回答1:


My example: Authentication service:

@Service
public class AuthService implements UserDetailsService {

    @Autowired
    private UserJpaRepository userJpaRepository;
    @Autowired
    private UserProfileJPARepository profileJPARepository;
    @Autowired
    private UserProfileContainer profileContainer;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = (User) userJpaRepository.findByLogin(username);
        GrantedAuthority authority = new SimpleGrantedAuthority(user.getRole().name());
        UserDetails userDetails = (UserDetails) new SecureUser(
                user.getId(),
                user.getFirstName(),
                user.getLastName(),
                user.getEmail(),
                user.getMobileNumber(),
                user.getLogin(),
                user.getPassword(),
                user.isActive(),
                true,
                true,
                true,
                Arrays.asList(authority)
        );
        user.setLastLogonTime(new Timestamp((new Date()).getTime()));
        userJpaRepository.saveAndFlush(user);
        profileContainer.setUser(user);
        return userDetails;
    }

}

Session scoped bean:

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserProfileContainer {
    private User user = null;

    public UserProfileContainer() {
    }

    public void setUser(User user) {
        this.user = user;
    }

    public User getUser() {
        return user;
    }
}

And in User class you cal store a List<String> allowedURLS = new ArrayList<>();

AFTER EDIT:

I've wrote this example. In this case I have some SecureUser.class which extends org.springframework.security.core.userdetails.User and in this class I have Set<String> allowedPathSet actually HashSet. And here is the custom filter:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomerFilter implements Filter {

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    // nothing here...
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpSession session = req.getSession(true);

    SecurityContextImpl sci = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT");
    if (sci != null) {
      SecureUser user = (SecureUser) sci.getAuthentication().getPrincipal();
      String url = req.getRequestURI();
      if (!user.path.contains("url")) ((HttpServletResponse) response).sendRedirect("http://redirect-URL-Here/");
    }
    chain.doFilter(request, response);
  }

  @Override
  public void destroy() {

  }
}

This example isn't a silver bullet but the main idea is present here and it work.



来源:https://stackoverflow.com/questions/49630272/how-to-restrict-routes-in-spring-security-dynamically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!