当前位置: 首页 > 编程日记 > 正文

关于 OpenIdConnect 认证启用 HTTPS 回调 RedirectUri 不生效问题

在搭建 IdentityServer 服务端后,我们尝试使用了 OIDC(OpenID Connect) 的中间件来代替了原先的 Session 系统认证方式,起初采用的是 HTTP 协议,一切都没有什么问题,最近启用全站 HTTPS 后,发现登陆会跳转到 HTTP的页面,

OpenID Connect 认证流程

第一步:

请求构造授权页

Request URL:https://sso.xxx.cn/connect/authorize?client_id=10000005&redirect_uri=https%3A%2F%2Fp2.cloudhotels.cn&response_mode=form_post&response_type=id_token%20token&scope=openid%20profile&state=OpenIdConnect.AuthenticationProperties%3DTl--AjNJpswyb_R1ytC6SqEKnWP5FWe969jAIK-tPHj7l5bCYieg5fffC111-Bjur08jIafy5-DNg2ESrenp71it4OBCLnUsLXPbFGxlsT6jWwsTmRgJf5HxG-HtsTZm2iIwDkFl2P4GmlUt7GAl8gMuTNlaLqB3M-RuJ2prt603WzMQ&nonce=636321569961956638.ODdlZTBkOWItYmU4Mi00OTliLTk5ZjktNjY0YTkwNjk4MTE0ODczM2M4ZWUtNzIyZi00YjgwLTlhZDAtM2NkNmE3NzY2MzJl&x-client-SKU=ID_NET&x-client-ver=1.0.40306.1554
Request Method:GET
Status Code:200 
Remote Address:222.186.49.226:443
Referrer Policy:no-referrer-when-downgrade
:authority:sso.xxx.cn
:method:GET
:path:/connect/authorize?client_id=10000005&redirect_uri=https%3A%2F%2Fp2.xxx.cn&response_mode=form_post&response_type=id_token%20token&scope=openid%20profile&state=OpenIdConnect.AuthenticationProperties%3DTl--AjNJpswyb_R1ytC6SqEKnWP5FWe969jAIK-tPHj7l5bCYieg5fffC111-Bjur08jIafy5-DNg2ESrenp71it4OBCLnUsLXPbFGxlsT6jWwsTmRgJf5HxG-HtsTZm2iIwDkFl2P4GmlUt7GAl8gMuTNlaLqB3M-RuJ2prt603WzMQ&nonce=636321569961956638.ODdlZTBkOWItYmU4Mi00OTliLTk5ZjktNjY0YTkwNjk4MTE0ODczM2M4ZWUtNzIyZi00YjgwLTlhZDAtM2NkNmE3NzY2MzJl&x-client-SKU=ID_NET&x-client-ver=1.0.40306.1554
:scheme:https
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
accept-encoding:gzip, deflate, sdch, br
accept-language:zh-CN,zh;q=0.8
cookie:acw_tc=AQAAACVlAyxojQIAFpTodHdoRw2DIBLj; idsrv.xsrf=lL0mbSQCJwUEqyWAufNmPsKzR6s4rlmo9TnH5RgESnOUtVXBzRBfF1bumRiySNSdyI8LDA; SignInMessage.410d3116e4685a1ff945b72ec5b7bdee=owpop5ySCBwDREEoMovtaEIsnr5k6JVvD8kbdp2dJlSJvAUWX6xXvR1qP_G-C-Hf6QOOV8M5wZ_HBJ8L-101uznPFSmw1lqkmnPHTj0xJeR3gJ4QeaP9IEm4sQvEyZWzdnNGwW-F_y_9ooSGDqpNEr-PFoI_nrK7az0PWvgHsqv-hKSBQVonq_AIPaGumS7p5ORNHkHwB1LdJXWXnVwFq6NMM1DLD1zXJgpXp4EkzjCExIA89Nd9wUYZlJDb1TuNGLpucraql9RZ6kpKJpnr4z2bGtW1JENWdPb3YH4thqBlP6JMz4s9rKCJWhrOtojpuqfzGUanE-Sw8he4My0GQQ3FcNPqT8GFaVUmwPpy8qIZriLyCRO6IUlXoqo_uwAHS2N5f3AYtaoIo88TEJZl8sZCIeM1QD2ZADB1L96JHuTzMAR7TLEWxtFrFmlIX4Ue0XyXclzQnKbNPnhFlwK11joxFxpVczMuUp4bpEvfdhmuFaqTkTqO9qOmxh3fiVQxqpv9LXNg-JFrAWzlXfSJmrFaRUJ6-RFbHi31cYkLQ0v4Gal7KASMsVTvp9Iswj1lgvRtHoMEAXmwyMWThZg6RGJbFrQQSjG2uFB7-LFCOI_V_d3EYQMHxkvFeFJHUQ4O9DbXq0v-nSXCzcyNYEXBUS273X6OensJ4nilWZVtnssyXh1SppSICXGnX1MHfNvWMp2AlmdQQo76myLL0l2yCRVpyP6fLGWcMUmn9MmQi5-NoIALlCNyOslwAOGsgCkpcpLEeeI0BD7SKwXzQZQnTgCtJJayMZVdPB3aEKojZFe1BsBUV8nwsdEAhY8dc6HZPY3wpGhrVK1tYH1KzCFt1yw2LI3qgKgQyGnqETk7GUD-gunrvMYym-CMjteLu7lSyOiaaRTjMWb8o35psxK8RvHRNqc; _pms_session=gyyabpm4wizgtp0drl02nuuf; SignInMessage.9d3ece88ead86da0d24435c1a430c34e=NGNDv77kQPUAKKXDc9uVuokKTz1CIJG0t1G81CCrtHgPxx2wEb1TwxRdCT7UV61lmQxF-kYGSXH2-irds7PfoQSdp4Wm4Aot-zOjtpjtR8aH5VEndu78hbGIv6n2JEOAUQBtfh2GTrmQYBgHpEHIulCrHJWovGVmFIsgjDHmpnzAz_Kf6ZmcL0sC2tFDZYKP2PTYkaF83cG3PYbqVIeM7HTuucORtaybnuzv15UxGKU4T28cZwI28d_u-Og8gXkAoYNNFnT054S-q_Coxhz1nR5rYAZe_WmLZCvqM_3D0M7IK_1nHN8NexBKyuRIZ9V25D4afl7rNROCb2A0m3Y3ayUgu3FySHZwcjjhsia_l16IJMVu6KjFJCVZHh6JGu06O6lTza8QUnvYA6vh-PWVFiLFoszUy16RxuDWJl_fnoaWFBxP97zhFZ7gCHj9zdr5BjEgko6fkoEIcmHosehqsrTYJUGPKkaKR2GUfKzCEBeoNFvUveCOXrrjayeCSw5hk6dEjdehQvjrBy7ezffBRgViimpBr0YLqH00WSRdsZzfBA_KlUBkE3zJDBIrmGkyB7xiTOSHFXT-CoC4g7rEF4usM44CCntWTO48UGd_eq6qIxSLjVhXGrsuauqXZTKs82mPmARsd85opyA69kHfDkHT2vCKT3GLVmvBxk4Sdi1zoCobyHohFpj0o-u0J9fko6W8uxhilcKovPeWh8yDp5CQrpquXKc6yAN-4x1Lyh-lnKKHm2m1uPSV0v04P4PZfBYqASkYtgSKTRcmwErF8l8H7XpqlWFRT2DdXWYwetTv2I5MhC6HqwIlVoYzBk3JRIGheYTazNaO8Mz3pm1Ayp0VIWPH36mvdXynMV5iJmqgccVkWpdHmwJbHzdYajWPtqYocartaA2pAU9zog4nneNs9KI; SignInMessage.2e3550a6f27dbe37def555603163623e=dQUu6i3OyRhbsoYaK7wbtzSK5xGjVNSmenWCdZ0wbSvAnMAK7KNmBLBCOcV9rKRxAA-9jehtXT7bkFA0NRptXfgrWrU_my-cVvC2ok72b7qwk4LGTHonPqklVl-L_xCCBkUe0svpP1C4B3etBAj5MotsOVNFHuyhkNDAfMt_HpA6fCUJnEZtfQ0i3qycFmwL67O4JQx1EEbvhuugnlbyDiahppUlc-_TeVoySc_SNpnJc8HC9fCkYm7p2vQaLZoWVUsROU-JCPeIJ8NRDISTMqYlSWL0QY1UNa8vXF7zLSGO8jfMQ5YdmpYJIwG7VZrqf4yqHKi9E14G0IhYi1Y99wddOyaPYIKIQGIhWHkWVkRX0E1Mq-gsvzXJzLlN0-0_Ywyt4VRtpE1tQz9iS4xAtNPZBp3xyBzPJ0KsM6sHOuxuZT3X0NQV7hIZRA1eIV4xKhrGJtlh59FC7BaCmVIDDV7dytO9AGMlO5iYSjgKI4bTGC8cGYXHs2k7BsFTEh_RWKg0ygyu3hjvjIgN4X67yQ4BGHv92iFwLUxEn4nBXb7oZEx7BawzYAFcTlCK-l81VPmwr2Is0FjnhYlcr7MS-tvUx3HmG758-QPpoth5T0oZrOKVwv8Pop1503VjS1hFF1MCEzp0zzXaJcjZ_XeDLWmzElZ9jl8pw4AB2I64W-33IWtxBBXgjc9iX1L4t8imT9EMKXKK6wDxTZNQ8uxL2rnoV6NmYRoVcFjR0CFnAhntZDvhNGPWcFtH-eaGeFgDxa8HlbBV4vk1yNDlxN4-4upJxO7fbWmXx3OGPo8IVydyeQI0pUF61UKXYzVekyjc2rMS7wEpVsd8LdOy147tXLeZwqHBVbgU8GA6uITahJdjatOB2RLgTKgJvb_IPfgQQhRNv4ur5q2cfqerTIzSmH1lOJI; SignInMessage.249b0aeaa528d65e2fabdac9f695167d=PoHjxvv3eyxmJKkLNVuho_DAgPaIEjTg0XfzznyM_sKpPQ5vATFKZRIO7h2b9Zf-OtjqdTQN4gvEewnlEOVOvNED-WVT_hTcmBrj22ghMEKXJhYzjjVNOJxc5nYjcI0BHCiNgFsBZyTqsVqGG-QINfID8iG2NpnROU3sLygzIObydw56IJj63N6kJTBemCompDHcm0V8yOuqr8DIu_jR02JCPYotz2nRuHTsN-SRLCJzm1Q5ggfiy5HMMdV0jkdMj2CirxQV3sri32VNVNCvZ0XZJxFd5Ut-xoVfyPU9gGx1FI7iIEDhXyjSNGHgTGo2DFmgTVRn7kVIHnJ5kRiMvM9fYl8PHz2e_pB8VEGuUCisrXrQjdCiaTHdxjFudlmS-IcRksQV9fx4K0Ug0uy9Luf9RrfnUQo8i8JyARtPdrjmguJ79LVOjL-8eblBQlgUB6ih6uwXLBvRziyDTaB4B2FBT--Ke4guwrYBvxJdIgMh7Up5eJne8UW6Qeoc30L6q3TqiFLQLiFS39lehwx7EqoG_xLnp2y133ClQqfbFSBlBnPZD0OvNSuiWnOE724NeqioVkACPWUFgF7X1fbPDQXLc9mfRt0aNwlipNnCKtKwAoXtFJby1skdLx_I18uALo3KAwptivFweCvtKLELv0dBcQxzRzzOcIPi_gNUdrXnS7z23DvhCbsu8q842J-wZeqwXMrwakUzhh1-FvQW4Agt7FrTOCmOS1KzmarC2Xm5srIH3hWGc3gsvT3NYZxM0k-5WAhHw_d16zLAIWW4K_euxz5GnX-qKwvT3Rcpui4DsKQvZQGfCg4Ua3KKQT1iN-YOuixKMQ7nSiIHaP_0qZYI5H16mj3eiW4w0D2mDUSWCCRmJ7BR5qak0_mH0uLodDVvd8oejbfivWt-SGAd0MnZsoU; SignInMessage.8773da773d34dd5079a297ef19316ac0=4KfGGFxV7E7AiKGysQXQS9Dszsj3xHqg2RaVgdc-0uSz8c6ZLf_4ZB2FA1HLFXxoTnFbU-EN86eB1ZjPdYZO1BRPWw4dt_pk-ojgj88HcdDFlshoQBwAoN6MeTlnEriewC78lYz7UZVDJnCFZki4J7dMGPwu7XM93sLif3cR-d0pIFPdLBsjBZ2XaEDi6B9kKN8IAt5afWT8St-1LgnHSJPWl6iiCj2T71NaNnE0XU1ij_JdQRzLIQy4Z0eG8HA-jH3J_0oaqqoR-X3aJAiNlvb_GMPvXWF6CXaWFPiSxpu8_ApjKeI3Sq5bPghCZdApTdV1BH5UWDPciyZmX1knQd3B8DkmSsrAdSYXq5XVSDB4VYRFbZti-Msd5vZlCTo6w9tcGdNRlAnv9aEZjopkkf8IQqgiW0xZFlQjS9oGEVyNv80BkuhMMmoeNaEotHOaoK3qkNswqJRUNWxT9-6lLKB8pUaDxZZE4dJVC2VnW-CK6nbdDqCACcA-Ayf2wCTy2iVknv_zUUyXW5AkUO0CPI1BrBJkc_GqCbymXJphKO44vNLVUBoaMNjdAkqktpHBYx_rXImhCHNdXh0hvsVST4EWlTb2Y6IHx4G4sWNqE7irBPqhFJ4GcSUCfZlM0MD_72JdNCo9sYRDXqBUKO4gx1yRg2pyO00R0ch604AJ5EsF2fotrUm7Ie3br2erdI3dKkuKmy2jpyPQG3NmsZVFXFqIzguX7v4YvQTXXbvlVNHRpj3ulgGL7EQwnaikOD1Zc6mntSyesZ19nrkIQqjeFNFYA22-myhhFDo9ukjm0JIqvLoBLCN5br0JnyTXfHj0Bai_OsR1JMqoBSC9ZYHcSpEkNGDgi_gGiN1rQWUQikxhV3I5T1thx0A4_otw3MV2BMOWKxNMBdI4-jO4AAoWPK4BtFI; idsvr.session=a60e0086521e99c099122e9d54e6a870; idsrv=FXCKHsF7lWgZ6xBWmn5VU8KmB3Uo_DPkYFTsRNvEH3CKFOW4is94zus3LN9lPVj6yOqoV2o36dl5FS3tBTOWphg1fzIShAbW522-_AKnL0I3kKQldeccu7Wusb1moa2iAjq9q3y7mxlGFGBP7itBigCY1cfHeAZGbBfx1R1O5RUBO2Zjwf0PZuH1_-0EexZUNn-8qwOaMrpVTVTUOjZqc1Lr0cFFc6_PyLsyhHWbuiZLRcIHSsf_tSiw1YorIWFgoEv8kRlHOc4squfvAQQsraxBRrIKqWieqqhCA1y7kGUvlBJV8I0eLmP6lu9S08kehlM4sw
referer:https://sso.xxx.cn/login?signin=249b0aeaa528d65e2fabdac9f695167d
upgrade-insecure-requests:1
user-agent:Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Mobile Safari/537.36

