提交 10fab993 编写于 作者: K Koo Taejin 提交者: koo-taejin

[#7205] Support very simple authentication on Web

上级 152a81cc
......@@ -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>
......
......@@ -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>
......
......@@ -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",
......
<!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
/*
* 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
/*
* 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);
......
/*
* 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
/*
* 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
/*
* 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
/*
* 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
/*
* 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
/*
* 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
/*
* 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
/*
* 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
......@@ -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>
......@@ -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.
先完成此消息的编辑!
想要评论请 注册