问题
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