第二步:

请求构造授权页会返回一个OAuth2回传信息 POST 到客户端 ,OAuth 2.0 Form Post Response Mode ,是一个对 OAuth2 的扩展,构造回传信息提交到客户端是通过URL的querystring和fragment这两种方式,这个扩展标准提供了一基于form表单的形式把数据post给客户端的机制。

Request URL:https://p2.xxx.cn/
Request Method:POST
Status Code:302 
Remote Address:58.220.27.80:443
Referrer Policy:no-referrer-when-downgradeid_token:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSIsImtpZCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSJ9.eyJpc3MiOiJodHRwczovL3Nzby5jbG91ZGhvdGVscy5jbiIsImF1ZCI6IjEwMDAwMDA1IiwiZXhwIjoxNDk2NTYwMjA1LCJuYmYiOjE0OTY1NjAyMDQsIm5vbmNlIjoiNjM2MzIxNTY5OTYxOTU2NjM4Lk9EZGxaVEJrT1dJdFltVTRNaTAwT1RsaUxUazVaamt0TmpZMFlUa3dOams0TVRFME9EY3pNMk00WldVdE56SXlaaTAwWWpnd0xUbGhaREF0TTJOa05tRTNOelkyTXpKbCIsImlhdCI6MTQ5NjU2MDIwNCwiYXRfaGFzaCI6InJEYVhQcXRaSFZEcUxVSzhscmotUFEiLCJzaWQiOiJhNjBlMDA4NjUyMWU5OWMwOTkxMjJlOWQ1NGU2YTg3MCIsInN1YiI6ImlydmluZyIsImF1dGhfdGltZSI6MTQ5NjU2MDIwNCwiaWRwIjoiaWRzcnYiLCJ1c2VyIjoie1wiVXNlcklEXCI6XCJpcnZpbmdcIixcIlVzZXJOYW1lXCI6XCLlkajmtptcIixcIlVzZXJQd2RcIjpcIioqKioqKlwiLFwiU2FsdFwiOlwiKioqKioqXCIsXCJDaXR5QXJlYUlEXCI6XCIxMDAwMDAwOFwiLFwiQ2l0eUFyZWFOTVwiOlwi5Y2X5Y2O6KW_XCIsXCJDaXR5R3JvdXBJRFwiOlwiXCIsXCJDaXR5R3JvdXBOYW1lXCI6XCJcIixcIkpvYklEXCI6XCJBMDAwM1wiLFwiSm9iVGl0bGVcIjpcIuWfjuWMuumUgOWUruWJr-aAu-ebkVwiLFwiRW1haWxcIjpcInl4ZGVuZ0Bob21laW5ucy5jb21cIixcIkJ1c2luZXNzRGVwXCI6XCJcIixcIlVzZXJTb3VyY2VcIjozLFwiWFR5cGVcIjoyLFwiTW9iaWxlXCI6XCIxMzgxNzk2MzY2MlwiLFwiSG90ZWxDZFwiOlwiMDIxMDY0XCIsXCJIb3RlbE5hbWVcIjpcIuS4iua1t-WcuuS4rei3r-WcsOmTgeermeW6l--8iOWGheWuvu-8iVwiLFwiSG90ZWxKb2JJRFwiOlwiUkpDV0pMXCIsXCJIb3RlbEpvYlRpdGxlXCI6XCLotKLliqHnu4_nkIZcIixcIkJyYW5kQ2RcIjpcIlJKXCIsXCJCcmFuZERlc2NcIjpcIuWmguWutlwiLFwiVXBkYXRlVGltZVwiOlwiMjAxNy0wNS0xOFQwOTo0MDoyMS4wNFwifSIsImFtciI6WyJwYXNzd29yZCJdfQ.c_Dn0xxmLRGsp9_iZ7T2UOhwGf2uVjKwWYeGrKr70HtWDXcoafurb6_JxgEwdcWJzlhv3t9a-Y-LcupLbRBfBO-mP7CcbWM5Jr5zn55-z7RH2QnMlViK17AOOiXrKdCr8kTaGAK2bnkMpYIzk4oUAgWkwS3z0_RQ4G1aAIwIDxRvrKo4DuLwCXGPTYXp7YwAemnpvgywNvDM6yjKEL8KltdKyYWaHg8zxQVEPUOeteLFlsBA6rHJ873YTv-s6XNH3Rx944Sh75qGmPCkv3N3mEIDvHd8emMKyGJ53_Rbr6Jjr6eH_h8XNdwvtSIlH3GRfCgsJXppGxEl-KtRDGaR0w
access_token:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSIsImtpZCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSJ9.eyJpc3MiOiJodHRwczovL3Nzby5jbG91ZGhvdGVscy5jbiIsImF1ZCI6Imh0dHBzOi8vc3NvLmNsb3VkaG90ZWxzLmNuL3Jlc291cmNlcyIsImV4cCI6MTQ5NjU2MDIwNSwibmJmIjoxNDk2NTYwMjA0LCJjbGllbnRfaWQiOiIxMDAwMDAwNSIsInNjb3BlIjpbIm9wZW5pZCIsInByb2ZpbGUiXSwic3ViIjoiaXJ2aW5nIiwiYXV0aF90aW1lIjoxNDk2NTYwMjA0LCJpZHAiOiJpZHNydiIsImFtciI6WyJwYXNzd29yZCJdfQ.e4DeFyh2Jt6dnsry0ALSbEJpj34lbN0u_iW9YAsc_XlSgWm044LeI19xRzgZvzF4lN_4jjwjvMaQPzOO4MOokSmSAjwnMdVg1j2b9U3c7YyqIUQMueHn1hTr06f2kd2OLYLz38RnNilvFf1xAAF8tXs2TOyrHl9L39i6Nb3I7pQenooIoIbP8yRGpGAztRVBBEHf-b1-7b1wmhaDYEKe_dFOXzlNPRjFzrDhvCcoke2SHJ3Zo60c9JQVUKopFPYUF0EN_TDsS4dHeZCE55tLb--1KJpz7e2WVNGMbts7HGUrlpa4O4mwESxN_c1F3V8YVstdEB7i8xYZCSqQHUdE4Q
token_type:Bearer
expires_in:1
scope:openid profile
state:OpenIdConnect.AuthenticationProperties=Tl--AjNJpswyb_R1ytC6SqEKnWP5FWe969jAIK-tPHj7l5bCYieg5fffC111-Bjur08jIafy5-DNg2ESrenp71it4OBCLnUsLXPbFGxlsT6jWwsTmRgJf5HxG-HtsTZm2iIwDkFl2P4GmlUt7GAl8gMuTNlaLqB3M-RuJ2prt603WzMQ
session_state:UDOKlCOQmRPUjrKy2bRKz-erQ9Ze4jkre7FwspSAZBA.d02260a76d5c74285e125e59531cea07

