从令牌服务器(身份服务器 4)进行身份验证后,重定向到客户端的相同 URL

pav*_*any 5 reactjs asp.net-core identityserver4

我正在使用 Identity server 4 进行用户身份和令牌服务。我的客户端应用程序是用 .Net core React 模板编写的。一切工作正常,但是当最终用户点击客户端子 URL 页面(从电子邮件接收)时,它会重定向到 STS 身份服务器进行身份验证并返回主页,而不是返回用户点击 URL 中的子页面。乞讨。

例如,当用户点击客户端 URL ( https://localhost:44309/bills)(通过电子邮件接收)时,它将进入登录页面 ( https://localhost:44318/Login ),并且在用户身份验证后,它将重定向到( https://localhost:44309/Home ) 而不是 ( https://localhost:44309/bills )。

我使用 Identity server 4 编写的代码类似于下面的链接

https://github.com/damienbod/IdentityServer4AspNetCoreIdentityTemplate/tree/master/content/StsServerIdentity

身份服务器添加客户端


{
        "ClientId": "reactclient",
        "ClientName": "React Client",
        "Enabled": true,
        "RequireClientSecret": false,
        "EnableLocalLogin": true,
        "RequireConsent": false,
        "AllowedGrantTypes": [ "authorization_code", "hybrid", "client_credentials" ],
        "RedirectUris": [ "https://localhost:44309/signin-oidc" ],
        "PostLogoutRedirectUris": [ "https://localhost:44309/logout/callback" ],
        "AccessTokenType": "Jwt",
        "AllowAccessTokensViaBrowser": true,
        //"UpdateAccessTokenClaimsOnRefresh": true,
        "AllowOfflineAccess": true,
        "AccessTokenLifetime": 14400,
        "IdentityTokenLifetime": 7200,
        "AllowedScopes": [
          "openid",
          "profile",
          "email",
          "offline_access"
        ]
      }
Run Code Online (Sandbox Code Playgroud)

客户端


{
        "ClientId": "reactclient",
        "ClientName": "React Client",
        "Enabled": true,
        "RequireClientSecret": false,
        "EnableLocalLogin": true,
        "RequireConsent": false,
        "AllowedGrantTypes": [ "authorization_code", "hybrid", "client_credentials" ],
        "RedirectUris": [ "https://localhost:44309/signin-oidc" ],
        "PostLogoutRedirectUris": [ "https://localhost:44309/logout/callback" ],
        "AccessTokenType": "Jwt",
        "AllowAccessTokensViaBrowser": true,
        //"UpdateAccessTokenClaimsOnRefresh": true,
        "AllowOfflineAccess": true,
        "AccessTokenLifetime": 14400,
        "IdentityTokenLifetime": 7200,
        "AllowedScopes": [
          "openid",
          "profile",
          "email",
          "offline_access"
        ]
      }
Run Code Online (Sandbox Code Playgroud)
"base": {
    "REACT_APP_TESTENV": "1",
    "REACT_APP_IDENTITY_CLIENT_ID": "reactclient",
    "REACT_APP_REDIRECT_PATH": "signin-oidc",
    "REACT_APP_SILENT_REDIRECT_PATH": "silentrenew",
    "REACT_APP_LOGOFF_REDIRECT_PATH": "logout/callback",
    "REACT_APP_SCOPE": "openid profile email",
    "NODE_TLS_REJECT_UNAUTHORIZED": "0"
  },
  "development": {
    "REACT_APP_TESTENV": "development",
    "REACT_APP_AUTH_URI": "https://localhost:44318",
    "REACT_APP_AUTH_ISSUER": "https://localhost:44318",
    "REACT_APP_BASE_URI": "https://localhost:44309/",
    "REACT_APP_SERVICE_MEMBER_BASE_URI": "https://localhost:44320/"
  },
Run Code Online (Sandbox Code Playgroud)

身份服务器端代码。类似于https://github.com/IdentityServer/IdentityServer4.Demo/blob/master/src/IdentityServer4Demo/Quickstart/Account/AccountController.cs

export const IDENTITY_CONFIG = {
    authority: process.env.REACT_APP_AUTH_URI,
    client_id: process.env.REACT_APP_IDENTITY_CLIENT_ID, 
    redirect_uri: process.env.REACT_APP_BASE_URI + process.env.REACT_APP_REDIRECT_PATH,
    automaticSilentRenew: true, 
    filterProtocolClaims: true,
    loadUserInfo: true, 
    silent_redirect_uri: process.env.REACT_APP_BASE_URI + process.env.REACT_APP_SILENT_REDIRECT_PATH, 
    post_logout_redirect_uri: process.env.REACT_APP_BASE_URI + process.env.REACT_APP_LOGOFF_REDIRECT_PATH, 
    response_type: 'code',
    scope: process.env.REACT_APP_SCOPE
};
Run Code Online (Sandbox Code Playgroud)

谁能解释一下我如何重定向到特定页面,而不是每次登录后都转到主页。我想在身份服务器而不是客户端解决这个问题。

小智 2

您必须在reactjs中使用历史记录来获取以前的路径,并且需要保存在sessionStorage中。

也许这会对您有所帮助:

const SAVED_URI = 'APP_PLU';
const FORBIDDEN_URIS = ['/login-response', '/'];
const DEFAULT_URI = '/';

function setPostLoginUri() {
  // using just the pathname for demo, should be more detailed in production to
  // include query params, hash bangs, etc
  const currentPath = window.location.pathname;
  const savedURI = sessionStorage.getItem(SAVED_URI);

  if (FORBIDDEN_URIS.includes(currentPath) || savedURI) {
    return;
  }

  sessionStorage.setItem(SAVED_URI, currentPath);
}

function getPostLoginUri(retain) {
  const savedURI = sessionStorage.getItem(SAVED_URI);

  if (!retain) {
    sessionStorage.removeItem(SAVED_URI);
  }

  return savedURI || DEFAULT_URI;
}

export default {
  get: getPostLoginUri,
  set: setPostLoginUri
};
Run Code Online (Sandbox Code Playgroud)

并在app.js中设置

然后在您的登录响应页面中添加此代码,

function LoginResponse({ history, setUser }) {
  const [error, setError] = useState(null);

  useEffect(() => {
    // the login redirect has been completed and we call the
    // signinRedirectCallback to fetch the user data
    userManager.signinRedirectCallback().then(user => {
      // received the user data so we set it in the app state and push the
      // router to the secure or bookmarked route
      setUser(user);
      history.push(postLoginUri.get());
    }, ({ message }) => {
      // userManager throws if someone tries to access the route directly or if
      // they refresh on a failed request so we just send them to the app root
      if (message && redirectErrors.includes(message)) {
        history.push('/');
        return;
      }

      // for all other errors just display the message in production it would be
      // a good idea to initiate a sign out after a countdown
      setError(message);
    });
  }, []);

  return error;
}

export default LoginResponse;
Run Code Online (Sandbox Code Playgroud)