복붙노트

[SPRING] Liferay를 사용하여 REST 서비스에서 인증 및 권한 부여

SPRING

Liferay를 사용하여 REST 서비스에서 인증 및 권한 부여

우리는 RESTful API를 통해 노출 될 일부 서비스를 구축 중입니다. 이 API의 주요 고객은 Angular JS를 사용하는 Liferay 포틀릿입니다. 즉 클라이언트 측 (Angular)에서 Google 서비스로의 직접 호출이 있음을 의미합니다.

지금까지 우리는 인증 된 사용자 (Liferay)가 우리의 API를 요청하고 있음을 확인할 수 있도록 인증 및 권한 부여 메커니즘을 설계했습니다.

추신 : Liferay를 사용하고 있지만 다른 Java 기반 응용 프로그램이 될 수 있습니다.

우리가 설계 한 것은 :

이 디자인은 현재 우리에게 일관성이 있으며,이 토큰을 만드는 알고리즘에 따라 안전한 접근이라고 믿습니다.

우리의 의심은 :

미리 감사드립니다. 어떤 도움을 주셔서 감사합니다.

Filipe

해결법

  1. ==============================

    1.스프링 보안은 문제 설명을 해결하고 보너스로 모든 무료 보안 기능을 무료로 제공합니다.

    스프링 보안은 문제 설명을 해결하고 보너스로 모든 무료 보안 기능을 무료로 제공합니다.

    Token 접근법은 훌륭합니다. 여기 스프링 보안을 사용하여 API를 보호하는 방법이 있습니다. AuthenticationEntryPoint를 구현하고 시작 방법을 다음과 같이 3XX 방향을 바꾸지 않고 401로 설정합니다.

    httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,"Access Denied");
    

    @보수

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
                    HttpServletRequest httpRequest = this.getAsHttpRequest(request);
                    String authToken = this.extractAuthTokenFromRequest(httpRequest);
                    String userName = TokenUtils.getUserNameFromToken(authToken);
                    if (userName != null) {
                    UserDetails userDetails = userDetailsService.loadUserByUsername(userName);
    
                        if (TokenUtils.validateToken(authToken, userDetails)) {
                            UsernamePasswordAuthenticationToken authentication =new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
                            SecurityContextHolder.getContext().setAuthentication(authentication);
                        }
                    }
                    chain.doFilter(request, response);
                }
    

    Spring 보안 설정은 다음과 같습니다.

        @Configuration
        @EnableGlobalMethodSecurity(prePostEnabled = true)
        @EnableWebSecurity
        public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
            @Autowired
            private AuthFailure authFailure;
    
            @Autowired
            private AuthSuccess authSuccess;
    
            @Autowired
            private EntryPointUnauthorizedHandler unauthorizedHandler;
    
            @Autowired
            private UserDetailsService userDetailsService;
    
            @Autowired
            private AuthenticationTokenProcessingFilter authTokenProcessingFilter;
    
            @Autowired
            public void configureAuthBuilder(AuthenticationManagerBuilder auth) throws Exception {
                auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
            }
    
            @Bean
            @Override
            public AuthenticationManager authenticationManagerBean() throws Exception {
                return super.authenticationManagerBean();
            }
    
            @Bean public PasswordEncoder passwordEncoder(){
                return new BCryptPasswordEncoder();
            }
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http
                        .csrf().disable()
                        .sessionManagement()
                           .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // Restful hence stateless
                         .and()
                        .exceptionHandling()
                        .authenticationEntryPoint(unauthorizedHandler) // Notice the entry point
                        .and()
                        .addFilter(authTokenProcessingFilter) // Notice the filter
                        .authorizeRequests()
                           .antMatchers("/resources/**", "/api/authenticate").permitAll()                 
                           //.antMatchers("/admin/**").hasRole("ADMIN")
                           //.antMatchers("/providers/**").hasRole("ADMIN") 
                        .antMatchers("/persons").authenticated();
            }
    
    }
    

    - 마지막으로 인증 및 토큰 생성을위한 또 다른 엔드 포인트가 필요합니다. 여기에 봄 MVC 예제가있다.

    @Controller
    @RequestMapping(value="/api")
    public class TokenGenerator{
        @Autowired
        @Lazy
        private  AuthenticationManager authenticationManager;
    
        @Autowired
        private  UtilityBean utilityBean;
    
        @Autowired
        private  UserDetailsService userDetailsService;
    
    
        @RequestMapping(value="/authenticate", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
        ResponseEntity<?> generateToken(@RequestBody EmefanaUser user){
            ResponseEntity<?> response = null;
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserId(),user.getCredential());
    
            try {
                Authentication authentication = authenticationManager.authenticate(authenticationToken);
                SecurityContextHolder.getContext().setAuthentication(authentication);
    
                /*
                 * Reload user as password of authentication principal will be null
                 * after authorization and password is needed for token generation
                 */
                UserDetails userDetails = userDetailsService.loadUserByUsername(user.getUserId());
                String token = TokenUtils.createToken(userDetails);
                response = ResponseEntity.ok(new TokenResource(utilityBean.encodePropertyValue(token)));
            } catch (AuthenticationException e) {
                response = ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
            }
            return response;
        } 
    
    }
    

    1 토큰 생성, 2. 후속 API 호출에는 토큰이 있어야합니다.  예 스프링 보안이 이것을 할 수 있으며 인증, 승인에서 새로운 토대를 깰 필요가 없습니다.

  2. ==============================

    2.Single Sign On 및 Spring Security OAuth2 토큰 인증을 살펴보십시오.

    Single Sign On 및 Spring Security OAuth2 토큰 인증을 살펴보십시오.

    예를 들면 다음과 같습니다. sso-with-oauth2-angular-js-and-spring-security.

    Spring 4.2는 CORS를 지원할 수 있습니다.

  3. ==============================

    3.나는 현재의 평점으로 누군가의 대답을 높일 수는 없지만 위의 대답은 아마도 올바른 방향 일 것이다. 조사 할 필요가있는 것처럼 들리는 것은 크로스 사이트 스크립팅으로 보안을 제공하는 CORS라는 것입니다. 미안하지만 어떻게 작동하는지 아직 모르겠다. (나는 같은 상황에있다.)하지만 이것이 REST에 관한이 NSA 문서의 주요 주제이다.

    나는 현재의 평점으로 누군가의 대답을 높일 수는 없지만 위의 대답은 아마도 올바른 방향 일 것이다. 조사 할 필요가있는 것처럼 들리는 것은 크로스 사이트 스크립팅으로 보안을 제공하는 CORS라는 것입니다. 미안하지만 어떻게 작동하는지 아직 모르겠다. (나는 같은 상황에있다.)하지만 이것이 REST에 관한이 NSA 문서의 주요 주제이다.

    봄에, 어쩌면 시작 하시겠습니까?

  4. ==============================

    4.나는 파티에 늦었지만 여기에는 두 센트가있다.

    나는 파티에 늦었지만 여기에는 두 센트가있다.

    내가 그 질문을 정확하게 이해한다면, 여기에 두 가지 시나리오가 있습니다. 첫 번째 것은 이미 로그인 한 사용자가 호출 할 RESTful API를 만들어야한다는 것입니다. 즉, AJAX 호출은 아마도 클라이언트의 포털 렌더링 내에서 실행됩니다. 여기서 가장 중요한 문제는 보안, REST 호출을 보호하는 방법입니다. 무엇보다도 먼저 다른 프레임 워크를 사용하기 전에 어떤 프레임 워크를 사용하든간에 활용하려고 노력해야한다고 생각합니다. Liferay는 백엔드에서 Spring을 사용하지만 이미 보안을 구현했습니다. 위임 서블릿을 사용하는 것이 좋습니다. 이 서블릿은 모든 사용자 정의 클래스를 실행하고 Liferay의 인증 경로에 넣습니다. 즉, PortalUtil.getUser (request)를 사용할 수 있으며 0 또는 null 인 경우 사용자는 인증되지 않습니다. 위임 서블릿을 사용하려면 web.xml 파일에서 구성해야합니다.

    <servlet>
        <servlet-name>My Servlet</servlet-name>
        <servlet-class>com.liferay.portal.kernel.servlet.PortalDelegateServlet</servlet-class>
        <init-param>
            <param-name>servlet-class</param-name>
            <param-value>com.samples.MyClass</param-value>
        </init-param>
        <init-param>
            <param-name>sub-context</param-name>
            <param-value>api</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>
    

    보시다시피 우리는 다른 서블릿을 인스턴스화합니다. 이 서블릿은 PortalDelegateServlet에 의해 정의 될 것입니다. Delegate Servlet은 sevlet-class param 값에있는 클래스를 사용합니다. 이 클래스 내에서 Liferay의 Utils가있는 HttpServletRequest 객체에 유효한 사용자 이름이 있는지 확인할 수 있습니다. 사용자가 있으면 OK입니다. 이제이 방법에 액세스하는 방법은 Delegate Servlet이 하위 컨텍스트 값을 사용하여 URL에서 참조하는 클래스를 확인하는 것입니다. 따라서이 예제에서는 https : //my.portal/delegate/api로 이동하여 com.samples.MyClass에 액세스하게됩니다. '대리자'부분이 항상있을 것이고, URL의 두 번째 부분은 init-param. 하위 컨텍스트에 대해 URI의 한 수준 만 정의 할 수 있습니다. 즉, 하위 컨텍스트로 /api/v2.0/을 설정할 수 없습니다. 그때부터 서블릿 클래스에서 원하는 모든 작업을 수행하고 원하는대로 REST URI 구문 분석을 처리 할 수있다.

    또한 Delegate Servlet이 호출 할 클래스로 Spring의 Dispatcher 클래스를 사용할 수 있으며 스프링 서블릿을 설정하기 만하면 url 주석 mappins가 생깁니다.

    두 번째 시나리오는 외부 애플리케이션에서이 RESTful API를 호출 할 수 있어야한다 (구현에 상관 없다). 이것은 완전히 다른 짐승이고 iamiddy가 대답을 참조해야하고 Spring의 인증 토큰을 사용하는 것이 좋은 방법 일 수 있습니다.

    이를 수행하는 또 다른 방법은 로그인 페이지 나 종류의 것들로 보내서 서블릿 클래스의 승인되지 않은 사용자를 처리하는 것입니다. 일단 그들이 성공적으로 Liferay의 Utils에 로그인하면 요청 된 인증 된 사용자를 인식해야합니다. 외부 응용 프로그램 내에서이 작업을 수행하려면 양식 기반 로그인을 모방하고 전체 시간 동안 동일한 쿠키 항아리를 사용해야합니다. 나는 이것을 시도하지는 않았지만, 이론 상으로는 효과가있다. 그리고 다시 이론 상으로는 공산주의가 작동합니다.

    희망이 거기에 다른 가난한 영혼을 도와주세요.

  5. from https://stackoverflow.com/questions/28242604/authentication-and-authorization-in-rest-services-with-liferay by cc-by-sa and MIT license