注意这一步会返回一个 302 的 Location 头,并且是 HTTP ?

cache-control:no-cache
content-length:0
date:Sun, 04 Jun 2017 07:10:05 GMT
eagleid:3adc014214965602048883069e
expires:-1
location:http://p2.xxx.cn
pragma:no-cache
server:Tengine
set-cookie:OpenIdConnect.nonce.nC4ZwLkiOvWjmFbe4uMezWn3Ot8OR5Q%2FEKWIPNawETw%3D=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT
set-cookie:_pms_cookies=GKjrW_Lmfe3Iek_fsJ0zN9CeIQWNuawbZSAi_tl1yl3q8CT2BCqNzk7rDYrsoJGmfE_tRYN7eccbe34g4TKJjBTSOeMXbdj-JYa249ypqj_zO6spFIoCbchvtMlFUct5ygIbs9a5QVD1FdfZh6oUMFBE283N6EENqX6SxAqv1KfIrrkEyAq2vvwtrnH6uRDcva4vfvgj5777VaXHl-DGQWRy5ET1xusxwT6rx8sA_39QPKxmLeqvoEaz1JRl_pXkBwndcmAmem1g12x1J8m5oW1jBB0sF-fcVCEw737SshYAgOLs42Gb6f-KfOZToqtvf-jkjgHKDM_FgoJjigYOGG3Jbcg158wnbPhBLCukDx1-V3gHLpaKVuiv4kPVzNsQouI27AplfJUbCYQK9KAgzpAIiQXpeGW4AGCfHgHiL_txBNCRoWLRM02xvetHlvmW3vxqBu-qTa_fnYeCFd8DcSJLHcyyOwVGkI8eQEIDzAAmRvy9qYetFRhJo75_SnxK73sHw0OCzM9jX-cFt1_5X1AwXK52QBKwgtfg8Ehxtn5aKwoyEQ3SgJQOMjO1W-AK1pzPN9fbNG-zMhXxN22V7srHxOS5J8s9_w0kZKU_vTjqr8-UaGtj-ed09ik-CpfCZvYOH3sKFIa3Yb_HeOt6GnSviaML1pULaXYR0qKxsOwL2yXyfRxsZb95TGUZ9e8wVvb5AGlxVAZD6_NWlU5qxTqss7fR3vAVbFJyWDcnZ_qEP4iu2yhXuZfplsnDSB8ZO_7JEUJKEKG3AEjsaX0c0eJAc0gJEQ5bx7uujGIUe1mpGhz6AwaLXHnbY_mzgA2HFXFLaqL_l6vwbLJzg8khzqOUT8sF0d91yGco6xxxb_tcLWFURT4z3e6i2Nz0KOpQkt5R8U4TiM41khXbpfiRxsWetc-TunteIv0iVtw3K1My7-qJOeSJn_JvDtnTxaesEiMbaMcGGkyGF_Ew33kSVrO3Ooiiv3qpb2oLLCz5CQ3gxStFCxpf4_ga69rCVQZwnY3-OX4r1pUq-1ObvQBuM055c2jCyhK5EGcd0aN7tu5yCCVLcIsjVLYBmCt-fa2Hkw_qgy6e6-0T07gLPB56k7_O4dm7qI7DbtmBEVR5LYPIA3LxK0Rpsfza0Uj9ELgubA6LP7GhMD313_mIC9DMAjZ3S2jpiuENqm8FsYsLPBKjSWBDCPbI9hHwEl1fBhSoaMxhNSaLdIj88Y5tBADrV0jMgFk9n2Xnzxr8WIMlczvWcFYLoDV6W1shGdxxsDpLK6XLYtzu2hxtm26z1Zhn41LNPuOTUpOK8iC_9J68lUW61mHJbYtWBTmKgXe6IssWegbfdtRLFBRccsWSqIBYtWQtEccTFtzmX4IgBqwCHpOCIVAg7F1m3zV-cI2AfpLccceSGbONTmdOl9dmye0EgW45Mqkz4gAqBfHwkGw8EyiBV9oIUY5dwB3RcrJx9MQlF7iLRMpnbKeVxBePtiEmkc4cn81CPkxjS1PvhH1EljWtHi9OKXKeWzoExnWtVbdHJxe2mcgvNcmqfrPj-R3DWfN83pqNdymqVpqsjZFbZv2UmQlZ8RJxMAqIPqihdA5iYxWzjhtINcrvSRY6qw8fN392t83_1in0XJCHkIO5MJnNYbHhaX7RbnifvXn1Lkg2NwvjAMrl1b8EEq-AO2pqt_XvgAThvv8Khrcwon-RQxmLKVrZPpOv7O-vaHoLsTr2inclMRvwZ_b_w3WMI5G9CAU8mD8eGco1BnkSK8EL78-j57NTH3kXnro6DsA4vgv57a_QuTxXi_DsMLcK5xFDJzohSYzI4DPDjgyuWItztGgk6pAn_ScOkGJ8iMiMaAKH0kxe0g4hjoUSfsS5-SSfAe7RnhZo-WNMn3x6Iz6S7vi9mKttfBRLiKyyPe1tS3ULngJEMukZfR90tUVD1V-yRf1Td1oX08-8iIf1H_qQgLvy37_glhrQRnJOVnufbTGmBTrfJdf482TGhn5HxEOKcaXYKHSU259IegMjT0ikzrxXkCVoI-M1kBuEYtBKCvG1gPH8vO1H710GNzPGq2ZCXBFtNFPsegmx-WXviJd_-B3nFrv_N0w_op0EBZH0Zxel_ZJzkPWzs7zDMRA_qVKjjeVDFDawOK2jKfchsQn4jWCXEYRjn0OpdWb2Hq0PmLvhFPcSgGxPOs6StdcHUGIkwoERzPr20mGj4ZBM9R7krYjjbo6Lddg-Pkvu503E07J9GZMnJ97lvbSVZeckrdFXd2btmh1aJI_qg_DCWwovhKIImN-l-IShEFkQjEBwei9nIiik05qjnU3twlVVIqRaPwV9UUXPODV-xz-oXh0CeN1QKNVAHV8-uoyfzF6F1tQ1Fkv2du_AvEFYySTqqAZVcmXGY6g0ESntPJ4bSYZ-CD3Sk7PxUvJpnQoXgtVzDlqRQeTr2ltqo5QFMyIuTEOCk1alYy-crWQi6Y7-iDHdNtDkYfaVWlYy4mHavmZ9mE5VhIR69UEvRGw2c1D0sNdkBd15EzRS2jA5KGI56bTjNElT9aJOwnPyHQUTJ5I; path=/; HttpOnly
status:302
timing-allow-origin:*
via:cache5.l2cm10-1[157,0], cache2.cn242[166,0]
x-powered-by:ASP.NET

