基于注解的 Spring Security for REST API [英] Annotation based Spring Security for REST API

查看:57
本文介绍了基于注解的 Spring Security for REST API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试创建一个受 Spring 安全保护的 rest api

I have been trying to create a rest api secured with Spring security

有关架构详细信息,请参阅此链接:Spring Security with REST 架构

For the architecture details kindly see this link: Spring Security with REST architecture

但是,在我的实施过程中,我面临以下问题:

But, during my implementation I am facing following issues like :

异常启动过滤器 springSecurityFilterChain

Exception starting filter springSecurityFilterChain

我的应用程序实现就像:

My application implementation is like :

@EnableWebMvc
@Configuration
@ComponentScan({ "com.ws.service.*" })
public class AppConfig extends Application {
 ...
}

CustomJDBCDaoImpl

public class CustomJDBCDaoImpl extends JdbcDaoImpl {

    public CustomJDBCDaoImpl() {
        // TODO Auto-generated constructor stub
        super();

    }

    private DataSource getDataSourceFromJndi() {
        ...
    }

    @Override
    protected List<GrantedAuthority> loadGroupAuthorities(String username) {
     ...
    }

    @Override
    public UserDetails loadUserByUsername(String username) {
         ...
    }

    private UpUser findUserByScreenName(String userName) {
         ...
    }

    private ResultSet executeQuery(String sql){
         ...
    }
}

无状态身份验证过滤器的源代码

无状态身份验证安全配置

@EnableWebSecurity
@Configuration
@Order(1)
public class StatelessAuthenticationSecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private TokenAuthenticationService tokenAuthenticationService;

    public StatelessAuthenticationSecurityConfig() {
        super(true);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .exceptionHandling().and()
                .anonymous().and()
                .servletApi().and()
                .headers().cacheControl().and()
                .authorizeRequests()

                //allow anonymous resource requests
                .antMatchers("/").permitAll()
                .antMatchers("/favicon.ico").permitAll()
                .antMatchers("/resources/**").permitAll()

                //allow anonymous POSTs to login
                .antMatchers(HttpMethod.POST, "/api/login").permitAll()

                //allow anonymous GETs to API
                .antMatchers(HttpMethod.GET, "/api/**").permitAll()

                //defined Admin only API area
                .antMatchers("/admin/**").hasRole("ADMIN")

                //all other request need to be authenticated
                .anyRequest().hasRole("USER").and()             

                // custom JSON based authentication by POST of {"username":"<name>","password":"<password>"} which sets the token header upon authentication
                .addFilterBefore(new StatelessLoginFilter("/api/login", tokenAuthenticationService, new CustomJDBCDaoImpl(), authenticationManager()), UsernamePasswordAuthenticationFilter.class)

                // custom Token based authentication based on the header previously given to the client
                .addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(new CustomJDBCDaoImpl()).passwordEncoder(new BCryptPasswordEncoder());
    }


}

无状态登录过滤器

class StatelessLoginFilter extends AbstractAuthenticationProcessingFilter {

    private final TokenAuthenticationService tokenAuthenticationService;
    private final CustomJDBCDaoImpl userDetailsService;

    protected StatelessLoginFilter(String urlMapping, TokenAuthenticationService tokenAuthenticationService,
            CustomJDBCDaoImpl userDetailsService, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(urlMapping));
        this.userDetailsService = userDetailsService;
        this.tokenAuthenticationService = tokenAuthenticationService;
        setAuthenticationManager(authManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {

                final UsernamePasswordAuthenticationToken loginToken = new UsernamePasswordAuthenticationToken(
                request.getParameter("username").toString(), request.getParameter("password").toString());
        return getAuthenticationManager().authenticate(loginToken);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
            FilterChain chain, Authentication authentication) throws IOException, ServletException {

        // Lookup the complete User object from the database and create an Authentication for it
        final UserDetails authenticatedUser = userDetailsService.loadUserByUsername(authentication.getName());
        final UserAuthentication userAuthentication = new UserAuthentication(authenticatedUser);

        // Add the custom token as HTTP header to the response
        tokenAuthenticationService.addAuthentication(response, userAuthentication);

        // Add the authentication to the Security context
        SecurityContextHolder.getContext().setAuthentication(userAuthentication);
    }
}

令牌认证服务的源代码

令牌处理程序的源代码

此外,它直接将我重定向到服务,而不是向我显示输入用户名和密码的对话框.

Also it's directly redirecting me to the service instead of showing me a dialog to enter username and password.

推荐答案

我有类似的设置.不同的是,我有一个额外的 ContextLoaderListener 来加载 SpringSecurityFilerChain

i have a similar setup. the difference is, i have an additional ContextLoaderListener to load the SpringSecurityFilerChain

@WebListener
public class SpringContextLoader extends ContextLoaderListener {

    @Override
    protected WebApplicationContext createWebApplicationContext(final ServletContext sc) {
        AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
        applicationContext.register(SpringConfiguration.class);

        sc.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain")).addMappingForUrlPatterns(null, false, "/*");

        Dynamic dynamic = sc.addServlet("dispatcher", new DispatcherServlet(applicationContext));  
        dynamic.addMapping("/");  
        dynamic.setLoadOnStartup(1); 

        return applicationContext;
    }
}

这篇关于基于注解的 Spring Security for REST API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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