Ошибка 404: javax.servlet.ServletException: java.io.FileNotFoundException: SRVE0190E: файл не найден: / oidcclient / redirect / MyRP

Я пытаюсь интегрировать службу AppID с моим весенним приложением. Для этого я добавил redirect-uri https: // app-host-name: номер-порта / oidcclient / redirect / MyRP в службу MyAppId - ›Управление -› Настройки аутентификации с целью перенаправления обратно в приложение после аутентификации учетных данных пользователя.

Теперь проблема в том, что когда пользователь пытается войти в приложение после ввода учетных данных, он не перенаправляется на uri, который я указал в своем коде приложения, вместо этого он дает код 404, указанный в теме.

Просмотрите указанный ниже код, относящийся к части реализации AppID, и предложите мне решение этой проблемы.

Ниже приводится технологический стек приложения: -

1.Spring (4.3.0.RELEASE)
2.Spring Security (4.1.1.RELEASE)
3.Websphere Liberty (20.0.0.1)

Я реализовал код интеграции в соответствии с официальным репозиторием кода IBM для AppID на https://github.com/ibm-cloud-security/app-id-sample-java

В код приложения внесены следующие изменения: -

server.xml

<!-- Enable features -->
<featureManager>
    <feature>jsp-2.3</feature>
    <feature>localConnector-1.0</feature>
    <!-- Features for APP ID -->
    <feature>servlet-3.1</feature>
    <feature>appSecurity-2.0</feature>
    <feature>openidConnectClient-1.0</feature>
    <feature>ssl-1.0</feature>
</featureManager>

<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
<httpEndpoint httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint"/>
              
<!-- Automatically expand WAR files and EAR files -->
<applicationManager autoExpand="true" startTimeout="15m"/>


<applicationMonitor updateTrigger="mbean"/>

<keyStore id="defaultKeyStore" password="${keystore_password}"/>
<keyStore id="digicertRootCA" location="${server.config.dir}/resources/security/digicert-root-ca.jks" password="digicert"/>
<ssl id="oidcClientSSL" keyStoreRef="defaultKeyStore" trustStoreRef="digicertRootCA"/>



  <authFilter id="myAuthFilter">
    <requestUrl id="myRequestUrl" urlPattern="/appid_callback" matchType="contains"/>
</authFilter>


<openidConnectClient id="MyRP"
                     clientId="${env.APP_ID_CLIENT_ID}"
                     clientSecret= "${env.APP_ID_CLIENT_SECRET}"
                     authorizationEndpointUrl="${env.APP_ID_OAUTH_SERVER_URL}/authorization"
                     tokenEndpointUrl="${env.APP_ID_OAUTH_SERVER_URL}/token"
                     jwkEndpointUrl="${env.APP_ID_OAUTH_SERVER_URL}/publickeys"
                     issuerIdentifier="${env.APP_ID_ISSUER_IDENTIFIER}"
                     tokenEndpointAuthMethod="basic"
                     signatureAlgorithm="RS256"
                     authFilterid="myAuthFilter"
                     redirectToRPHostAndPort="https://${env.APP_ID_HOSTNAME}.${env.APP_ID_DOMAIN}"
/> 
 
<application id="ne" location="ne-1.0.0-BUILD-SNAPSHOT.war" name="ne">
    <application-bnd>
        <security-role name="appidrole">
                    <special-subject type="ALL_AUTHENTICATED_USERS" />
        </security-role>
    </application-bnd>
 </application>  
 

web.xml

<web-app 
xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 
version="3.1">

<display-name>MyWebApp</display-name>

<security-role>
    <role-name>appidrole</role-name>
</security-role>

<servlet>
    <servlet-name>AppIdCallbackServlet</servlet-name>
    <servlet-class>com.example.appid.AppIdCallBackServlet</servlet-class>
</servlet>

<servlet>
    <servlet-name>LogoutServlet</servlet-name>
    <servlet-class>com.example.appid.AppIdLogoutServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>AppIdCallbackServlet</servlet-name>
    <url-pattern>/appid_callback</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>LogoutServlet</servlet-name>
    <url-pattern>/logout</url-pattern>
</servlet-mapping>

<security-constraint>
    <display-name>Security Constraints</display-name>
    <web-resource-collection>
        <web-resource-name>Security Constraint</web-resource-name>
        <url-pattern>/appid_callback/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>PUT</http-method>
        <http-method>POST</http-method>
        <http-method>DELETE</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>appidrole</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
</security-constraint>

<!-- <filter>
    <filter-name>FilterToGetTimeOut </filter-name> 
    <filter-class>example.common.filter.FilterToGetTimeOut </filter-class> 
</filter>
<filter-mapping> 
    <filter-name>FilterToGetTimeOut</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> -->

<session-config>
    <session-timeout>20</session-timeout>
</session-config>   

Сопоставление