第三步:

根据 Location 的地址跳转 ,这个时候发现 并不是 HTTPS

问题分析

本能的认为是 Idsrv 的 Client 配置回调地址问题 ,后面查阅 Idsrv 源码发现跟授权的 RedirectUri 并没有什么关系(OIDC 是兼容 OAuth 2.0 的),后面查看了客户端的源码(https://github.com/aspnet/AspNetKatana/blob/dev/src/Microsoft.Owin.Security.OpenIdConnect/OpenidConnectAuthenticationHandler.cs)

        /// <summary>/// Handles SignIn/// </summary>/// <returns></returns>protected override async Task ApplyResponseChallengeAsync(){if (Response.StatusCode == 401){AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);if (challenge == null){return;}// order for redirect_uri// 1. challenge.Properties.RedirectUri// 2. CurrentUriAuthenticationProperties properties = challenge.Properties;if (string.IsNullOrEmpty(properties.RedirectUri)){properties.RedirectUri = CurrentUri;}// this value will be passed to the AuthorizationCodeReceivedNotificationif (!string.IsNullOrWhiteSpace(Options.RedirectUri)){properties.Dictionary.Add(OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey, Options.RedirectUri);}if (_configuration == null){_configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.Request.CallCancelled);}OpenIdConnectMessage openIdConnectMessage = new OpenIdConnectMessage{ClientId = Options.ClientId,IssuerAddress = _configuration.AuthorizationEndpoint ?? string.Empty,RedirectUri = Options.RedirectUri,RequestType = OpenIdConnectRequestType.AuthenticationRequest,Resource = Options.Resource,ResponseMode = OpenIdConnectResponseModes.FormPost,ResponseType = Options.ResponseType,Scope = Options.Scope,State = OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey + "=" + Uri.EscapeDataString(Options.StateDataFormat.Protect(properties)),};if (Options.ProtocolValidator.RequireNonce){AddNonceToMessage(openIdConnectMessage);}var notification = new RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options){ProtocolMessage = openIdConnectMessage};await Options.Notifications.RedirectToIdentityProvider(notification);if (!notification.HandledResponse){string redirectUri = notification.ProtocolMessage.CreateAuthenticationRequestUrl();if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute)){_logger.WriteWarning("The authenticate redirect URI is malformed: " + redirectUri);}Response.Redirect(redirectUri);}}return;}

默认是取 Properties.RedirectUri 的地址否则自动获得当前请求的 CurrentUri

private string CurrentUri{get{return Request.Scheme +Uri.SchemeDelimiter +Request.Host +Request.PathBase +Request.Path +Request.QueryString;}}

由于我们使用的负载时在LB层做的,所以默认获得的地址是 HTTP的,那么为什么 Properties.RedirectUri 获取是哪里的数据呢 ?

private readonly IOwinContext _context;
.../// <summary>/// Find response challenge details for a specific authentication middleware/// </summary>/// <param name="authenticationType">The authentication type to look for</param>/// <param name="authenticationMode">The authentication mode the middleware is running under</param>/// <returns>The information instructing the middleware how it should behave</returns>public AuthenticationResponseChallenge LookupChallenge(string authenticationType, AuthenticationMode authenticationMode){if (authenticationType == null){throw new ArgumentNullException("authenticationType");}AuthenticationResponseChallenge challenge = _context.Authentication.AuthenticationResponseChallenge;bool challengeHasAuthenticationTypes = challenge != null && challenge.AuthenticationTypes != null && challenge.AuthenticationTypes.Length != 0;if (challengeHasAuthenticationTypes == false){return authenticationMode == AuthenticationMode.Active ? (challenge ?? new AuthenticationResponseChallenge(null, null)) : null;}foreach (var challengeType in challenge.AuthenticationTypes){if (string.Equals(challengeType, authenticationType, StringComparison.Ordinal)){return challenge;}}return null;}

也就是说在 401 状态码的情况下,会获取  _context.Authentication.AuthenticationResponseChallenge 对象时候为 null ,并不是客户端配置项,最后突然想到可能是 Idsrv 的拦截器里配置的(https://github.com/IdentityServer/IdentityServer3.Extensions.Mvc/blob/master/source/IdentityServer3.Extensions.Mvc/IdentityServer3.Extensions.Mvc/Filters/IdentityServerFullLoginAttribute.cs)

public class IdentityServerFullLoginAttribute : OwinAuthenticationAttribute{public IdentityServerFullLoginAttribute(): base(Constants.PrimaryAuthenticationType){this.Order = 1;}public override void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext){var statusCodeResult = filterContext.Result as HttpStatusCodeResult;if (statusCodeResult != null && statusCodeResult.StatusCode == 401){var ctx = filterContext.HttpContext.Request.GetOwinContext();var url = ctx.Environment.CreateSignInRequest(new SignInMessage{ReturnUrl = filterContext.HttpContext.Request.Url.AbsoluteUri});filterContext.Result = new RedirectResult(url);}}}

解决方案

1.) 客户单强制设置返回 302 与 URL 或 强制给 Properties.RedirectUri 赋值

 public class Startup{private static readonly Logger logger = LogManager.GetCurrentClassLogger();/// <summary>/// 启动类配置/// </summary>/// <param name="app"></param>public void Configuration(IAppBuilder app){//忽略SSL证书,安全验证//ServicePointManager.ServerCertificateValidationCallback += delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)//{//    return true;//};// configuring RedisGlobalHost.DependencyResolver.UseRedis(new RedisScaleoutConfiguration(CacheSetting.Redis, "SignalR") { Database = 3 });//configuring the OpenID Connect authentication middlewareapp.UseCookieAuthentication(new CookieAuthenticationOptions{AuthenticationType = "Cookies",});app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions{// Set expiration time to 8 hoursProtocolValidator = new OpenIdConnectProtocolValidator(){NonceLifetime = new TimeSpan(0, 8, 0, 0)},Authority = IdsvSetting.Authority,ClientId = IdsvSetting.ClientId,Scope = "openid profile",ResponseType = "id_token token",RedirectUri = IdsvSetting.RedirectUri,SignInAsAuthenticationType = "Cookies",UseTokenLifetime = false,Notifications = new OpenIdConnectAuthenticationNotifications{SecurityTokenValidated = async n =>{try{var id = n.AuthenticationTicket.Identity;var nid = new ClaimsIdentity(id.AuthenticationType);// keep the id_token for logoutnid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));// add access token for sample APInid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));// keep track of access token expirationnid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));//获得用户信息// var client = new UserInfoClient(new Uri(n.Options.Authority + "/connect/userinfo"), n.ProtocolMessage.AccessToken);//var userInfo = await client.GetAsync();//var user = userInfo.JsonObject.Last.First.ToString().DeserializeJson<XHotelOAuth2UserInfoResponse>(System.Text.Encoding.UTF8);var userInfoClient = new UserInfoClient(new Uri(n.Options.Authority + "/connect/userinfo"), n.ProtocolMessage.AccessToken);var userInfo = await userInfoClient.GetAsync();var user = userInfo.JsonObject.Last.First.ToString().DeserializeJson<XHotelOAuth2UserInfoResponse>(System.Text.Encoding.UTF8);...n.AuthenticationTicket = new AuthenticationTicket(nid, n.AuthenticationTicket.Properties);////清空 OpenIdConnect 开头的 Cookies foreach (var item in HttpContext.Current.Request.Cookies.AllKeys){if (item.Contains("OpenIdConnect", StringComparison.OrdinalIgnoreCase)){HttpCookie cookie = HttpContext.Current.Request.Cookies[item];cookie.Expires = DateTime.Now.AddDays(-1);HttpContext.Current.Response.Cookies.Add(cookie);}}HttpContext.Current.Response.AddHeader("Location", IdsvSetting.RedirectUri);}catch (Exception ex){ex.ToExceptionless().MarkAsCritical().Submit();logger.Error(ex, "UseOpenIdConnectAuthentication: " + ex.Message);}},RedirectToIdentityProvider = n =>{if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest){var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");if (idTokenHint != null){n.ProtocolMessage.IdTokenHint = idTokenHint.Value;}}return Task.FromResult(0);},AuthenticationFailed = (context) =>{if (context.Exception is OpenIdConnectProtocolInvalidNonceException && context.Exception.Message.ContainsAny(new string[] { "IDX10316", "IDX10311" })){logger.Warn("OpenIdConnectProtocolInvalidNonce expired, reauthenticating...");context.HandleResponse();//context.Response.Redirect("/Error.aspx?message=" + context.Exception.Message);
                            context.Response.Redirect(context.Request.Uri.PathAndQuery);}return Task.FromResult(0);},}});}}

