mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-23 02:35:49 +08:00
Support auto-login.
This commit is contained in:
parent
2029a28d7b
commit
f5ceae901b
1
main.go
1
main.go
@ -43,6 +43,7 @@ func main() {
|
||||
beego.SetStaticPath("/static", "web/build/static")
|
||||
// https://studygolang.com/articles/2303
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.StaticFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.AutoLoginFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter)
|
||||
|
||||
beego.BConfig.WebConfig.Session.SessionName = "casdoor_session_id"
|
||||
|
@ -58,7 +58,7 @@ func generateJwtToken(application *Application, user *User) (string, error) {
|
||||
return token, err
|
||||
}
|
||||
|
||||
func parseJwtToken(token string) (*Claims, error) {
|
||||
func ParseJwtToken(token string) (*Claims, error) {
|
||||
tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return jwtSecret, nil
|
||||
})
|
||||
|
@ -61,18 +61,12 @@ func getObject(ctx *context.Context) (string, string) {
|
||||
method := ctx.Request.Method
|
||||
if method == http.MethodGet {
|
||||
query := ctx.Request.URL.RawQuery
|
||||
|
||||
// query == "owner=admin"
|
||||
if query == "" || strings.Contains(query, "=") {
|
||||
// query == "?id=built-in/admin"
|
||||
idParamValue := parseQuery(query, "id")
|
||||
if idParamValue == "" {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
// query == "id=built-in/admin"
|
||||
query = strings.TrimLeft(query, "id=")
|
||||
tokens := strings.Split(query, "/")
|
||||
owner := tokens[0]
|
||||
name := tokens[1]
|
||||
return owner, name
|
||||
return parseSlash(idParamValue)
|
||||
} else {
|
||||
body := ctx.Input.RequestBody
|
||||
|
||||
|
62
routers/auto_login_filter.go
Normal file
62
routers/auto_login_filter.go
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package routers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/astaxie/beego/context"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
)
|
||||
|
||||
func getSessionUser(ctx *context.Context) string {
|
||||
user := ctx.Input.CruSession.Get("username")
|
||||
if user == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return user.(string)
|
||||
}
|
||||
|
||||
func setSessionUser(ctx *context.Context, user string) {
|
||||
err := ctx.Input.CruSession.Set("username", user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// https://github.com/beego/beego/issues/3445#issuecomment-455411915
|
||||
ctx.Input.CruSession.SessionRelease(ctx.ResponseWriter)
|
||||
}
|
||||
|
||||
func AutoLoginFilter(ctx *context.Context) {
|
||||
query := ctx.Request.URL.RawQuery
|
||||
// query == "?access_token=123"
|
||||
accessToken := parseQuery(query, "accessToken")
|
||||
if accessToken == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if getSessionUser(ctx) != "" {
|
||||
return
|
||||
}
|
||||
|
||||
claims, err := object.ParseJwtToken(accessToken)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
userId := fmt.Sprintf("%s/%s", claims.Organization, claims.Username)
|
||||
setSessionUser(ctx, userId)
|
||||
}
|
34
routers/util.go
Normal file
34
routers/util.go
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package routers
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func parseQuery(query string, key string) string {
|
||||
valueMap, err := url.ParseQuery(query)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return valueMap.Get(key)
|
||||
}
|
||||
|
||||
func parseSlash(s string) (string, string) {
|
||||
tokens := strings.Split(s, "/")
|
||||
return tokens[0], tokens[1]
|
||||
}
|
@ -17,7 +17,7 @@ import './App.less';
|
||||
import * as Setting from "./Setting";
|
||||
import {DownOutlined, LogoutOutlined, SettingOutlined} from '@ant-design/icons';
|
||||
import {Avatar, BackTop, Dropdown, Layout, Menu} from 'antd';
|
||||
import {Switch, Route, withRouter, Redirect, Link} from 'react-router-dom'
|
||||
import {Link, Redirect, Route, Switch, withRouter} from 'react-router-dom'
|
||||
import OrganizationListPage from "./OrganizationListPage";
|
||||
import OrganizationEditPage from "./OrganizationEditPage";
|
||||
import UserListPage from "./UserListPage";
|
||||
@ -105,11 +105,26 @@ class App extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
getAccessTokenParam() {
|
||||
// "/page?access_token=123"
|
||||
const params = new URLSearchParams(this.props.location.search);
|
||||
return params.get("access_token");
|
||||
}
|
||||
|
||||
getUrlWithoutQuery() {
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
return location.toString().replace(location.search, "");
|
||||
}
|
||||
|
||||
getAccount() {
|
||||
AuthBackend.getAccount()
|
||||
const accessToken = this.getAccessTokenParam();
|
||||
if (accessToken !== null) {
|
||||
window.history.replaceState({}, document.title, this.getUrlWithoutQuery());
|
||||
}
|
||||
AuthBackend.getAccount(accessToken)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
account: res.data,
|
||||
account: res.status === "ok" ? res.data : null,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ export function showMessage(type, text) {
|
||||
}
|
||||
|
||||
export function isAdminUser(account) {
|
||||
if (account === null) {
|
||||
if (account === undefined || account === null) {
|
||||
return false;
|
||||
}
|
||||
return account.owner === "built-in" || account.isGlobalAdmin === true;
|
||||
|
@ -14,8 +14,9 @@
|
||||
|
||||
import {authConfig} from "./Auth";
|
||||
|
||||
export function getAccount() {
|
||||
return fetch(`${authConfig.serverUrl}/api/get-account`, {
|
||||
export function getAccount(accessToken) {
|
||||
let param = (accessToken === null) ? "" : `?accessToken=${accessToken}`;
|
||||
return fetch(`${authConfig.serverUrl}/api/get-account${param}`, {
|
||||
method: 'GET',
|
||||
credentials: 'include'
|
||||
}).then(res => res.json());
|
||||
|
@ -65,7 +65,7 @@ export function deleteUser(user) {
|
||||
|
||||
export function uploadAvatar(avatar) {
|
||||
let account;
|
||||
AuthBackend.getAccount().then((res) => {
|
||||
AuthBackend.getAccount(null).then((res) => {
|
||||
account = Setting.parseJson(res.data);
|
||||
let formData = new FormData();
|
||||
formData.append("avatarfile", avatar);
|
||||
|
Loading…
x
Reference in New Issue
Block a user