我有一个Spring Boot应用程序,该应用程序应提供AD身份验证,并使用存储在数据库中的权限来授权请求。 Ldap身份验证工作正常。我在Spring Security Java Configuration类中放入的授权设置有问题,因为它不起作用。我以在数据库中具有SYSTEM_LOGIN权限的用户身份登录,但 .antMatchers(“ / requests / **”)。hasAuthority(“ SYSTEM_LOGIN”)不允许他访问/ requests URL(带有403禁止响应)
我尝试实现CustomSecurityExpressionRoot和CustomSecurityExpressionHandler,但没有帮助。可能我以错误的方式将其注入配置...
这是我的SpringSecurity Java配置:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${ldap.urls:ldap://host:port/dc=test,dc=local}")
private String ldapUrls;
@Value("${ldap.filter:(&(objectClass=user)(sAMAccountName={0}))}")
private String ldapFilter;
@Value("${ldap.managerDn:test}")
private String ldapManagerDn;
@Value("${ldap.managerPassword:testpass}")
private String ldapManagerPassword;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login*").permitAll()
.antMatchers("/requests/**").hasAuthority("SYSTEM_LOGIN")
.anyRequest().permitAll()
.and()
.logout().deleteCookies("JSESSIONID")
.and()
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
CustomJdbcUserDetailsService customJdbcUserDetailsService = new CustomJdbcUserDetailsService();
customJdbcUserDetailsService.setDataSource(dataSource);
CustomLdapAuthoritiesPopulator customLdapAuthoritiesPopulator = new CustomLdapAuthoritiesPopulator(customJdbcUserDetailsService);
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldapUrls);
contextSource.setUserDn(ldapManagerDn);
contextSource.setPassword(ldapManagerPassword);
contextSource.setReferral("follow");
contextSource.afterPropertiesSet();
LdapUserSearch ldapUserSearch = new FilterBasedLdapUserSearch("", ldapFilter, contextSource);
BindAuthenticator bindAuthenticator = new BindAuthenticator(contextSource);
bindAuthenticator.setUserSearch(ldapUserSearch);
LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider(bindAuthenticator);
auth.authenticationProvider(ldapAuthenticationProvider);
auth.ldapAuthentication().ldapAuthoritiesPopulator(customLdapAuthoritiesPopulator).
userDnPatterns("uid={0},ou=users").contextSource(contextSource);
}
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public AuthTokenService tokenService() {
return new AuthTokenService();
}
@Bean
public CustomSecurityExpressionHandler expressionHandler() {
return new CustomSecurityExpressionHandler();
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
这是登录控制器:
@Slf4j
@RestController
public class LoginController {
private static Map<String, Object> defaultMapToReturn = new HashMap<>();
@Autowired
private ADAuthService authenticationService;
@RequestMapping(
value = "/login",
method = RequestMethod.POST)
public Map<String, Object> getLogin(@RequestBody UIAuthenticationRequest request) throws TokenAlreadyExistsException {
AuthToken authToken = authenticationService.authenticateUser(request);
defaultMapToReturn.put("token", authToken.getTokenValue());
defaultMapToReturn.put("userPermissions", authToken.getUser().getAuthorities());
return defaultMapToReturn;
}
服务代码:
@Service
public class ADAuthService {
@Autowired
private SuidRolesRepository rolesRepository;
@Autowired
private PermissionRepository permsRepository;
/**
* Authentication Manager from spring security context.
*/
@Autowired
private AuthenticationManager authenticationManager;
/**
* AuthTokenService which validates tokens.
*/
private AuthTokenService authTokenService;
@Autowired
@Qualifier("sessionRegistry")
private SessionRegistry sessionRegistry;
/**
* Constructor injection of AuthenticationManager and AuthTokenService
*/
@Autowired
public ADAuthService(AuthenticationManager authenticationManager, AuthTokenService authTokenService) {
this.authenticationManager = authenticationManager;
this.authTokenService = authTokenService;
}
public AuthToken authenticateUser(UIAuthenticationRequest request) throws TokenAlreadyExistsException {
List<SuidRole> roles = rolesRepository.findByUser(request.getUsername());
List auths = new ArrayList(getPermissions(roles));
final Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword(), auths)
);
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
UserDetails userDetails = new ADUserDetails(
request.getUsername(),
request.getPassword(),
getPermissions(roles)
);
AuthToken authToken = new AuthToken(UUID.randomUUID().toString(), LocalDateTime.now(), userDetails);
authTokenService.storeToken(authToken);
return authToken;
}
在调试时,我看到当我使用url / requests / **调用请求时,它转到SecurityExpressionRoot类,在方法hasAuthority()中,但是SecurityExpressionRoot内部的身份验证对象具有主体=“ anonymousUser”,并且在权限中仅列出了“ ROLE_ANONYMOUS”,其中显然不是我所期望的。