2.) MVC 拦截器里设置 Properties.RedirectUri

 public class TokenAuthorizeFilter : AuthorizeAttribute{public override void OnAuthorization(AuthorizationContext context){if (!context.HttpContext.User.Identity.IsAuthenticated){
#if !DEBUGHttpContext.Current.GetOwinContext().Authentication.Challenge(new AuthenticationProperties{RedirectUri = context.HttpContext.Request.Url.ToString().Replace("http", "https")});
#endif// 401 who are you? go login and then try againcontext.Result = new HttpUnauthorizedResult();}//如果 session 不存在,清除 openid// context.RequestContext.HttpContext.GetOwinContext().Authentication.SignOut();// context.Result = new RedirectResult("/home?returnUrl=" + HttpUtility.UrlEncode(HttpContext.Current.Request.Url.AbsoluteUri));
        }}

REFER:
https://github.com/IdentityServer/IdentityServer3.Extensions.Mvc
https://github.com/aspnet/AspNetKatana
干掉状态:从session到token
https://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513566&idx=1&sn=a2688cadbe9c8042ff1abbdf04a8bd5e&chksm=80d67a1db7a1f30b28b93ed2ab29edfbf982b780433e4bfd178e3cc52cb1f9100cc8f923db4f#rd

相关文章:

C#中使用GUID

GUID&#xff08;全局统一标识符&#xff09;是指在一台机器上生成的数字&#xff0c;它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成GUID的API。生成算法很有意思&#xff0c;用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字。GUID的唯一缺陷在于生…

Matlab与线性代数 -- 对角矩阵

本微信图文详细介绍了Matlab中diag()函数的应用。

leetcode--对称二叉树--python

文章目录题目题目详情示例说明解题代码代码运行结果体会题目 题目详情 给定一个二叉树&#xff0c;检查它是否是镜像对称的。 示例 例如&#xff0c;二叉树 [1,2,2,3,4,4,3] 是对称的。 1/ \2 2/ \ / \ 3 4 4 3但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的: 1…

IPV6的设置问题!

最近一段在研究IPV6&#xff0c;在网上搜了好多资料&#xff0c;但是感觉大部分都不实在&#xff0c;都是泛泛而谈&#xff0c;实用性不强&#xff0c;故决定做点什么&#xff01;正所谓该出手时就出手&#xff0c;风风火火闯九州哦~~ IPV6设置步骤&#xff1a; 1.首先查看你时…

Matlab与线性代数 -- 数组与矩阵的乘幂

本微信图文详细介绍了数组的乘幂运算power()与矩阵的乘幂运算mpower()。

Docker 公司是如何做社区的?

今天看了一个Docker公司是如何做社区的PPT&#xff0c;演讲者是Docker公司的市场部老大。Docker从发布之初就受到了开发者的关注&#xff0c;1.0版本发布的时候Docker就收到了超过460位贡献者的8741条改进建议&#xff0c;Docker也承认是社区帮助他们迅速达到了这一新的里程碑。…

leetcode--整数反转--python

文章目录题目题目详情示例注意解题代码小知识代码运行结果体会题目 题目详情 给出一个 32 位的有符号整数&#xff0c;你需要将这个整数中每位上的数字进行反转。 示例 输入: 123 输出: 321输入: -123 输出: -321输入: 120 输出: 21注意 假设我们的环境只能存储得下 32 位…

水晶报表调用存储过程的问题

前言&#xff1a;现在碰到了水晶报表调用存储过程的问题&#xff0c;问题是这样的&#xff1a;ERP软件里有很多的数据表&#xff0c;有些报表的字段要从多个数据表里取数据&#xff0c;并且要对数据进行处理&#xff0c;来作为报表的字段&#xff0c;我看了些资料&#xff0c;说…

iOS-ARC_Xcode检测循环引用

iOS-ARC_Xcode检测循环引用 一&#xff0c;在桌面上新建立一个工程&#xff0c;在ViewController.m中输入如下代码&#xff1a; - (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.NSMutableArray *firstArr…

什么是SESSION?(三)

本微信图文通过一个利用数据库的方式存储Session的例子&#xff0c;深入介绍了对Session机制的理解。本微信图文由钟锦提供。

leetcode--回文数--python

文章目录题目题目详情示例解题代码代码运行结果体会题目 题目详情 判断一个整数是否是回文数。回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 示例 输入: 121 输出: true输入: -121 输出: false 解释: 从左向右…

DevXpress 控件: 第一篇: 将 Master_Details 关系进行到底--XtraPivotGridControl控件

一. 控件说明: XtraPivotGridControl&#xff1b;数据控件 二. 控件特点: 1. 支持行, 列字段拖动, 对调 支持行, 列字段的添加, 移除 支持数据字段的添加, 移除, 对调 2. 支持以行, 列字段排序 支持以过滤字段排序 3. 支持行, 列字段过滤 …

JNI与NDK学习第二篇-----应用篇

2019独角兽企业重金招聘Python工程师标准>>> 1.安装配置NDK 1). 解压NDK的zip包到非中文目录(最好英文目录不要带空格) 2). 配置path : 解压后NDK的根目录----->ndk-build 2.给AS关联NDK 1). local.properties中添加配置 ndk.dirE\:\\Android\\sdk\\android-…

