mirror of
https://github.com/apache/rocketmq-dashboard.git
synced 2026-05-29 22:03:45 +08:00
[ISSUE-#205|#247] Support SSL + UserName & Password Login
[ISSUE-#205|#247] Support SSL + UserName & Password Login
This commit is contained in:
@@ -61,4 +61,55 @@
|
|||||||
* 根据Topic和Key进行查询
|
* 根据Topic和Key进行查询
|
||||||
* 最多只会展示64条
|
* 最多只会展示64条
|
||||||
* 根据消息主题和消息Id进行消息的查询
|
* 根据消息主题和消息Id进行消息的查询
|
||||||
* 消息详情可以展示这条消息的详细信息,查看消息对应到具体消费组的消费情况(如果异常,可以查看具体的异常信息)。可以向指定的消费组重发消息。
|
* 消息详情可以展示这条消息的详细信息,查看消息对应到具体消费组的消费情况(如果异常,可以查看具体的异常信息)。可以向指定的消费组重发消息。
|
||||||
|
|
||||||
|
|
||||||
|
## HTTPS 方式访问Console
|
||||||
|
* HTTPS功能实际上是使用SpringBoot提供的配置功能即可完成,首先,需要有一个SSL KeyStore来存放服务端证书,可以使用本工程所提供的测试密钥库:
|
||||||
|
resources/rmqcngkeystore.jks, 它可以通过如下keytool命令生成
|
||||||
|
```
|
||||||
|
#生成库并以rmqcngKey别名添加秘钥
|
||||||
|
keytool -genkeypair -alias rmqcngKey -keyalg RSA -validity 3650 -keystore rmqcngkeystore.jks
|
||||||
|
#查看keystore内容
|
||||||
|
keytool -list -v -keystore rmqcngkeystore.jks
|
||||||
|
#转换库格式
|
||||||
|
keytool -importkeystore -srckeystore rmqcngkeystore.jks -destkeystore rmqcngkeystore.jks -deststoretype pkcs12
|
||||||
|
```
|
||||||
|
|
||||||
|
* 配置resources/application.properties, 打开SSL的相关选项, 启动console后即开启了HTTPS.
|
||||||
|
```
|
||||||
|
#设置https端口
|
||||||
|
server.port=8443
|
||||||
|
|
||||||
|
### SSL setting
|
||||||
|
#server.ssl.key-store=classpath:rmqcngkeystore.jks
|
||||||
|
#server.ssl.key-store-password=rocketmq
|
||||||
|
#server.ssl.keyStoreType=PKCS12
|
||||||
|
#server.ssl.keyAlias=rmqcngkey
|
||||||
|
```
|
||||||
|
|
||||||
|
## 登录访问Console
|
||||||
|
在访问Console时支持按用户名和密码登录控制台,在操作完成后登出。需要做如下的设置:
|
||||||
|
|
||||||
|
* 1.在Spring配置文件resources/application.properties中修改 开启登录功能
|
||||||
|
```$xslt
|
||||||
|
# 开启登录功能
|
||||||
|
rocketmq.config.loginRequired=true
|
||||||
|
|
||||||
|
# Dashboard文件目录,登录用户配置文件所在目录
|
||||||
|
rocketmq.config.dataPath=/tmp/rocketmq-console/data
|
||||||
|
```
|
||||||
|
* 2.确保${rocketmq.config.dataPath}定义的目录存在,并且该目录下创建登录配置文件"users.properties", 如果该目录下不存在此文件,则默认使用resources/users.properties文件。
|
||||||
|
users.properties文件格式为:
|
||||||
|
```$xslt
|
||||||
|
# 该文件支持热修改,即添加和修改用户时,不需要重新启动console
|
||||||
|
# 格式, 每行定义一个用户, username=password[,N] #N是可选项,可以为0 (普通用户); 1 (管理员)
|
||||||
|
|
||||||
|
#定义管理员
|
||||||
|
admin=admin,1
|
||||||
|
|
||||||
|
#定义普通用户
|
||||||
|
user1=user1
|
||||||
|
user2=user2
|
||||||
|
```
|
||||||
|
* 3. 启动控制台则开启了登录功能
|
||||||
@@ -62,4 +62,57 @@
|
|||||||
* Only Return 64 Messages
|
* Only Return 64 Messages
|
||||||
* Query By Topic And MessageId
|
* Query By Topic And MessageId
|
||||||
* look over this message's detail info.you can see the message's consume state(each group has one line),show the exception message if has exception.
|
* look over this message's detail info.you can see the message's consume state(each group has one line),show the exception message if has exception.
|
||||||
you can send this message to the group you selected
|
you can send this message to the group you selected
|
||||||
|
|
||||||
|
|
||||||
|
## Access Console with HTTPS
|
||||||
|
* SpringBoot itself has provided the SSL configuration. You can use the project test Keystore:resources/rmqcngkeystore.jks. The store is generated with the following unix keytool commands:
|
||||||
|
```
|
||||||
|
#Generate Keystore and add alias rmqcngKey
|
||||||
|
keytool -genkeypair -alias rmqcngKey -keyalg RSA -validity 3650 -keystore rmqcngkeystore.jks
|
||||||
|
#View keystore content
|
||||||
|
keytool -list -v -keystore rmqcngkeystore.jks
|
||||||
|
#Transfer type as official
|
||||||
|
keytool -importkeystore -srckeystore rmqcngkeystore.jks -destkeystore rmqcngkeystore.jks -deststoretype pkcs12
|
||||||
|
```
|
||||||
|
|
||||||
|
* Uncomment the following SSL properties in resources/application.properties. restart Console then access with HTTPS.
|
||||||
|
|
||||||
|
```
|
||||||
|
#Set https port
|
||||||
|
server.port=8443
|
||||||
|
|
||||||
|
### SSL setting
|
||||||
|
server.ssl.key-store=classpath:rmqcngkeystore.jks
|
||||||
|
server.ssl.key-store-password=rocketmq
|
||||||
|
server.ssl.keyStoreType=PKCS12
|
||||||
|
server.ssl.keyAlias=rmqcngkey
|
||||||
|
```
|
||||||
|
|
||||||
|
## Login/Logout on Console
|
||||||
|
Access Console with username and password and logout to leave the console。To stage the function on, we need the steps below:
|
||||||
|
|
||||||
|
* 1.Turn on the property in resources/application.properties.
|
||||||
|
```$xslt
|
||||||
|
# open the login func
|
||||||
|
rocketmq.config.loginRequired=true
|
||||||
|
|
||||||
|
# Directory of ashboard & login user configure file
|
||||||
|
rocketmq.config.dataPath=/tmp/rocketmq-console/data
|
||||||
|
```
|
||||||
|
* 2.Make sure the directory defined in property ${rocketmq.config.dataPath} exists and the file "users.properties" is created under it.
|
||||||
|
The console system will use the resources/users.properties by default if a customized file is not found。
|
||||||
|
|
||||||
|
The format in the content of users.properties:
|
||||||
|
```$xslt
|
||||||
|
# This file supports hot change, any change will be auto-reloaded without Console restarting.
|
||||||
|
# Format: a user per line, username=password[,N] #N is optional, 0 (Normal User); 1 (Admin)
|
||||||
|
|
||||||
|
# Define Admin
|
||||||
|
admin=admin,1
|
||||||
|
|
||||||
|
# Define Normal users
|
||||||
|
user1=user1
|
||||||
|
user2=user2
|
||||||
|
```
|
||||||
|
* 3. Restart Console Application after above configuration setting well.
|
||||||
2
pom.xml
2
pom.xml
@@ -11,7 +11,7 @@
|
|||||||
<groupId>org.apache</groupId>
|
<groupId>org.apache</groupId>
|
||||||
<artifactId>rocketmq-console-ng</artifactId>
|
<artifactId>rocketmq-console-ng</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>1.0.0</version>
|
<version>1.0.1</version>
|
||||||
<name>rocketmq-console-ng</name>
|
<name>rocketmq-console-ng</name>
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.rocketmq.console.config;
|
||||||
|
|
||||||
|
import org.apache.rocketmq.console.interceptor.AuthInterceptor;
|
||||||
|
import org.apache.rocketmq.console.model.UserInfo;
|
||||||
|
import org.apache.rocketmq.console.util.WebUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.MethodParameter;
|
||||||
|
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||||
|
import org.springframework.web.context.request.NativeWebRequest;
|
||||||
|
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||||
|
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||||
|
import org.springframework.web.multipart.support.MissingServletRequestPartException;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class AuthWebMVCConfigurerAdapter extends WebMvcConfigurerAdapter {
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("authInterceptor")
|
||||||
|
private AuthInterceptor authInterceptor;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
RMQConfigure configure;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
if (configure.isLoginRequired()) {
|
||||||
|
registry.addInterceptor(authInterceptor).excludePathPatterns("/error", "/user/guide/**", "/login/**");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||||
|
argumentResolvers.add(new HandlerMethodArgumentResolver() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsParameter(MethodParameter methodParameter) {
|
||||||
|
return methodParameter.getParameterType().isAssignableFrom(UserInfo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
|
||||||
|
NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
|
||||||
|
UserInfo userInfo = (UserInfo) WebUtil.getValueFromSession((HttpServletRequest) nativeWebRequest.getNativeRequest(),
|
||||||
|
UserInfo.USER_INFO);
|
||||||
|
if (userInfo != null) {
|
||||||
|
return userInfo;
|
||||||
|
}
|
||||||
|
throw new MissingServletRequestPartException(UserInfo.USER_INFO);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
super.addArgumentResolvers(argumentResolvers); //REVIEW ME
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,12 +17,18 @@
|
|||||||
package org.apache.rocketmq.console.config;
|
package org.apache.rocketmq.console.config;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.rocketmq.common.MixAll;
|
import org.apache.rocketmq.common.MixAll;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.web.servlet.ErrorPage;
|
||||||
|
import org.springframework.boot.web.servlet.ErrorPageRegistrar;
|
||||||
|
import org.springframework.boot.web.servlet.ErrorPageRegistry;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
import static org.apache.rocketmq.client.ClientConfig.SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY;
|
import static org.apache.rocketmq.client.ClientConfig.SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY;
|
||||||
|
|
||||||
@@ -37,12 +43,14 @@ public class RMQConfigure {
|
|||||||
private volatile String isVIPChannel = System.getProperty(SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY, "true");
|
private volatile String isVIPChannel = System.getProperty(SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY, "true");
|
||||||
|
|
||||||
|
|
||||||
private String dataPath;
|
private String dataPath = "/tmp/rocketmq-console/data";
|
||||||
|
|
||||||
private boolean enableDashBoardCollect;
|
private boolean enableDashBoardCollect;
|
||||||
|
|
||||||
private String msgTrackTopicName;
|
private String msgTrackTopicName;
|
||||||
|
|
||||||
|
private boolean loginRequired = false;
|
||||||
|
|
||||||
public String getNamesrvAddr() {
|
public String getNamesrvAddr() {
|
||||||
return namesrvAddr;
|
return namesrvAddr;
|
||||||
}
|
}
|
||||||
@@ -94,4 +102,27 @@ public class RMQConfigure {
|
|||||||
public void setMsgTrackTopicName(String msgTrackTopicName) {
|
public void setMsgTrackTopicName(String msgTrackTopicName) {
|
||||||
this.msgTrackTopicName = msgTrackTopicName;
|
this.msgTrackTopicName = msgTrackTopicName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLoginRequired() {
|
||||||
|
return loginRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginRequired(boolean loginRequired) {
|
||||||
|
this.loginRequired = loginRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error Page process logic, move to a central configure later
|
||||||
|
@Bean
|
||||||
|
public ErrorPageRegistrar errorPageRegistrar() {
|
||||||
|
return new MyErrorPageRegistrar();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MyErrorPageRegistrar implements ErrorPageRegistrar {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerErrorPages(ErrorPageRegistry registry) {
|
||||||
|
registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.rocketmq.console.controller;
|
||||||
|
|
||||||
|
import org.apache.rocketmq.console.config.RMQConfigure;
|
||||||
|
import org.apache.rocketmq.console.model.LoginInfo;
|
||||||
|
import org.apache.rocketmq.console.model.User;
|
||||||
|
import org.apache.rocketmq.console.model.UserInfo;
|
||||||
|
import org.apache.rocketmq.console.service.UserService;
|
||||||
|
import org.apache.rocketmq.console.util.WebUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/login")
|
||||||
|
public class LoginController {
|
||||||
|
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RMQConfigure configure;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
@RequestMapping(value = "/check.query", method = RequestMethod.GET)
|
||||||
|
@ResponseBody
|
||||||
|
public Object check(HttpServletRequest request) {
|
||||||
|
LoginInfo loginInfo = new LoginInfo();
|
||||||
|
|
||||||
|
loginInfo.setLogined(WebUtil.getValueFromSession(request, WebUtil.USER_NAME) != null);
|
||||||
|
loginInfo.setLoginRequired(configure.isLoginRequired());
|
||||||
|
|
||||||
|
return loginInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/login.do", method = RequestMethod.POST)
|
||||||
|
@ResponseBody
|
||||||
|
public Object login(@RequestParam("username") String username,
|
||||||
|
@RequestParam(value = "password") String password,
|
||||||
|
HttpServletRequest request,
|
||||||
|
HttpServletResponse response) throws Exception {
|
||||||
|
logger.info("user:{} login", username);
|
||||||
|
User user = userService.queryByUsernameAndPassword(username, password);
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
throw new IllegalArgumentException("Bad username or password!");
|
||||||
|
} else {
|
||||||
|
user.setPassword(null);
|
||||||
|
UserInfo userInfo = WebUtil.setLoginInfo(request, response, user);
|
||||||
|
WebUtil.setSessionValue(request, WebUtil.USER_INFO, userInfo);
|
||||||
|
WebUtil.setSessionValue(request, WebUtil.USER_NAME, username);
|
||||||
|
userInfo.setSessionId(WebUtil.getSessionId(request));
|
||||||
|
|
||||||
|
return userInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/logout.do", method = RequestMethod.POST)
|
||||||
|
@ResponseBody
|
||||||
|
public Object logout(HttpServletRequest request) {
|
||||||
|
WebUtil.removeSession(request);
|
||||||
|
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.rocketmq.console.interceptor;
|
||||||
|
|
||||||
|
import org.apache.rocketmq.console.service.LoginService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AuthInterceptor extends HandlerInterceptorAdapter {
|
||||||
|
@Autowired
|
||||||
|
private LoginService loginService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||||
|
throws Exception {
|
||||||
|
boolean ok = loginService.login(request, response);
|
||||||
|
if (!ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.rocketmq.console.model;
|
||||||
|
|
||||||
|
public class LoginInfo {
|
||||||
|
private boolean loginRequired;
|
||||||
|
private boolean logined;
|
||||||
|
|
||||||
|
public boolean isLoginRequired() {
|
||||||
|
return loginRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginRequired(boolean loginRequired) {
|
||||||
|
this.loginRequired = loginRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLogined() {
|
||||||
|
return logined;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogined(boolean logined) {
|
||||||
|
this.logined = logined;
|
||||||
|
}
|
||||||
|
}
|
||||||
83
src/main/java/org/apache/rocketmq/console/model/User.java
Normal file
83
src/main/java/org/apache/rocketmq/console/model/User.java
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.rocketmq.console.model;
|
||||||
|
|
||||||
|
import org.hibernate.validator.constraints.Range;
|
||||||
|
|
||||||
|
public class User {
|
||||||
|
public static final int ORDINARY = 0;
|
||||||
|
public static final int ADMIN = 1;
|
||||||
|
|
||||||
|
private long id;
|
||||||
|
private String name;
|
||||||
|
private String password;
|
||||||
|
@Range(min = 0, max = 1)
|
||||||
|
private int type = 0;
|
||||||
|
|
||||||
|
|
||||||
|
public User(String name, String password, int type) {
|
||||||
|
this.name = name;
|
||||||
|
this.password = password;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User cloneOne() {
|
||||||
|
return new User(this.name, this.password, this.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "User{" +
|
||||||
|
"id=" + id +
|
||||||
|
", name='" + name + '\'' +
|
||||||
|
", password='" + password + '\'' +
|
||||||
|
", type=" + type +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.rocketmq.console.model;
|
||||||
|
|
||||||
|
public class UserInfo {
|
||||||
|
public static final String USER_INFO = "userInfo";
|
||||||
|
private User user;
|
||||||
|
private long loginTime;
|
||||||
|
private String ip;
|
||||||
|
private String sessionId;
|
||||||
|
|
||||||
|
public long getLoginTime() {
|
||||||
|
return loginTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginTime(long loginTime) {
|
||||||
|
this.loginTime = loginTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIp() {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIp(String ip) {
|
||||||
|
this.ip = ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSessionId() {
|
||||||
|
return sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSessionId(String sessionId) {
|
||||||
|
this.sessionId = sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "UserInfo{" +
|
||||||
|
"user=" + user +
|
||||||
|
", loginTime=" + loginTime +
|
||||||
|
", ip='" + ip + '\'' +
|
||||||
|
", sessionId='" + sessionId + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.rocketmq.console.service;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
public interface LoginService {
|
||||||
|
boolean login(HttpServletRequest request, HttpServletResponse response);
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.rocketmq.console.service;
|
||||||
|
|
||||||
|
import org.apache.rocketmq.console.model.User;
|
||||||
|
|
||||||
|
public interface UserService {
|
||||||
|
User queryByName(String name);
|
||||||
|
|
||||||
|
User queryByUsernameAndPassword(String username, String password);
|
||||||
|
}
|
||||||
@@ -147,7 +147,9 @@ public class DashboardCollectServiceImpl implements DashboardCollectService {
|
|||||||
String dataLocationPath = rmqConfigure.getConsoleCollectData();
|
String dataLocationPath = rmqConfigure.getConsoleCollectData();
|
||||||
File file = new File(dataLocationPath + date + "_topic" + ".json");
|
File file = new File(dataLocationPath + date + "_topic" + ".json");
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
throw Throwables.propagate(new ServiceException(1, "This date have't data!"));
|
log.info(String.format("No dashboard data for data: %s", date));
|
||||||
|
//throw Throwables.propagate(new ServiceException(1, "This date have't data!"));
|
||||||
|
return Maps.newHashMap();
|
||||||
}
|
}
|
||||||
return jsonDataFile2map(file);
|
return jsonDataFile2map(file);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.rocketmq.console.service.impl;
|
||||||
|
|
||||||
|
import org.apache.rocketmq.console.config.RMQConfigure;
|
||||||
|
import org.apache.rocketmq.console.service.LoginService;
|
||||||
|
import org.apache.rocketmq.console.service.UserService;
|
||||||
|
import org.apache.rocketmq.console.util.WebUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class LoginServiceImpl implements LoginService {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RMQConfigure rmqConfigure;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean login(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
if (WebUtil.getValueFromSession(request, WebUtil.USER_NAME) != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auth(request, response);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void auth(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
try {
|
||||||
|
String url = WebUtil.getUrl(request);
|
||||||
|
try {
|
||||||
|
url = URLEncoder.encode(url, "UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
logger.error("url encode:{}", url, e);
|
||||||
|
}
|
||||||
|
WebUtil.redirect(response, request, "/#/login?redirect=" + url);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("redirect err", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.rocketmq.console.service.impl;
|
||||||
|
|
||||||
|
import org.apache.rocketmq.console.config.RMQConfigure;
|
||||||
|
import org.apache.rocketmq.console.exception.ServiceException;
|
||||||
|
import org.apache.rocketmq.console.model.User;
|
||||||
|
import org.apache.rocketmq.console.service.UserService;
|
||||||
|
import org.apache.rocketmq.srvutil.FileWatchService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserServiceImpl implements UserService, InitializingBean {
|
||||||
|
@Resource
|
||||||
|
RMQConfigure configure;
|
||||||
|
|
||||||
|
FileBasedUserInfoStore fileBasedUserInfoStore;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User queryByName(String name) {
|
||||||
|
return fileBasedUserInfoStore.queryByName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User queryByUsernameAndPassword(String username, String password) {
|
||||||
|
return fileBasedUserInfoStore.queryByUsernameAndPassword(username, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
if (configure.isEnableDashBoardCollect()) {
|
||||||
|
fileBasedUserInfoStore = new FileBasedUserInfoStore(configure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*packaged*/ static class FileBasedUserInfoStore {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
private static final String FILE_NAME = "users.properties";
|
||||||
|
|
||||||
|
private String filePath;
|
||||||
|
private final Map<String, User> userMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
public FileBasedUserInfoStore(RMQConfigure configure) {
|
||||||
|
filePath = configure.getRocketMqConsoleDataPath() + File.separator + FILE_NAME;
|
||||||
|
if (!new File(filePath).exists()) {
|
||||||
|
//Use the default path
|
||||||
|
InputStream inputStream = getClass().getResourceAsStream("/" + FILE_NAME);
|
||||||
|
if (inputStream == null) {
|
||||||
|
log.error(String.format("Can not found the file %s in Spring Boot jar", FILE_NAME));
|
||||||
|
System.out.printf(String.format("Can not found file %s in Spring Boot jar or %s, stop the console starting",
|
||||||
|
FILE_NAME, configure.getRocketMqConsoleDataPath()));
|
||||||
|
System.exit(1);
|
||||||
|
} else {
|
||||||
|
load(inputStream);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.info(String.format("Login Users configure file is %s", filePath));
|
||||||
|
load();
|
||||||
|
watch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load() {
|
||||||
|
load(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load(InputStream inputStream) {
|
||||||
|
|
||||||
|
Properties prop = new Properties();
|
||||||
|
try {
|
||||||
|
if (inputStream == null) {
|
||||||
|
prop.load(new FileReader(filePath));
|
||||||
|
} else {
|
||||||
|
prop.load(inputStream);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("load user.properties failed", e);
|
||||||
|
throw new ServiceException(0, String.format("Failed to load loginUserInfo property file: %s", filePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, User> loadUserMap = new HashMap<>();
|
||||||
|
String[] arrs;
|
||||||
|
int role;
|
||||||
|
for (String key : prop.stringPropertyNames()) {
|
||||||
|
String v = prop.getProperty(key);
|
||||||
|
if (v == null) continue;
|
||||||
|
arrs = v.split(",", 2);
|
||||||
|
if (arrs.length == 0) {
|
||||||
|
continue;
|
||||||
|
} else if (arrs.length == 1) {
|
||||||
|
role = 0;
|
||||||
|
} else {
|
||||||
|
role = Integer.parseInt(arrs[1].trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
loadUserMap.put(key, new User(key, arrs[0].trim(), role));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
userMap.clear();
|
||||||
|
userMap.putAll(loadUserMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean watch() {
|
||||||
|
try {
|
||||||
|
FileWatchService fileWatchService = new FileWatchService(new String[]{filePath}, new FileWatchService.Listener() {
|
||||||
|
@Override
|
||||||
|
public void onChanged(String path) {
|
||||||
|
log.info("The loginUserInfo property file changed, reload the context");
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fileWatchService.start();
|
||||||
|
log.info("Succeed to start LoginUserWatcherService");
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to start LoginUserWatcherService", e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public User queryByName(String name) {
|
||||||
|
return userMap.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public User queryByUsernameAndPassword(@NotNull String username, @NotNull String password) {
|
||||||
|
User user = queryByName(username);
|
||||||
|
if (user != null && password.equals(user.getPassword())) {
|
||||||
|
return user.cloneOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
140
src/main/java/org/apache/rocketmq/console/util/WebUtil.java
Normal file
140
src/main/java/org/apache/rocketmq/console/util/WebUtil.java
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.rocketmq.console.util;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.rocketmq.console.model.User;
|
||||||
|
import org.apache.rocketmq.console.model.UserInfo;
|
||||||
|
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
|
public class WebUtil {
|
||||||
|
public static final String USER_INFO = "userInfo";
|
||||||
|
public static final String USER_NAME = "username";
|
||||||
|
public static final String NEED_LOGIN = "needLogin";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain ServletRequest header value
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getHeaderValue(HttpServletRequest request, String name) {
|
||||||
|
String v = request.getHeader(name);
|
||||||
|
if (v == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return v.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch request ip address
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getIp(ServletRequest request) {
|
||||||
|
HttpServletRequest req = (HttpServletRequest) request;
|
||||||
|
String addr = getHeaderValue(req, "X-Forwarded-For");
|
||||||
|
if (StringUtils.isNotEmpty(addr) && addr.contains(",")) {
|
||||||
|
addr = addr.split(",")[0];
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(addr)) {
|
||||||
|
addr = getHeaderValue(req, "X-Real-IP");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(addr)) {
|
||||||
|
addr = req.getRemoteAddr();
|
||||||
|
}
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void redirect(HttpServletResponse response, HttpServletRequest request, String path) throws IOException {
|
||||||
|
response.sendRedirect(request.getContextPath() + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain the full url path
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getUrl(HttpServletRequest request) {
|
||||||
|
String url = request.getRequestURL().toString();
|
||||||
|
String queryString = request.getQueryString();
|
||||||
|
if (queryString != null) {
|
||||||
|
url += "?" + request.getQueryString();
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write content to front-page/response
|
||||||
|
*
|
||||||
|
* @param response
|
||||||
|
* @param result
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static void print(HttpServletResponse response, String result) throws IOException {
|
||||||
|
response.setContentType("text/html;charset=UTF-8");
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
out.print(result);
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getValueFromSession(HttpServletRequest request, String key) {
|
||||||
|
HttpSession session = request.getSession(false);
|
||||||
|
|
||||||
|
if (session != null) {
|
||||||
|
return session.getAttribute(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UserInfo setLoginInfo(HttpServletRequest request, HttpServletResponse response, User user) {
|
||||||
|
String ip = WebUtil.getIp(request);
|
||||||
|
UserInfo userInfo = new UserInfo();
|
||||||
|
userInfo.setIp(ip);
|
||||||
|
userInfo.setLoginTime(System.currentTimeMillis());
|
||||||
|
|
||||||
|
userInfo.setUser(user);
|
||||||
|
|
||||||
|
return userInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeSession(HttpServletRequest request) {
|
||||||
|
HttpSession session = request.getSession();
|
||||||
|
session.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSessionValue(HttpServletRequest request, String key, Object value) {
|
||||||
|
HttpSession session = request.getSession();
|
||||||
|
session.setAttribute(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSessionId(HttpServletRequest request) {
|
||||||
|
return request.getSession().getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,12 @@
|
|||||||
server.contextPath=
|
server.contextPath=
|
||||||
server.port=8080
|
server.port=8080
|
||||||
|
|
||||||
|
### SSL setting
|
||||||
|
#server.ssl.key-store=classpath:rmqcngkeystore.jks
|
||||||
|
#server.ssl.key-store-password=rocketmq
|
||||||
|
#server.ssl.keyStoreType=PKCS12
|
||||||
|
#server.ssl.keyAlias=rmqcngkey
|
||||||
|
|
||||||
#spring.application.index=true
|
#spring.application.index=true
|
||||||
spring.application.name=rocketmq-console
|
spring.application.name=rocketmq-console
|
||||||
spring.http.encoding.charset=UTF-8
|
spring.http.encoding.charset=UTF-8
|
||||||
@@ -15,4 +22,8 @@ rocketmq.config.dataPath=/tmp/rocketmq-console/data
|
|||||||
#set it false if you don't want use dashboard.default true
|
#set it false if you don't want use dashboard.default true
|
||||||
rocketmq.config.enableDashBoardCollect=true
|
rocketmq.config.enableDashBoardCollect=true
|
||||||
#set the message track trace topic if you don't want use the default one
|
#set the message track trace topic if you don't want use the default one
|
||||||
rocketmq.config.msgTrackTopicName=
|
rocketmq.config.msgTrackTopicName=
|
||||||
|
rocketmq.config.ticketKey=ticket
|
||||||
|
|
||||||
|
#Must create userInfo file: ${rocketmq.config.dataPath}/users.properties if the login is required
|
||||||
|
rocketmq.config.loginRequired=false
|
||||||
BIN
src/main/resources/rmqcngkeystore.jks
Normal file
BIN
src/main/resources/rmqcngkeystore.jks
Normal file
Binary file not shown.
@@ -113,6 +113,6 @@
|
|||||||
<script type="text/javascript" src="src/ops.js?timestamp=7"></script>
|
<script type="text/javascript" src="src/ops.js?timestamp=7"></script>
|
||||||
<script type="text/javascript" src="src/remoteApi/remoteApi.js"></script>
|
<script type="text/javascript" src="src/remoteApi/remoteApi.js"></script>
|
||||||
<script type="text/javascript" src="vendor/preLoading/main.js"></script>
|
<script type="text/javascript" src="vendor/preLoading/main.js"></script>
|
||||||
|
<script type="text/javascript" src="src/login.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
var initFlag = false;
|
||||||
|
var loginFlag = false;
|
||||||
var app = angular.module('app', [
|
var app = angular.module('app', [
|
||||||
'ngAnimate',
|
'ngAnimate',
|
||||||
'ngCookies',
|
'ngCookies',
|
||||||
@@ -29,27 +31,57 @@ var app = angular.module('app', [
|
|||||||
'localytics.directives',
|
'localytics.directives',
|
||||||
'pascalprecht.translate'
|
'pascalprecht.translate'
|
||||||
]).run(
|
]).run(
|
||||||
['$rootScope','$location','$cookies',
|
['$rootScope','$location','$cookies','$http', '$window','Notification',
|
||||||
function ($rootScope,$location,$cookies) {
|
function ($rootScope,$location,$cookies,$http, $window, Notification) {
|
||||||
// var filter = function(url){
|
var init = function(callback){
|
||||||
// var outFilterArrs = []
|
if (initFlag) return;
|
||||||
// outFilterArrs.push("/login");
|
initFlag = true;
|
||||||
// outFilterArrs.push("/reg");
|
|
||||||
// outFilterArrs.push("/logout");
|
|
||||||
// outFilterArrs.push("/404");
|
|
||||||
// var flag = false;
|
|
||||||
// $.each(outFilterArrs,function(i,value){
|
|
||||||
// if(url.indexOf(value) > -1){
|
|
||||||
// flag = true;
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// return flag;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if(angular.isDefined($cookies.get("isLogin")) && $cookies.get("isLogin") == 'true'){
|
var url = '/login/check.query';
|
||||||
// chatApi.login();
|
var setting = {
|
||||||
// }
|
type: "GET",
|
||||||
|
timeout:15000,
|
||||||
|
success:callback,
|
||||||
|
async:false
|
||||||
|
}
|
||||||
|
//sync invoke
|
||||||
|
$.ajax(url,setting)
|
||||||
|
}
|
||||||
|
console.log('initFlag0='+ initFlag + ' loginFlag0==='+loginFlag);
|
||||||
|
|
||||||
|
$rootScope.$on('$locationChangeStart', function (event, next, current) {
|
||||||
|
// redirect to login page if not logged in and trying to access a restricted page
|
||||||
|
init(function(resp){
|
||||||
|
if (resp.status == 0) {
|
||||||
|
// console.log('resp.data==='+resp.data);
|
||||||
|
var loginInfo = resp.data;
|
||||||
|
loginFlag = loginInfo.loginRequired;
|
||||||
|
if (!loginInfo.logined) {
|
||||||
|
$window.sessionStorage.clear();
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
Notification.error({message: "" + resp.errMsg, delay: 2000});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('initFlag='+ initFlag + ' loginFlag==='+loginFlag);
|
||||||
|
$rootScope.username = '';
|
||||||
|
if (loginFlag || loginFlag == "true") {
|
||||||
|
var username = $window.sessionStorage.getItem("username");
|
||||||
|
|
||||||
|
if (username != null) {
|
||||||
|
$rootScope.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log("username " + $rootScope.username);
|
||||||
|
var restrictedPage = $.inArray($location.path(), ['/login']) === -1;
|
||||||
|
if (restrictedPage && !username) {
|
||||||
|
var callback = $location.path();
|
||||||
|
$location.path('/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
$rootScope.$on('$routeChangeSuccess', function() {
|
$rootScope.$on('$routeChangeSuccess', function() {
|
||||||
@@ -77,6 +109,19 @@ var app = angular.module('app', [
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.factory('abc', function ($http, $window) {
|
||||||
|
console.log('xxxxxxx');
|
||||||
|
$http({
|
||||||
|
method: "GET",
|
||||||
|
url: "/login/check.query"
|
||||||
|
}).success(function (resp) {
|
||||||
|
if (resp.status == 0) {
|
||||||
|
alert(resp.data)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
app.provider('getDictName', function () {
|
app.provider('getDictName', function () {
|
||||||
|
|
||||||
var dictList = [];
|
var dictList = [];
|
||||||
@@ -125,11 +170,17 @@ app.config(['$routeProvider', '$httpProvider','$cookiesProvider','getDictNamePro
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// check login status
|
||||||
|
|
||||||
|
|
||||||
$httpProvider.defaults.cache = false;
|
$httpProvider.defaults.cache = false;
|
||||||
|
|
||||||
$routeProvider.when('/', {
|
$routeProvider.when('/', {
|
||||||
templateUrl: 'view/pages/index.html',
|
templateUrl: 'view/pages/index.html',
|
||||||
controller:'dashboardCtrl'
|
controller:'dashboardCtrl'
|
||||||
|
}).when('/login', {
|
||||||
|
templateUrl: 'view/pages/login.html',
|
||||||
|
controller:'loginController'
|
||||||
}).when('/cluster', {
|
}).when('/cluster', {
|
||||||
templateUrl: 'view/pages/cluster.html',
|
templateUrl: 'view/pages/cluster.html',
|
||||||
controller:'clusterController'
|
controller:'clusterController'
|
||||||
@@ -152,8 +203,8 @@ app.config(['$routeProvider', '$httpProvider','$cookiesProvider','getDictNamePro
|
|||||||
templateUrl: 'view/pages/ops.html',
|
templateUrl: 'view/pages/ops.html',
|
||||||
controller:'opsController'
|
controller:'opsController'
|
||||||
}).when('/404', {
|
}).when('/404', {
|
||||||
templateUrl: '404'
|
templateUrl: 'view/pages/404.html'
|
||||||
}).otherwise('404');
|
}).otherwise('/404');
|
||||||
|
|
||||||
$translateProvider.translations('en',en);
|
$translateProvider.translations('en',en);
|
||||||
$translateProvider.translations('zh',zh);
|
$translateProvider.translations('zh',zh);
|
||||||
|
|||||||
@@ -14,10 +14,20 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
app.controller('AppCtrl', ['$scope','$rootScope','$cookies','$location','$translate', function ($scope,$rootScope,$cookies,$location,$translate) {
|
app.controller('AppCtrl', ['$scope','$window','$translate','$http','Notification', function ($scope,$window,$translate, $http, Notification) {
|
||||||
$scope.changeTranslate = function(langKey){
|
$scope.changeTranslate = function(langKey){
|
||||||
$translate.use(langKey);
|
$translate.use(langKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.logout = function(){
|
||||||
|
$http({
|
||||||
|
method: "POST",
|
||||||
|
url: "login/logout.do"
|
||||||
|
}).success(function (resp) {
|
||||||
|
window.location = "/";
|
||||||
|
$window.sessionStorage.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
app.controller('dashboardCtrl', ['$scope','$rootScope','$translate','$filter','Notification','remoteApi','tools', function ($scope,$rootScope,$translate,$filter,Notification,remoteApi,tools) {
|
app.controller('dashboardCtrl', ['$scope','$rootScope','$translate','$filter','Notification','remoteApi','tools', function ($scope,$rootScope,$translate,$filter,Notification,remoteApi,tools) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
var en = {
|
var en = {
|
||||||
"TITLE": "RocketMq-Console-Ng",
|
"TITLE": "RocketMQ-Console",
|
||||||
"CLOSE": "Close",
|
"CLOSE": "Close",
|
||||||
"NO": "NO.",
|
"NO": "NO.",
|
||||||
"ADDRESS": "Address",
|
"ADDRESS": "Address",
|
||||||
@@ -77,5 +77,10 @@ var en = {
|
|||||||
"CLUSTER_NAME":"clusterName",
|
"CLUSTER_NAME":"clusterName",
|
||||||
"OPS":"OPS",
|
"OPS":"OPS",
|
||||||
"AUTO_REFRESH":"AUTO_REFRESH",
|
"AUTO_REFRESH":"AUTO_REFRESH",
|
||||||
"REFRESH":"REFRESH"
|
"REFRESH":"REFRESH",
|
||||||
|
"LOGOUT":"Logout",
|
||||||
|
"LOGIN":"Login",
|
||||||
|
"USER_NAME":"Username",
|
||||||
|
"PASSWORD":"Password",
|
||||||
|
"WELCOME":"Hi, welcome using RocketMQ Console"
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
var zh = {
|
var zh = {
|
||||||
"TITLE": "RocketMq控制台",
|
"TITLE": "RocketMQ控制台",
|
||||||
"CLOSE": "关闭",
|
"CLOSE": "关闭",
|
||||||
"NO": "编号",
|
"NO": "编号",
|
||||||
"ADDRESS": "地址",
|
"ADDRESS": "地址",
|
||||||
@@ -77,5 +77,10 @@ var zh = {
|
|||||||
"CLUSTER_NAME":"集群名",
|
"CLUSTER_NAME":"集群名",
|
||||||
"OPS":"运维",
|
"OPS":"运维",
|
||||||
"AUTO_REFRESH":"自动刷新",
|
"AUTO_REFRESH":"自动刷新",
|
||||||
"REFRESH":"刷新"
|
"REFRESH":"刷新",
|
||||||
|
"LOGOUT":"退出",
|
||||||
|
"LOGIN":"登录",
|
||||||
|
"USER_NAME":"用户名",
|
||||||
|
"PASSWORD":"密码",
|
||||||
|
"WELCOME":"您好,欢迎使用RocketMQ控制台"
|
||||||
}
|
}
|
||||||
46
src/main/resources/static/src/login.js
Normal file
46
src/main/resources/static/src/login.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
app.controller('loginController', ['$scope','$location','$http','Notification','$cookies','$window', function ($scope,$location,$http,Notification,$cookies, $window) {
|
||||||
|
$scope.login = function () {
|
||||||
|
if(!$("#username").val()) {
|
||||||
|
alert("用户名不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!$("#password").val()) {
|
||||||
|
alert("密码不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$http({
|
||||||
|
method: "POST",
|
||||||
|
url: "login/login.do",
|
||||||
|
params:{username:$("#username").val(), password:$("#password").val()}
|
||||||
|
}).success(function (resp) {
|
||||||
|
if (resp.status == 0) {
|
||||||
|
Notification.info({message: 'Login successful, redirect now', delay: 2000});
|
||||||
|
$window.sessionStorage.setItem("username", $("#username").val());
|
||||||
|
//alert("XXXXX resp.data="+resp.data.sessionId);
|
||||||
|
//$window.sessionStorage.setItem("sessionId", resp.data.sessionId);
|
||||||
|
window.location = "/";
|
||||||
|
initFlag = false;
|
||||||
|
} else{
|
||||||
|
Notification.error({message: resp.errMsg, delay: 2000});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}]);
|
||||||
@@ -28,7 +28,27 @@
|
|||||||
<li><a href="javascript:void(0)" ng-click="changeTranslate('zh')">Simplified Chinese</a></li>
|
<li><a href="javascript:void(0)" ng-click="changeTranslate('zh')">Simplified Chinese</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="dropdown" ng-show="username != ''">
|
||||||
|
<a href="bootstrap-elements.html" data-target="#" class="dropdown-toggle" data-toggle="dropdown">{{username}}
|
||||||
|
<b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="javascript:void(0)" ng-click="logout()">{{'LOGOUT' | translate}}</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var app = angular.module('DemoApp',[]);
|
||||||
|
|
||||||
|
app.controller('DemoController',function($scope){
|
||||||
|
$scope.IsVisible = false;
|
||||||
|
|
||||||
|
$scope.ShowHide = function(){
|
||||||
|
$scope.IsVisible = $scope.IsVisible = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
File diff suppressed because one or more lines are too long
42
src/main/resources/static/view/pages/login.html
Normal file
42
src/main/resources/static/view/pages/login.html
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<div id="loginModal" class="page-content" id="deployHistoryList" data-width="400" data-backdrop="static" role="main" >
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title">{{'WELCOME' | translate}}</h4>
|
||||||
|
</div>
|
||||||
|
<form class="form-horizontal form-bordered form-row-stripped" id="loginForm">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="form-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-md-4">{{'USER_NAME' | translate}}: </label>
|
||||||
|
<div class="col-md-5">
|
||||||
|
<input type="text" id="username" name="username" placeholder="{{'USER_NAME' | translate}}" class="form-control" ng-model="filterStr"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-md-4"> {{'PASSWORD' | translate}}: </label>
|
||||||
|
<div class="col-md-5">
|
||||||
|
<input type="password" name="password" id="password"
|
||||||
|
value="" placeholder="{{'USER_NAME' | translate}}"
|
||||||
|
class="form-control" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-raised btn-sm btn-primary" type="button" ng-click="login()">{{'LOGIN' | translate}}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
$(function(){
|
||||||
|
//$("#loginModal").modal("hide");
|
||||||
|
})
|
||||||
|
</script>
|
||||||
9
src/main/resources/users.properties
Normal file
9
src/main/resources/users.properties
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# This file supports hot change, any change will be auto-reloaded without Console restarting.
|
||||||
|
# Format: a user per line, username=password[,N] #N is optional, 0 (Normal User); 1 (Admin)
|
||||||
|
|
||||||
|
# Define Admin
|
||||||
|
admin=admin,1
|
||||||
|
|
||||||
|
# Define Users
|
||||||
|
user1=user1
|
||||||
|
user2=user2
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package org.apache.rocketmq.console.service.impl;
|
||||||
|
|
||||||
|
import org.apache.rocketmq.console.config.RMQConfigure;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class LoginFileTest {
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLoad() throws Exception {
|
||||||
|
RMQConfigure configure = new RMQConfigure();
|
||||||
|
configure.setDataPath(this.getClass().getResource("/").getPath());
|
||||||
|
|
||||||
|
UserServiceImpl.FileBasedUserInfoStore fileBasedUserInfoStore = new UserServiceImpl.FileBasedUserInfoStore(configure);
|
||||||
|
Assert.assertTrue("No exception raise for FileBasedUserInfoStore", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
src/test/resources/users.properties
Normal file
2
src/test/resources/users.properties
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
admin=admin
|
||||||
|
test=test
|
||||||
Reference in New Issue
Block a user