Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Zero.Ki
Pinpoint
提交
10fab993
P
Pinpoint
项目概览
Zero.Ki
/
Pinpoint
通知
4
Star
1
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Pinpoint
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
10fab993
编写于
4月 05, 2021
作者:
K
Koo Taejin
提交者:
koo-taejin
4月 05, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[#7205] Support very simple authentication on Web
上级
152a81cc
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
898 addition
and
2 deletion
+898
-2
pom.xml
pom.xml
+3
-0
web/pom.xml
web/pom.xml
+11
-0
web/src/main/angular/angular.json
web/src/main/angular/angular.json
+1
-0
web/src/main/angular/src/not_authorized.html
web/src/main/angular/src/not_authorized.html
+93
-0
web/src/main/java/com/navercorp/pinpoint/web/PinpointBasicLoginConfig.java
.../com/navercorp/pinpoint/web/PinpointBasicLoginConfig.java
+97
-0
web/src/main/java/com/navercorp/pinpoint/web/WebApp.java
web/src/main/java/com/navercorp/pinpoint/web/WebApp.java
+17
-1
web/src/main/java/com/navercorp/pinpoint/web/config/BasicLoginConfig.java
...a/com/navercorp/pinpoint/web/config/BasicLoginConfig.java
+133
-0
web/src/main/java/com/navercorp/pinpoint/web/security/login/BasicLoginConstants.java
...corp/pinpoint/web/security/login/BasicLoginConstants.java
+32
-0
web/src/main/java/com/navercorp/pinpoint/web/security/login/BasicLoginService.java
...ercorp/pinpoint/web/security/login/BasicLoginService.java
+106
-0
web/src/main/java/com/navercorp/pinpoint/web/security/login/JwtRequestFilter.java
...vercorp/pinpoint/web/security/login/JwtRequestFilter.java
+73
-0
web/src/main/java/com/navercorp/pinpoint/web/security/login/JwtService.java
...com/navercorp/pinpoint/web/security/login/JwtService.java
+112
-0
web/src/main/java/com/navercorp/pinpoint/web/security/login/PinpointMemoryUserDetailsService.java
.../web/security/login/PinpointMemoryUserDetailsService.java
+81
-0
web/src/main/java/com/navercorp/pinpoint/web/security/login/PreAuthenticationCheckFilter.java
...oint/web/security/login/PreAuthenticationCheckFilter.java
+63
-0
web/src/main/java/com/navercorp/pinpoint/web/security/login/SaveJwtTokenAuthenticationSuccessHandler.java
...urity/login/SaveJwtTokenAuthenticationSuccessHandler.java
+63
-0
web/src/main/resources/applicationContext-web.xml
web/src/main/resources/applicationContext-web.xml
+6
-0
web/src/main/resources/pinpoint-web-root.properties
web/src/main/resources/pinpoint-web-root.properties
+7
-1
未找到文件。
pom.xml
浏览文件 @
10fab993
...
...
@@ -170,6 +170,9 @@
<mybatis.spring.version>
1.3.3
</mybatis.spring.version>
<mybatis.version>
3.4.6
</mybatis.version>
<jjwt.version>
0.9.1
</jjwt.version>
<jaxb.version>
2.3.1
</jaxb.version>
<!-- maven-plugin -->
<plugin.compiler.version>
3.8.1
</plugin.compiler.version>
<plugin.resources.version>
3.2.0
</plugin.resources.version>
...
...
web/pom.xml
浏览文件 @
10fab993
...
...
@@ -302,6 +302,17 @@
<artifactId>
mail
</artifactId>
</dependency>
<dependency>
<groupId>
io.jsonwebtoken
</groupId>
<artifactId>
jjwt
</artifactId>
<version>
${jjwt.version}
</version>
</dependency>
<dependency>
<groupId>
javax.xml.bind
</groupId>
<artifactId>
jaxb-api
</artifactId>
<version>
${jaxb.version}
</version>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>
com.navercorp.pinpoint
</groupId>
...
...
web/src/main/angular/angular.json
浏览文件 @
10fab993
...
...
@@ -21,6 +21,7 @@
"assets"
:
[
"src/favicon.ico"
,
"src/assets"
,
"src/not_authorized.html"
,
{
"glob"
:
"utils.js"
,
"input"
:
"node_modules/intl-tel-input/build/js"
,
...
...
web/src/main/angular/src/not_authorized.html
0 → 100644
浏览文件 @
10fab993
<!doctype html>
<html
lang=
"en-US"
>
<head>
<title>
PINPOINT
</title>
<meta
charset=
"utf-8"
>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge,chrome=1"
>
<meta
name=
"viewport"
content=
"width=device-width"
>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"assets/fonts/fontawesome-free-5.0.10/css/fontawesome-all.min.css"
/>
<style>
*
{
margin
:
0
;
padding
:
0
;
text-decoration
:
none
;
box-sizing
:
border-box
;
}
html
,
body
{
width
:
100%
;
height
:
100%
;
font-family
:
"Helvetica Neue"
,
Helvetica
,
Arial
,
sans-serif
;
font-size
:
14px
;
line-height
:
1.42857143
;
}
.page-header
{
width
:
100%
;
height
:
50px
;
background-color
:
#408dd4
;
display
:
flex
;
align-items
:
center
;
}
.logo
{
margin-left
:
20px
;
}
.contents-section
{
margin-top
:
200px
;
width
:
70%
;
margin-left
:
auto
;
margin-right
:
auto
;
}
.bug-icon
{
font-size
:
50px
;
color
:
#a94442
;
}
.contents-header
{
padding
:
10px
15px
;
}
.contents-header-text
{
display
:
inline-block
;
color
:
#a94442
;
font-size
:
30px
;
margin-left
:
3px
;
}
.contents-body
{
padding
:
15px
;
font-size
:
19px
;
color
:
#333
;
}
</style>
</head>
<body>
<header
class=
"page-header"
>
<img
class=
"logo"
src=
"/assets/img/logo.png"
width=
"116"
height=
"18"
>
</header>
<section
class=
"contents-section"
>
<header
class=
"contents-header"
>
<span
class=
"bug-icon fas fa-exclamation-triangle"
></span>
<h3
class=
"contents-header-text"
></h3>
</header>
<p
class=
"contents-body"
></p>
</section>
<script>
const
titleElem
=
document
.
querySelector
(
'
.contents-header-text
'
);
const
bodyElem
=
document
.
querySelector
(
'
.contents-body
'
);
const
userLang
=
window
.
navigator
.
language
;
// ko or else
if
(
userLang
.
includes
(
'
ko
'
))
{
titleElem
.
textContent
=
'
접근 권한이 없습니다.
'
;
bodyElem
.
innerHTML
=
`업무상 접근이 필요한 경우, 관리자에게 문의하세요.`
;
}
else
{
titleElem
.
textContent
=
'
You are not authorized.
'
;
bodyElem
.
innerHTML
=
`Please ask your administrator for access.`
;
}
</script>
</body>
</html>
\ No newline at end of file
web/src/main/java/com/navercorp/pinpoint/web/PinpointBasicLoginConfig.java
0 → 100644
浏览文件 @
10fab993
/*
* Copyright 2021 NAVER Corp.
*
* 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
com.navercorp.pinpoint.web
;
import
com.navercorp.pinpoint.web.security.login.BasicLoginConstants
;
import
com.navercorp.pinpoint.web.security.login.BasicLoginService
;
import
com.navercorp.pinpoint.web.security.login.JwtRequestFilter
;
import
com.navercorp.pinpoint.web.security.login.PreAuthenticationCheckFilter
;
import
com.navercorp.pinpoint.web.security.login.SaveJwtTokenAuthenticationSuccessHandler
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Profile
;
import
org.springframework.security.authentication.AuthenticationManager
;
import
org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
;
import
org.springframework.security.config.annotation.web.builders.HttpSecurity
;
import
org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
;
import
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
;
import
org.springframework.security.config.http.SessionCreationPolicy
;
import
org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
;
import
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter
;
/**
* @author Taejin Koo
*/
@Configuration
@EnableWebSecurity
@Profile
(
"basicLogin"
)
public
class
PinpointBasicLoginConfig
extends
WebSecurityConfigurerAdapter
{
@Autowired
private
BasicLoginService
basicLoginService
;
@Override
protected
void
configure
(
AuthenticationManagerBuilder
auth
)
throws
Exception
{
auth
.
eraseCredentials
(
false
);
auth
.
userDetailsService
(
basicLoginService
.
getUserDetailsService
());
}
@Override
protected
void
configure
(
HttpSecurity
http
)
throws
Exception
{
// for common
http
.
csrf
().
disable
()
.
sessionManagement
().
sessionCreationPolicy
(
SessionCreationPolicy
.
STATELESS
)
.
and
()
.
formLogin
()
.
successHandler
(
new
SaveJwtTokenAuthenticationSuccessHandler
(
basicLoginService
))
.
and
()
.
httpBasic
()
.
and
()
.
logout
()
.
deleteCookies
(
BasicLoginConstants
.
PINPOINT_JWT_COOKIE_NAME
);
// for admin
http
.
authorizeRequests
().
antMatchers
(
"/admin/**"
).
hasRole
(
"ADMIN"
)
.
and
()
.
exceptionHandling
()
.
accessDeniedPage
(
BasicLoginConstants
.
URI_NOT_AUTHORIZED
);
// for user
http
.
authorizeRequests
().
anyRequest
().
authenticated
();
http
.
addFilterBefore
(
new
JwtRequestFilter
(
basicLoginService
),
UsernamePasswordAuthenticationFilter
.
class
);
http
.
addFilterBefore
(
new
PreAuthenticationCheckFilter
(),
DefaultLoginPageGeneratingFilter
.
class
);
}
@Bean
public
PasswordEncoder
passwordEncoder
()
{
return
new
BCryptPasswordEncoder
();
}
@Override
@Bean
public
AuthenticationManager
authenticationManagerBean
()
throws
Exception
{
return
super
.
authenticationManagerBean
();
}
}
\ No newline at end of file
web/src/main/java/com/navercorp/pinpoint/web/WebApp.java
浏览文件 @
10fab993
/*
* Copyright 2021 NAVER Corp.
*
* 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
com.navercorp.pinpoint.web
;
import
com.navercorp.pinpoint.common.server.util.ServerBootLogger
;
...
...
@@ -22,7 +38,7 @@ public class WebApp {
public
static
void
main
(
String
[]
args
)
{
try
{
WebStarter
starter
=
new
WebStarter
(
WebApp
.
class
,
WebMvcConfig
.
class
);
WebStarter
starter
=
new
WebStarter
(
WebApp
.
class
,
WebMvcConfig
.
class
,
PinpointBasicLoginConfig
.
class
);
starter
.
start
(
args
);
}
catch
(
Exception
exception
)
{
logger
.
error
(
"[WebApp] could not launch app."
,
exception
);
...
...
web/src/main/java/com/navercorp/pinpoint/web/config/BasicLoginConfig.java
0 → 100644
浏览文件 @
10fab993
/*
* Copyright 2021 NAVER Corp.
*
* 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
com.navercorp.pinpoint.web.config
;
import
com.navercorp.pinpoint.common.util.CollectionUtils
;
import
com.navercorp.pinpoint.common.util.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Profile
;
import
org.springframework.security.core.authority.SimpleGrantedAuthority
;
import
org.springframework.security.core.userdetails.User
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
;
import
javax.annotation.PostConstruct
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.concurrent.TimeUnit
;
/**
* @author Taejin Koo
*/
@Profile
(
"basicLogin"
)
@Configuration
public
class
BasicLoginConfig
{
private
static
final
String
DEFAULT_JWT_SECRET_KEY
=
"PINPOINT_JWT_SECRET"
;
private
final
int
DEFAULT_EXPIRATION_TIME_SECONDS
=
new
Long
(
TimeUnit
.
HOURS
.
toSeconds
(
12
)).
intValue
();
private
final
BCryptPasswordEncoder
passwordEncoder
=
new
BCryptPasswordEncoder
();
@Value
(
"${web.security.auth.user:}"
)
private
List
<
String
>
userIdAndPasswordPairList
;
@Value
(
"${web.security.auth.admin:}"
)
private
List
<
String
>
adminIdAndPasswordPairList
;
@Value
(
"${web.security.auth.jwt.secretkey:#{null}}"
)
private
String
jwtSecretKey
=
DEFAULT_JWT_SECRET_KEY
;
private
List
<
UserDetails
>
userList
;
private
List
<
UserDetails
>
adminList
;
public
List
<
UserDetails
>
getUserList
()
{
return
userList
;
}
public
List
<
UserDetails
>
getAdminList
()
{
return
adminList
;
}
public
String
getJwtSecretKey
()
{
return
jwtSecretKey
;
}
public
int
getExpirationTimeSeconds
()
{
return
DEFAULT_EXPIRATION_TIME_SECONDS
;
}
@PostConstruct
public
void
setup
()
{
List
<
UserDetails
>
userList
=
createUser
(
userIdAndPasswordPairList
);
this
.
userList
=
userList
;
List
<
UserDetails
>
adminList
=
createAdmin
(
adminIdAndPasswordPairList
);
this
.
adminList
=
adminList
;
if
(
StringUtils
.
isEmpty
(
jwtSecretKey
))
{
throw
new
IllegalArgumentException
(
"'jwtSecretKey' may not be empty"
);
}
}
private
List
<
UserDetails
>
createUser
(
List
<
String
>
idAndPasswordList
)
{
List
<
UserDetails
>
users
=
createUserDetails
(
idAndPasswordList
,
"ROLE_USER"
);
return
users
;
}
private
List
<
UserDetails
>
createAdmin
(
List
<
String
>
idAndPasswordList
)
{
List
<
UserDetails
>
users
=
createUserDetails
(
idAndPasswordList
,
"ROLE_ADMIN"
);
return
users
;
}
private
List
<
UserDetails
>
createUserDetails
(
List
<
String
>
idAndPasswordList
,
String
role
)
{
if
(
CollectionUtils
.
isEmpty
(
idAndPasswordList
))
{
return
Collections
.
emptyList
();
}
List
<
UserDetails
>
users
=
new
ArrayList
<>(
idAndPasswordList
.
size
());
for
(
String
idAndPassword
:
idAndPasswordList
)
{
List
<
String
>
tokenize
=
StringUtils
.
tokenizeToStringList
(
idAndPassword
,
":"
);
if
(
CollectionUtils
.
nullSafeSize
(
tokenize
)
==
2
)
{
String
id
=
tokenize
.
get
(
0
);
String
password
=
tokenize
.
get
(
1
);
User
role_user
=
new
User
(
id
,
passwordEncoder
.
encode
(
password
),
Arrays
.
asList
(
new
SimpleGrantedAuthority
(
role
)));
users
.
add
(
role_user
);
}
}
return
users
;
}
@Override
public
String
toString
()
{
final
StringBuilder
sb
=
new
StringBuilder
(
"BasicLoginConfig{"
);
sb
.
append
(
"userList="
).
append
(
userList
);
sb
.
append
(
", adminList="
).
append
(
adminList
);
sb
.
append
(
'}'
);
return
sb
.
toString
();
}
}
\ No newline at end of file
web/src/main/java/com/navercorp/pinpoint/web/security/login/BasicLoginConstants.java
0 → 100644
浏览文件 @
10fab993
/*
* Copyright 2021 NAVER Corp.
*
* 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
com.navercorp.pinpoint.web.security.login
;
/**
* @author Taejin Koo
*/
public
final
class
BasicLoginConstants
{
public
static
final
String
URI_MAIN
=
"/"
;
public
static
final
String
URI_LOGIN
=
"/login"
;
public
static
final
String
URI_NOT_AUTHORIZED
=
"/not_authorized.html"
;
public
static
final
String
PINPOINT_JWT_COOKIE_NAME
=
"pinpointJwt"
;
}
\ No newline at end of file
web/src/main/java/com/navercorp/pinpoint/web/security/login/BasicLoginService.java
0 → 100644
浏览文件 @
10fab993
/*
* Copyright 2021 NAVER Corp.
*
* 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
com.navercorp.pinpoint.web.security.login
;
import
com.navercorp.pinpoint.web.config.BasicLoginConfig
;
import
io.jsonwebtoken.ExpiredJwtException
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Profile
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UserDetailsService
;
import
org.springframework.stereotype.Service
;
import
javax.servlet.http.Cookie
;
import
java.util.Date
;
import
java.util.concurrent.TimeUnit
;
/**
* @author Taejin Koo
*/
@Service
@Profile
(
"basicLogin"
)
public
class
BasicLoginService
{
private
final
PinpointMemoryUserDetailsService
pinpointMemoryUserDetailsService
;
private
final
Logger
logger
=
LoggerFactory
.
getLogger
(
this
.
getClass
());
private
final
JwtService
jwtService
;
@Autowired
public
BasicLoginService
(
BasicLoginConfig
basicLoginConfig
)
{
PinpointMemoryUserDetailsService
pinpointMemoryUserDetailsService
=
new
PinpointMemoryUserDetailsService
(
basicLoginConfig
);
this
.
pinpointMemoryUserDetailsService
=
pinpointMemoryUserDetailsService
;
this
.
jwtService
=
new
JwtService
(
basicLoginConfig
);
}
public
UserDetails
getUserDetails
(
Cookie
[]
cookies
)
{
if
(
cookies
==
null
)
{
return
null
;
}
for
(
Cookie
cookie
:
cookies
)
{
String
name
=
cookie
.
getName
();
if
(
BasicLoginConstants
.
PINPOINT_JWT_COOKIE_NAME
.
equals
(
name
))
{
String
pinpointJwtToken
=
cookie
.
getValue
();
try
{
Date
expirationDate
=
jwtService
.
getExpirationDate
(
pinpointJwtToken
);
if
(
expirationDate
.
getTime
()
>
System
.
currentTimeMillis
())
{
String
userId
=
jwtService
.
getUserId
(
pinpointJwtToken
);
UserDetails
userDetails
=
pinpointMemoryUserDetailsService
.
loadUserByUsername
(
String
.
valueOf
(
userId
));
if
(
userDetails
!=
null
)
{
return
userDetails
;
}
}
else
{
logger
.
warn
(
"This token already expired."
);
}
}
catch
(
ExpiredJwtException
e
)
{
logger
.
warn
(
"This token already expired. message:{}"
,
e
.
getMessage
(),
e
);
}
}
}
return
null
;
}
public
Cookie
createNewCookie
(
String
userId
)
{
UserDetails
userDetails
=
pinpointMemoryUserDetailsService
.
loadUserByUsername
(
userId
);
if
(
userDetails
==
null
)
{
throw
new
IllegalArgumentException
(
"Could not load User information."
);
}
String
token
=
jwtService
.
createToken
(
userDetails
);
Cookie
cookie
=
new
Cookie
(
BasicLoginConstants
.
PINPOINT_JWT_COOKIE_NAME
,
token
);
cookie
.
setPath
(
"/"
);
long
maxAge
=
TimeUnit
.
MILLISECONDS
.
toSeconds
(
jwtService
.
getExpirationTimeMillis
());
cookie
.
setMaxAge
(
new
Long
(
maxAge
).
intValue
());
return
cookie
;
}
public
UserDetailsService
getUserDetailsService
()
{
return
pinpointMemoryUserDetailsService
;
}
}
\ No newline at end of file
web/src/main/java/com/navercorp/pinpoint/web/security/login/JwtRequestFilter.java
0 → 100644
浏览文件 @
10fab993
/*
* Copyright 2021 NAVER Corp.
*
* 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
com.navercorp.pinpoint.web.security.login
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.context.SecurityContext
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.web.authentication.WebAuthenticationDetailsSource
;
import
org.springframework.web.filter.OncePerRequestFilter
;
import
javax.servlet.FilterChain
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.Cookie
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.util.Objects
;
/**
* @author Taejin Koo
*/
public
class
JwtRequestFilter
extends
OncePerRequestFilter
{
private
final
BasicLoginService
basicLoginService
;
private
final
WebAuthenticationDetailsSource
webAuthenticationDetailsSource
=
new
WebAuthenticationDetailsSource
();
public
JwtRequestFilter
(
BasicLoginService
basicLoginService
)
{
this
.
basicLoginService
=
Objects
.
requireNonNull
(
basicLoginService
,
"basicLoginService"
);
}
@Override
protected
void
doFilterInternal
(
HttpServletRequest
httpServletRequest
,
HttpServletResponse
httpServletResponse
,
FilterChain
filterChain
)
throws
ServletException
,
IOException
{
Cookie
[]
cookies
=
httpServletRequest
.
getCookies
();
if
(
cookies
==
null
)
{
filterChain
.
doFilter
(
httpServletRequest
,
httpServletResponse
);
return
;
}
UserDetails
userDetails
=
basicLoginService
.
getUserDetails
(
cookies
);
if
(
userDetails
==
null
)
{
filterChain
.
doFilter
(
httpServletRequest
,
httpServletResponse
);
return
;
}
SecurityContext
securityContext
=
SecurityContextHolder
.
getContext
();
if
(
securityContext
!=
null
&&
securityContext
.
getAuthentication
()
==
null
)
{
UsernamePasswordAuthenticationToken
usernamePasswordAuthenticationToken
=
new
UsernamePasswordAuthenticationToken
(
userDetails
,
null
,
userDetails
.
getAuthorities
());
usernamePasswordAuthenticationToken
.
setDetails
(
webAuthenticationDetailsSource
.
buildDetails
(
httpServletRequest
));
securityContext
.
setAuthentication
(
usernamePasswordAuthenticationToken
);
}
filterChain
.
doFilter
(
httpServletRequest
,
httpServletResponse
);
}
}
\ No newline at end of file
web/src/main/java/com/navercorp/pinpoint/web/security/login/JwtService.java
0 → 100644
浏览文件 @
10fab993
/*
* Copyright 2021 NAVER Corp.
*
* 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
com.navercorp.pinpoint.web.security.login
;
import
com.navercorp.pinpoint.common.util.Assert
;
import
com.navercorp.pinpoint.common.util.StringUtils
;
import
com.navercorp.pinpoint.web.config.BasicLoginConfig
;
import
io.jsonwebtoken.Claims
;
import
io.jsonwebtoken.Jws
;
import
io.jsonwebtoken.JwtBuilder
;
import
io.jsonwebtoken.JwtParser
;
import
io.jsonwebtoken.Jwts
;
import
io.jsonwebtoken.SignatureAlgorithm
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
java.util.Collection
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
import
java.util.stream.Collectors
;
/**
* @author Taejin Koo
*/
public
class
JwtService
{
private
final
String
KEY_CLAIMS_USER_ID
=
"userId"
;
private
final
String
KEY_CLAIMS_USER_ROLE
=
"userRole"
;
private
final
JwtParser
jwtParser
;
private
final
SignatureAlgorithm
signatureAlgorithm
=
SignatureAlgorithm
.
HS256
;
private
final
String
secretKey
;
private
final
long
expirationTimeMillis
;
public
JwtService
(
BasicLoginConfig
basicLoginConfig
)
{
String
secretKey
=
basicLoginConfig
.
getJwtSecretKey
();
if
(
StringUtils
.
isEmpty
(
secretKey
))
{
throw
new
IllegalArgumentException
(
"secretKey may not be empty"
);
}
this
.
secretKey
=
secretKey
;
Assert
.
isTrue
(
basicLoginConfig
.
getExpirationTimeSeconds
()
>
0
,
"expirationTimeSeconds must be '>= 0'"
);
this
.
expirationTimeMillis
=
TimeUnit
.
SECONDS
.
toMillis
(
basicLoginConfig
.
getExpirationTimeSeconds
());
JwtParser
jwtParser
=
Jwts
.
parser
();
jwtParser
.
setSigningKey
(
secretKey
);
this
.
jwtParser
=
jwtParser
;
}
public
String
createToken
(
UserDetails
userDetails
)
{
Map
<
String
,
Object
>
claims
=
new
HashMap
<>();
Collection
<?
extends
GrantedAuthority
>
authorities
=
userDetails
.
getAuthorities
();
List
<
String
>
collect
=
authorities
.
stream
().
map
(
e
->
((
GrantedAuthority
)
e
).
getAuthority
()).
collect
(
Collectors
.
toList
());
claims
.
put
(
KEY_CLAIMS_USER_ID
,
userDetails
.
getUsername
());
claims
.
put
(
KEY_CLAIMS_USER_ROLE
,
collect
);
return
createToken
(
claims
);
}
private
String
createToken
(
Map
<
String
,
Object
>
claims
)
{
JwtBuilder
jwtBuilder
=
Jwts
.
builder
();
jwtBuilder
.
setClaims
(
claims
);
jwtBuilder
.
setIssuedAt
(
new
Date
(
System
.
currentTimeMillis
()));
jwtBuilder
.
setExpiration
(
new
Date
(
System
.
currentTimeMillis
()
+
expirationTimeMillis
));
jwtBuilder
.
signWith
(
signatureAlgorithm
,
secretKey
);
return
jwtBuilder
.
compact
();
}
public
String
getUserId
(
String
token
)
{
Jws
<
Claims
>
claimsJws
=
jwtParser
.
parseClaimsJws
(
token
);
Claims
body
=
claimsJws
.
getBody
();
return
body
.
get
(
KEY_CLAIMS_USER_ID
,
String
.
class
);
}
public
Date
getExpirationDate
(
String
token
)
{
Jws
<
Claims
>
claimsJws
=
jwtParser
.
parseClaimsJws
(
token
);
Claims
body
=
claimsJws
.
getBody
();
return
body
.
getExpiration
();
}
public
long
getExpirationTimeMillis
()
{
return
expirationTimeMillis
;
}
}
\ No newline at end of file
web/src/main/java/com/navercorp/pinpoint/web/security/login/PinpointMemoryUserDetailsService.java
0 → 100644
浏览文件 @
10fab993
/*
* Copyright 2021 NAVER Corp.
*
* 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
com.navercorp.pinpoint.web.security.login
;
import
com.navercorp.pinpoint.web.config.BasicLoginConfig
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Profile
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UserDetailsService
;
import
org.springframework.security.core.userdetails.UsernameNotFoundException
;
import
org.springframework.stereotype.Service
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
/**
* @author Taejin Koo
*/
@Service
@Profile
(
"basicLogin"
)
public
class
PinpointMemoryUserDetailsService
implements
UserDetailsService
{
private
final
Logger
logger
=
LoggerFactory
.
getLogger
(
this
.
getClass
());
private
final
Map
<
String
,
UserDetails
>
userDetailsMap
;
@Autowired
public
PinpointMemoryUserDetailsService
(
BasicLoginConfig
basicLoginConfig
)
{
Map
<
String
,
UserDetails
>
userDetailsMap
=
new
HashMap
<>();
final
List
<
UserDetails
>
userList
=
basicLoginConfig
.
getUserList
();
for
(
UserDetails
user
:
userList
)
{
userDetailsMap
.
put
(
user
.
getUsername
(),
user
);
}
if
(
logger
.
isDebugEnabled
())
{
Collection
<
String
>
userRoleUserNameList
=
userList
.
stream
().
map
(
user
->
user
.
getUsername
()).
collect
(
Collectors
.
toList
());
logger
.
debug
(
"Has been registered {} that has USER role."
,
userRoleUserNameList
);
}
List
<
UserDetails
>
adminList
=
basicLoginConfig
.
getAdminList
();
for
(
UserDetails
admin
:
adminList
)
{
userDetailsMap
.
put
(
admin
.
getUsername
(),
admin
);
}
if
(
logger
.
isDebugEnabled
())
{
Collection
<
String
>
adminRoleUserNameList
=
adminList
.
stream
().
map
(
user
->
user
.
getUsername
()).
collect
(
Collectors
.
toList
());
logger
.
debug
(
"Has been registered {} that has ADMIN role."
,
adminRoleUserNameList
);
}
this
.
userDetailsMap
=
Collections
.
unmodifiableMap
(
userDetailsMap
);
}
@Override
public
UserDetails
loadUserByUsername
(
String
username
)
throws
UsernameNotFoundException
{
return
userDetailsMap
.
get
(
username
);
}
}
\ No newline at end of file
web/src/main/java/com/navercorp/pinpoint/web/security/login/PreAuthenticationCheckFilter.java
0 → 100644
浏览文件 @
10fab993
/*
* Copyright 2021 NAVER Corp.
*
* 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
com.navercorp.pinpoint.web.security.login
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.context.SecurityContext
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.web.filter.GenericFilterBean
;
import
javax.servlet.FilterChain
;
import
javax.servlet.ServletException
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.ServletResponse
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
/**
* @author Taejin Koo
*/
public
class
PreAuthenticationCheckFilter
extends
GenericFilterBean
{
@Override
public
void
doFilter
(
ServletRequest
request
,
ServletResponse
response
,
FilterChain
chain
)
throws
IOException
,
ServletException
{
if
(!(
request
instanceof
HttpServletRequest
)
||
!(
response
instanceof
HttpServletResponse
))
{
chain
.
doFilter
(
request
,
response
);
return
;
}
SecurityContext
securityContext
=
SecurityContextHolder
.
getContext
();
if
(
securityContext
==
null
)
{
chain
.
doFilter
(
request
,
response
);
return
;
}
Authentication
authentication
=
securityContext
.
getAuthentication
();
if
(
authentication
==
null
)
{
chain
.
doFilter
(
request
,
response
);
return
;
}
if
(
authentication
.
isAuthenticated
()
&&
((
HttpServletRequest
)
request
).
getRequestURI
().
equals
(
BasicLoginConstants
.
URI_LOGIN
))
{
((
HttpServletResponse
)
response
).
sendRedirect
(
BasicLoginConstants
.
URI_MAIN
);
}
else
{
chain
.
doFilter
(
request
,
response
);
}
}
}
\ No newline at end of file
web/src/main/java/com/navercorp/pinpoint/web/security/login/SaveJwtTokenAuthenticationSuccessHandler.java
0 → 100644
浏览文件 @
10fab993
/*
* Copyright 2021 NAVER Corp.
*
* 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
com.navercorp.pinpoint.web.security.login
;
import
com.navercorp.pinpoint.common.util.Assert
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.MediaType
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.web.authentication.AuthenticationSuccessHandler
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.Cookie
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
/**
* @author Taejin Koo
*/
public
class
SaveJwtTokenAuthenticationSuccessHandler
implements
AuthenticationSuccessHandler
{
private
final
Logger
logger
=
LoggerFactory
.
getLogger
(
this
.
getClass
());
private
final
BasicLoginService
basicLoginService
;
public
SaveJwtTokenAuthenticationSuccessHandler
(
BasicLoginService
basicLoginService
)
{
this
.
basicLoginService
=
Assert
.
requireNonNull
(
basicLoginService
,
"basicLoginService"
);
}
@Override
public
void
onAuthenticationSuccess
(
HttpServletRequest
request
,
HttpServletResponse
response
,
Authentication
authentication
)
throws
IOException
,
ServletException
{
logger
.
debug
(
"onAuthenticationSuccess() started"
);
String
userId
=
authentication
.
getName
();
Cookie
newCookie
=
basicLoginService
.
createNewCookie
(
userId
);
response
.
addCookie
(
newCookie
);
response
.
setStatus
(
HttpStatus
.
OK
.
value
());
response
.
setContentType
(
MediaType
.
APPLICATION_JSON_VALUE
);
response
.
sendRedirect
(
BasicLoginConstants
.
URI_MAIN
);
return
;
}
}
\ No newline at end of file
web/src/main/resources/applicationContext-web.xml
浏览文件 @
10fab993
...
...
@@ -201,4 +201,10 @@
<bean
class=
"com.navercorp.pinpoint.web.interceptor.PerformanceLoggingInterceptor"
>
<constructor-arg
value=
"1000"
/>
</bean>
<beans
profile=
"basicLogin"
>
<bean
id=
"basicLoginConfig"
class=
"com.navercorp.pinpoint.web.config.BasicLoginConfig"
/>
<bean
id=
"basicLoginService"
class=
"com.navercorp.pinpoint.web.security.login.BasicLoginService"
/>
</beans>
</beans>
web/src/main/resources/pinpoint-web-root.properties
浏览文件 @
10fab993
...
...
@@ -84,4 +84,10 @@ websocket.allowedOrigins=
# If you have own downloadUrl information, please include the pinpoint version and downloadUrl information.
# default value is the github's pinpoint page.
web.installation.pinpointVersion
=
web.installation.downloadUrl
=
\ No newline at end of file
web.installation.downloadUrl
=
# Declares user:password in pinpoint-web.properties. (You can declare multiple people using,.)
# Role (User : Can use whole function except for admin rest api, Admin : Can use whole function)
#web.security.auth.user=alice:foo, bob:bar
#web.security.auth.admin=eve:baz
#
web.security.auth.jwt.secretkey
=
PINPOINT_JWT_SECRET
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录