数据结构与算法课程的代码链接

VS2005版本 http://download.csdn.net/detail/lsgo_myp/9713329 VS2015版本 http://download.csdn.net/detail/lsgo_myp/9730592

leetcode--字符串转换为整数--python

文章目录题目题目详情说明示例解题代码思路代码运行结果最佳方案题目 题目详情 请你来实现一个 atoi 函数&#xff0c;使其能将字符串转换成整数。 首先&#xff0c;该函数会根据需要丢弃无用的开头空格字符&#xff0c;直到寻找到第一个非空格的字符为止。 当我们寻找到的…

什么是自组织特征映射网络?

什么是自组织特征映射网络&#xff1f;

理解jQuery对象$.html

如果要比喻jQuery和原生javascript的关系&#xff0c;我个人认为是自动档和手动档汽车的区别。使用原生javascript&#xff0c;可以知道离合器以及档位的作用&#xff1b;而使用jQuery&#xff0c;则把离合器和手动档位封装到函数&#xff0c;直接前进、后退或驻车即可。所以&a…

精通ASP.NET中弹出窗口技术

本文讨论如何以ASP.NET中的CodeBehind方式实现各种弹出窗口&#xff0c;实现与弹出窗口的交互。并探讨常用非标准IE浏览器对弹出的窗口的各种过滤行为及使用弹出窗口相应对策&#xff0c;以期给出使用弹出窗口的一个通用较优方案。 关键词&#xff1a;ASP.NET、CodeBehind、过滤…

