Spring RESTful Token Web Service Review

时间:2014-09-25 18:45:47

标签: java spring rest spring-mvc

我一直试图使用Spring.IO实现一个新的RESTful Web服务。我已经完成了大约30个不同的在线示例,这些示例假设提供了这个示例,但没有一个能够在开箱即用的情况下运行。

更复杂的是,95%的示例都使用XML配置,我个人认为这不像纯java配置那样可读。

经过了很长时间,我已经设法凑齐了一些可以工作的东西'但对于我的具体实施,我非常感兴趣。具体做法是:

  1. 假设客户端授权令牌没有受到损害,我的实施是安全的。
  2. 由于构造函数需要AuthenticationManager,我无法在AuthenticationTokenProcessingFilter中正确自动更新WebSecurityConfig类。如果有办法做到这一点,将有助于清理一些事情。
  3. 主要应用类:

    @ComponentScan({"webservice"})
    @Configuration
    @EnableAutoConfiguration
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    

    WebSecurityConfig类(AFAIK执行以前由XML执行的大部分工作):

    @Configuration
    @EnableWebMvcSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        AuthenticationTokenProcessingFilter authenticationTokenProcessingFilter;
    
        @Autowired
        CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
    
            authenticationTokenProcessingFilter = 
                new AuthenticationTokenProcessingFilter(authenticationManager());
    
            http
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                .authorizeRequests().antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                    .and()
                .addFilterBefore(authenticationTokenProcessingFilter, AnonymousAuthenticationFilter.class)
                .httpBasic().authenticationEntryPoint(customAuthenticationEntryPoint);
        }
    }
    

    在客户端连接上执行令牌身份验证的AuthenticationTokenProcessingFilter

    public class AuthenticationTokenProcessingFilter extends GenericFilterBean {
    
        AuthenticationManager authManager;
    
        public AuthenticationTokenProcessingFilter(AuthenticationManager authManager) {
            this.authManager = authManager;
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
    
            @SuppressWarnings("unchecked")
            Map<String, String[]> parms = request.getParameterMap();
    
            if(parms.containsKey("authToken")) {
                String token = parms.get("authToken")[0];
    
                // Validate the token
                User user = TokenUtils.getUserFromToken(token);
    
                // If we managed to get a user we can finish the authentication
                if (user!=null) {
                    //Add a default authority for all users
                    List<GrantedAuthority> grantedAuths = new ArrayList();
                    grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
    
                    // build an Authentication object with the user's info
                    AbstractAuthenticationToken authentication = 
                        new UsernamePasswordAuthenticationToken(user, token, grantedAuths);
    
                    // set the authentication into the SecurityContext
                    SecurityContextHolder.getContext().setAuthentication(authentication);         
                }
            }
    
            // continue thru the filter chain
            chain.doFilter(request, response);
        }
    }
    

    TokenUtils使用的AuthenticationTokenProcessingFilter类:

    public class TokenUtils {
    
        /**
         * Get an authorisation token for the provided userId
         * 
         * @param userId
         * @return 
         */
        public static String getToken(long userId) {
            throw new UnsupportedOperationException("Not implemented yet!");
        }
    
        /**
         * Attempt to get a user for the provided token
         * 
         * @param token
         * @return User if found, otherwise null
         */
        public static User getUserFromToken(String token) {
            throw new UnsupportedOperationException("Not implemented yet!");
        } 
    }
    

    CustomAuthenticationEntryPoint,如果用户未成功通过身份验证,则返回403:

    @Component
    public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response,
                AuthenticationException authException) throws IOException, ServletException {
    
            response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized: Authentication token was either missing or invalid." );
        }
    }
    

    最后我的网络服务入口点:

    @RestController
    public class EntryPoints {
    
        @RequestMapping(value = "/login", method={RequestMethod.POST})
        public LoginResponse login(@RequestParam(value="username", required=true) String username,
                @RequestParam(value="password", required=true) String password) {
    
            LoginRequest loginRequest = new LoginRequest(username, password);
    
            //Authenticate the user using the provided credentials
    
            //If succesfull return authentication token
            //return new LoginResponse(token);
    
            throw new UnsupportedOperationException("Not implemented yet!");
        }
    
        @RequestMapping(value = "/account", method={RequestMethod.POST})
        public AccountResponse account(@RequestParam(value="accountId", required=true) long accountId) {
    
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    
            //Return the request account information
    
            throw new UnsupportedOperationException("Not implemented yet!");
        }
    }
    

0 个答案:

没有答案