mirror of
				https://github.com/casdoor/casdoor.git
				synced 2025-10-31 09:27:53 +08:00 
			
		
		
		
	Support auto-login.
This commit is contained in:
		
							
								
								
									
										1
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								main.go
									
									
									
									
									
								
							| @ -43,6 +43,7 @@ func main() { | |||||||
| 	beego.SetStaticPath("/static", "web/build/static") | 	beego.SetStaticPath("/static", "web/build/static") | ||||||
| 	// https://studygolang.com/articles/2303 | 	// https://studygolang.com/articles/2303 | ||||||
| 	beego.InsertFilter("*", beego.BeforeRouter, routers.StaticFilter) | 	beego.InsertFilter("*", beego.BeforeRouter, routers.StaticFilter) | ||||||
|  | 	beego.InsertFilter("*", beego.BeforeRouter, routers.AutoLoginFilter) | ||||||
| 	beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter) | 	beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter) | ||||||
|  |  | ||||||
| 	beego.BConfig.WebConfig.Session.SessionName = "casdoor_session_id" | 	beego.BConfig.WebConfig.Session.SessionName = "casdoor_session_id" | ||||||
|  | |||||||
| @ -58,7 +58,7 @@ func generateJwtToken(application *Application, user *User) (string, error) { | |||||||
| 	return token, err | 	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) { | 	tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) { | ||||||
| 		return jwtSecret, nil | 		return jwtSecret, nil | ||||||
| 	}) | 	}) | ||||||
|  | |||||||
| @ -61,18 +61,12 @@ func getObject(ctx *context.Context) (string, string) { | |||||||
| 	method := ctx.Request.Method | 	method := ctx.Request.Method | ||||||
| 	if method == http.MethodGet { | 	if method == http.MethodGet { | ||||||
| 		query := ctx.Request.URL.RawQuery | 		query := ctx.Request.URL.RawQuery | ||||||
|  | 		// query == "?id=built-in/admin" | ||||||
| 		// query == "owner=admin" | 		idParamValue := parseQuery(query, "id") | ||||||
| 		if query == "" || strings.Contains(query, "=") { | 		if idParamValue == "" { | ||||||
| 			return "", "" | 			return "", "" | ||||||
| 		} | 		} | ||||||
|  | 		return parseSlash(idParamValue) | ||||||
| 		// query == "id=built-in/admin" |  | ||||||
| 		query = strings.TrimLeft(query, "id=") |  | ||||||
| 		tokens := strings.Split(query, "/") |  | ||||||
| 		owner := tokens[0] |  | ||||||
| 		name := tokens[1] |  | ||||||
| 		return owner, name |  | ||||||
| 	} else { | 	} else { | ||||||
| 		body := ctx.Input.RequestBody | 		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 * as Setting from "./Setting"; | ||||||
| import {DownOutlined, LogoutOutlined, SettingOutlined} from '@ant-design/icons'; | import {DownOutlined, LogoutOutlined, SettingOutlined} from '@ant-design/icons'; | ||||||
| import {Avatar, BackTop, Dropdown, Layout, Menu} from 'antd'; | 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 OrganizationListPage from "./OrganizationListPage"; | ||||||
| import OrganizationEditPage from "./OrganizationEditPage"; | import OrganizationEditPage from "./OrganizationEditPage"; | ||||||
| import UserListPage from "./UserListPage"; | 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() { |   getAccount() { | ||||||
|     AuthBackend.getAccount() |     const accessToken = this.getAccessTokenParam(); | ||||||
|  |     if (accessToken !== null) { | ||||||
|  |       window.history.replaceState({}, document.title, this.getUrlWithoutQuery()); | ||||||
|  |     } | ||||||
|  |     AuthBackend.getAccount(accessToken) | ||||||
|       .then((res) => { |       .then((res) => { | ||||||
|         this.setState({ |         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) { | export function isAdminUser(account) { | ||||||
|   if (account === null) { |   if (account === undefined || account === null) { | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|   return account.owner === "built-in" || account.isGlobalAdmin === true; |   return account.owner === "built-in" || account.isGlobalAdmin === true; | ||||||
|  | |||||||
| @ -14,8 +14,9 @@ | |||||||
|  |  | ||||||
| import {authConfig} from "./Auth"; | import {authConfig} from "./Auth"; | ||||||
|  |  | ||||||
| export function getAccount() { | export function getAccount(accessToken) { | ||||||
|   return fetch(`${authConfig.serverUrl}/api/get-account`, { |   let param = (accessToken === null) ? "" : `?accessToken=${accessToken}`; | ||||||
|  |   return fetch(`${authConfig.serverUrl}/api/get-account${param}`, { | ||||||
|     method: 'GET', |     method: 'GET', | ||||||
|     credentials: 'include' |     credentials: 'include' | ||||||
|   }).then(res => res.json()); |   }).then(res => res.json()); | ||||||
|  | |||||||
| @ -65,7 +65,7 @@ export function deleteUser(user) { | |||||||
|  |  | ||||||
| export function uploadAvatar(avatar) { | export function uploadAvatar(avatar) { | ||||||
|   let account; |   let account; | ||||||
|   AuthBackend.getAccount().then((res) => { |   AuthBackend.getAccount(null).then((res) => { | ||||||
|     account = Setting.parseJson(res.data); |     account = Setting.parseJson(res.data); | ||||||
|     let formData = new FormData(); |     let formData = new FormData(); | ||||||
|     formData.append("avatarfile", avatar); |     formData.append("avatarfile", avatar); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Yang Luo
					Yang Luo