leetcode--删除排序数组中的重复项--python

文章目录题目题目详情示例说明解题代码思路代码运行结果最佳方案题目 题目详情 给定一个排序数组&#xff0c;你需要在原地删除重复出现的元素&#xff0c;使得每个元素只出现一次&#xff0c;返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须在原地修改…

转换人民币大小金额

1 usingSystem; 2 3 namespaceTest 4 { 5 /**////<summary>6 ///Rmb 的摘要说明。 7 ///</summary>8 publicclassRmb 9 { 10 /**////<summary>11 ///转换人民币大小金额 12 ///</summary>13 ///<param name"num">金额</param>14…

偏执却管用的 10 条 Java 编程技巧

经过一段时间的编码&#xff08;咦&#xff0c;我已经经历了将近20年的编程生涯&#xff0c;快乐的日子总是过得很快&#xff09;&#xff0c;我们开始感谢那些好习惯。因为&#xff0c;你知道… “任何可能出错的事情&#xff0c;最后都会出错。” 这就是人们为什么喜欢进行“…

如何利用SOM网络进行柴油机故障诊断

如何利用SOM网络进行柴油机故障诊断

leetcode--删除排序链表中的重复元素--python

文章目录题目题目详情示例解题代码思路代码运行结果最佳方案题目 题目详情 给定一个排序链表&#xff0c;删除所有重复的元素&#xff0c;使得每个元素只出现一次。 示例 输入: 1->1->2 输出: 1->2输入: 1->1->2->3->3 输出: 1->2->3解题代码 …

如何使用 UserAccountControl 标志操纵用户帐户属性

转载&#xff1a; http://support.microsoft.com/kb/305144 概要 在打开用户帐户的属性后&#xff0c;单击帐户选项卡&#xff0c;然后选中或清除“帐户选项”对话框中的复选框&#xff0c;则会将数值分配给 UserAccountControl 属性。分配给该属性的值通知 Windows 已启用了哪…

程序员 专属的新年祝福原来是这样的! (附中奖名单)

程序员的新年祝福会是什么样的&#xff1f;我们共收到了97位 OSCer 的回复&#xff0c;以下为支持数排名前十的祝福语&#xff1a; yale8848&#xff08;支持数&#xff1a;10&#xff09; document.write("") &#xff08;小编&#xff1a;捂脸&#xff0c;不过不知…

LSGO代码小组第16周复盘日志

LSGO代码小组第16周复盘日志&#xff0c;汇报人&#xff1a;高勇

leetcode--买股票的最佳时机II--python

文章目录题目题目详情注意示例代码思路解题代码运行结果最佳方案题目 题目详情 给定一个数组&#xff0c;它的第 i 个元素是一支给定股票第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&#xff09;。…

我的广州生活~

步入11月份&#xff0c;天气逐渐转冷&#xff01;本以为广东的冬天是永远的裤头T恤&#xff0c;看来我错了。。。在凉席上抗争了一周&#xff0c;我感冒了两次&#xff0c;看来人毕竟斗不过天&#xff0c;还是乖乖的铺上褥子&#xff0c;等待南国的冬天。他们都说广州的冬天是种…

苹果手表可以运行 ruby 脚本了

不得不佩服啊&#xff01; 各位看下载地址吧https://itunes.apple.com/cn/app/ruby-2.0-for-ios-yun-xing/id727047729?mt8https://yqfile.alicdn.com/d0403806fdff7411060f9b0b059d1f9966c19447.png" >https://yqfile.alicdn.com/5dbd9a02e4252465b9896713a592e092ca…

Matlab与线性代数--广义逆矩阵

本微信图文详细介绍了Matlab中求解广义逆矩阵的方法。