如何动态限制spring安全性中的路由?

时间:2018-04-03 12:36:55

标签: java spring spring-mvc spring-boot spring-security

美好的一天,

我使用spring security来限制用户,我正在使用mongodb。

我创建了UserDetail和userDetail Services。

她是我的webSecurity配置。

@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();

    }

}

我将权限存储在数据库中。

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

这是userDetail服务。

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;
    }
}

在私人最终名单中授予权力;我已成功存储了授权人。这是“/ reports / report1”,“/ reports / report2”

当我运行我的Web应用程序时,它会重定向到登录页面,在有效凭据之后,它会重定向到/ hello页面。

现在我正在创建像

这样的控制器和动作
@Controller
@ResponseBody
public class MyController {

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

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

    }

}

所以自List grantAuthorities;不包含此路由,不应允许用户执行此操作

我怎样才能做到这一点。假设所有权威都是动态的。

感谢。

1 个答案:

答案 0 :(得分:1)

我的例子: 身份验证服务:

@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;
    }

}

会话范围的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;
    }
}

在User类中,您可以存储List<String> allowedURLS = new ArrayList<>();

编辑后:

我写过这个例子。在这种情况下,我有一些SecureUser.class扩展org.springframework.security.core.userdetails.User,在这个类中我有Set<String> allowedPathSet实际上是HashSet。这是自定义过滤器:

@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() {

  }
}

这个例子不是灵丹妙药,但主要思想存在于此处并且有效。