@RequestMapping(value="/", method=RequestMethod.GET)
public String appidCallbackMapping(HttpServletRequest request, HttpServletResponse response)
{
    logger.info("present in appid callback mapping method created in UserController.java ===> [email protected]");
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    String idTokenRaw = null;
    try {
        idTokenRaw = getIDToken();
    } catch (IOException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
    }
    logger.info("calling getIdToken before checking whether auth object instanceof AnonymousAuthenticationToken ===> [email protected]");
    logger.info("idToken Value :- " + idTokenRaw);
    if (!(auth instanceof AnonymousAuthenticationToken)) {
        logger.info("authentication object found not to be an instance of AnonymousAuthenticationToken (successfully )===> [email protected]");
         try {
             idTokenRaw = getIDToken();
             logger.info("inside check of AnonymousAuthenticationToken --> tokenValue ===> " + idTokenRaw);
             if (idTokenRaw != null) {
                    String idTokenPayload = getTokenPayload(idTokenRaw);
                    // save the id_token and user's name on the request so that
                    // they can be passed on to UI elements
                    JSONObject idTokenContent = JSONObject.parse(idTokenPayload);
                    String username = idTokenContent.get("name").toString();
                    logger.info("Username value retrieved from appid token :- " + username);
                //    request.setAttribute("name", username);
                //   request.setAttribute("id_token", idTokenPayload);
                } else {
                    logger.info("No id_token located via security context");
                }
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
         UserDetails userDetail=null;
         userDetail = (UserDetails) auth.getPrincipal();
         ObjectMapper objectMapper = new ObjectMapper();
         try {
            logger.info(objectMapper.writeValueAsString(auth));
        } catch (JsonProcessingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
         
         String userId= userDetail.getUsername();
         
        logger.info("User Id of the user as follows :- " + userId); 
        return "redirect:/company";
    }
    else
        return "redirect:/appid_callback";
                
}

   private String getIDToken() throws IOException{
    Subject wasSubj;
    try {
        wasSubj = WSSubject.getRunAsSubject();
    } catch (WSSecurityException e) {
        // In real applications, exception should be handled better
        throw new IOException(e);
    }

    Set<Hashtable> creds = wasSubj.getPrivateCredentials(Hashtable.class);

    for (Hashtable hTable : creds) {
        if (hTable.containsKey("id_token")) {
            return hTable.get("id_token").toString();
        }
    }
    //return null if not found
    return null;
}

 private String getTokenPayload(String token) {
        String payload64 = token.split("\\.")[1];
        String payload = new String(Base64.decodeBase64(payload64));
        return payload;
    }

AppIdCallBackServlet.java

public class AppIdCallBackServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

private final static Logger logger = LogManager.getLogger(FileUploadController.class);

/**
 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
 */
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    logger.info("present in doGet nethod of appIdCallback method ==> [email protected]");
    
    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();
    try {
        String idTokenRaw = getIDToken();
        if (idTokenRaw != null) {
            String idTokenPayload = getTokenPayload(idTokenRaw);
            // save the id_token and user's name on the request so that
            // they can be passed on to UI elements
            JSONObject idTokenContent = JSONObject.parse(idTokenPayload);
            String username = idTokenContent.get("name").toString();
            logger.info("username value retrieved from token and currently present in AppIdCallbackServlet.java file ===> " + username);
            request.setAttribute("name", username);
            request.setAttribute("id_token", idTokenPayload);
        } else {
            out.println("No id_token located via security context");
        }
    } catch (Exception e) {
        // In real applications, exception should be handled better
        e.printStackTrace(out);
    }
    request.getRequestDispatcher("/").forward(request, response);
}

private String getTokenPayload(String token) {
    String payload64 = token.split("\\.")[1];
    String payload = new String(Base64.decodeBase64(payload64));
    return payload;
}

/*
This method uses Liberty API to extract a Hashtable object that contains
the App ID tokens.
 */
private String getIDToken() throws IOException{
    Subject wasSubj;
    try {
        wasSubj = WSSubject.getRunAsSubject();
    } catch (WSSecurityException e) {
        // In real applications, exception should be handled better
        throw new IOException(e);
    }

    Set<Hashtable> creds = wasSubj.getPrivateCredentials(Hashtable.class);

    for (Hashtable hTable : creds) {
        if (hTable.containsKey("id_token")) {
            return hTable.get("id_token").toString();
        }
    }
    //return null if not found
    return null;
}
  }

SecurityConfig.java

  @Override 
  protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests().antMatchers("/**").permitAll();
  }

person dlakra96    schedule 12.03.2021    source источник


Ответы (1)


В server.xml вместо <keyStore id="defaultKeyStore" password="${keystore_password}"/> <keyStore id="digicertRootCA" location="${server.config.dir}/resources/security/digicert-root-ca.jks" password="digicert"/> <ssl id="oidcClientSSL" keyStoreRef="defaultKeyStore" trustStoreRef="digicertRootCA"/>

Попробуйте использовать <keyStore id="defaultKeyStore" password="${keystore_password}"/> <ssl id="oidcClientSSL" keyStoreRef="defaultKeyStore" trustDefaultCerts="true" />

person Sachin Gupta    schedule 21.04.2021
comment
Спасибо, у меня сработало. - person dlakra96; 21.04.2021