Support auto-login.

This commit is contained in:
Yang Luo 2021-03-28 16:35:59 +08:00
parent 2029a28d7b
commit f5ceae901b
9 changed files with 125 additions and 18 deletions

View File

@ -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"

View File

@ -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
})

View File

@ -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

View 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
View 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]
}

View File

@ -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,
});
});
}

View File

@ -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;

View File

@ -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());

View File

@ -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);