如何动态限制spring security中的路由? [英] How to restrict routes in spring security dynamically?

查看:44
本文介绍了如何动态限制spring security中的路由?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

美好的一天,

我使用 spring security 限制用户,我使用 mongodb.

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

我已经创建了 UserDetail 和 userDetail 服务.

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"
]

这里是 userDetail 服务.

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

在私人最终列表中授予权限;我已成功存储权限.分别是/reports/report1"、/reports/report2"

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

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

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.

谢谢.

推荐答案

我的例子:认证服务:

@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:

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

在 User 类中,你可以存储一个 List;allowedURLS = new ArrayList<>();

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

修改后:

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

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.

这篇关于如何动态限制spring security中的路由?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