简体   繁体   中英

Java Spring RestController cannot implement custom interface

I am completely new to Spring and was tasked to create an application that enables SSO by authenticating a user using Azure Active Directory. I have a strict rule where I need to use an interface (provided from a vendor) that defines one method as such:

public String authenticate(HttpServletRequest request);

This method will be invoked from our vendor's software in order to authenticate the user. The string returned needs to be the user principal name. I followed official documentation on how to incorporate Azure Active Directory using spring security and was able to retrieve my user information in a controller! The problem I am having is when I implement the vendor interface the method no longer works and reports the following error message:

There was an unexpected error (type=Not Found, status=404).

I have done research online where you can have annotations on the interface level and implement it on the controller, but I do not have access to the vendor interface, which is only provided to me through an external JAR file. I've also seen suggestions where you can update the application.properties file and set the following parameter to true, but this did not help:

spring.aop.proxy-target-class=true

Any help would be wonderful and I apologize if I missed any important details due to being new to the ecosystem. Below is my code:

AuthController:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.access.prepost.PreAuthorize;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import com.generic.CustomerVendorInterface;


@RestController
public class AuthController implements CustomVendorInterface {

   @RequestMapping("/")
   @PreAuthorize("isAuthenticated()")
   @Override
   public String authenticate(HttpServletRequest request) {
       String username = null;
       OAuth2User user = ((OAuth2AuthenticationToken)request.getUserPrincipal()).getPrincipal();
       if (user != null)
           username = user.getAttribute("upn");
       return username;
   }
}

WebSecurityConfig:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .oauth2Login()
            .userInfoEndpoint()
            .oidcUserService(oidcUserService);
    }
}

I suggest separating your controller and authentication into different classes. Here's how you can implement CustomVenderInterface :

@Component
public class Authenticator implements CustomVenderInterface {

   @Override
   public String authenticate(HttpServletRequest request) {
       String username = null;
       OAuth2User user = ((OAuth2AuthenticationToken)request.getUserPrincipal()).getPrincipal();
       if (user != null)
           username = user.getAttribute("upn");
       return username;
   }

}

Then your controller class would look like this:

@RestController
public class AuthController {
  
   private final Authenticator authenticator;

   public AuthController(Authenticator authenticator) {
       this.authenticator = authenticator;
   }

   @RequestMapping("/")
   @PreAuthorize("isAuthenticated()")
   public String handleAuthRequest(HttpServletRequest request) {
       return authenticator.authenticate(request);
   }
}

Please show how you are passing your CustomVenderInterface to your vendor's library.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM