假设我有简单的bean,它可以通过密码验证用户,也知道任何指定用户的角色:
interface MyBeanInterface {
boolean check(String username, String password);
List<String> roles(String username);
}
使用基本HTTP安全性将此功能插入Spring Web应用程序的最简单方法是什么?
同时,我想仅使用@Secured
注释来注释我的控制器和服务方法。请没有任何以点分隔的谓词like here。
我无法在Spring Security API中突破众多“populator”,“manager”,“adapter”和其他“configurers”...
更新
我写道:
1)从控制器返回的Greeting
类
2)用于投放网络请求GreetingController
和/greeting1
的{{1}}课程。我使用/greeting2
注释第一个方法,使用@Secured({"USER", "ADMIN"})
注释第二个方法。
3)我写了@Secured({"ADMIN"})
我在其中验证了两个具有不同访问级别的用户。
4)我写了MyAuthService
,其中实现了AuthenticationProviderEx
方法,调用了authenticate()
bean。
5)我写了MyAuthService
bean,SecurityConfig
返回我的提供者。
代码为here in commit fdc2466。在这种状态下,它根本不会要求身份验证。
更新2
我已将configure()
添加到@EnableGlobalMethodSecurity(securedEnabled = true)
类,但它开始询问用户名和密码,但遗憾的是,在任何请求中都会返回错误SecurityConfig
。
答案 0 :(得分:2)
在您的界面周围创建一个自定义身份验证提供程序包装器,如:
@Component("customAuthenticationProvider")
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private MyBeanInterface myInterface;
public Authentication authenticate(Authentication authentication) {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
if (!myInterface.check(username, password)) {
throw new BadCredentialsException("Bad username or password.");
}
List<GrantedAuthority> authorities = new ArrayList<>();
for (String role : myInterface.roles(username)) {
authorities.add(new SimpleGrantedAuthority(role));
}
return new UsernamePasswordAuthenticationToken(username, password, authorities);
}
public boolean supports(Class<?> clazz) {
return UsernamePasswordAuthenticationToken.class.equals(clazz);
}
}
使用XML:
在安全配置中使用它<authentication-manager>
<authentication-provider ref="customAuthenticationProvider"/>
</authentication-manager>
更新:也适用于java配置:
@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(customAuthenticationProvider);
}
/* rest of security config here */
}
其余的都很正常。
答案 1 :(得分:1)
添加如下的java配置:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired YourAuthFilter youfilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(yourfilter, UsernamePasswordAuthenticationFilter.class);
}
}
和YourAuthFilter
会是这样的:
@Component
public class YourAuthFilter extends GenericFilterBean {
@Autowired private MyBeanInterface myBeanInterface;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// extract http basic tokens
// use your myBeanInterface to authenticate
// if it was successful, set Authentication
// by using SecurityContextHolder.getContext().setAuthentication(...)
// otherwise, do whatever suits your application needs
chain.doFilter(request, response);
}
}
holmis83方法要好得多,但如果你想在Java Config中使用它:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired CustomAuthenticationProvider customAuthenticationProvider;
@Override
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(customAuthenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic();
}
}