提交 de8e29f4 编写于 作者: C Captain.B

init code

上级 aab54477
# Created by .ignore support plugin (hsz.mobi)
.DS_Store
node_modules
node/
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
frontend.iml
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
src/main/resources/static
src/main/resources/templates
target
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>metersphere-server</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<shiro.version>1.4.0</shiro.version>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
<exclusion>
<artifactId>hibernate-validator</artifactId>
<groupId>org.hibernate.validator</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-collections</artifactId>
<groupId>commons-collections</groupId>
</exclusion>
<exclusion>
<artifactId>commons-beanutils</artifactId>
<groupId>commons-beanutils</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.45</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<addResources>true</addResources>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- Overlay guacamole-common-js (zip) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>main-class-placement</id>
<phase>generate-resources</phase>
<configuration>
<target>
<move todir="src/main/resources/static">
<fileset dir="../frontend/dist">
<exclude name="*.html"/>
</fileset>
</move>
<move todir="src/main/resources/templates">
<fileset dir="../frontend/dist">
<include name="*.html"/>
</fileset>
</move>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.fit2cloud.metersphere;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication(exclude = {QuartzAutoConfiguration.class})
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
package com.fit2cloud.metersphere.base.domain;
import java.io.Serializable;
public class User implements Serializable {
private String id;
private String name;
private String email;
private String phone;
private String status;
private Long createTime;
private Long updateTime;
private static final long serialVersionUID = 1L;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id == null ? null : id.trim();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email == null ? null : email.trim();
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone == null ? null : phone.trim();
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status == null ? null : status.trim();
}
public Long getCreateTime() {
return createTime;
}
public void setCreateTime(Long createTime) {
this.createTime = createTime;
}
public Long getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Long updateTime) {
this.updateTime = updateTime;
}
}
\ No newline at end of file
package com.fit2cloud.metersphere.base.mapper;
import com.fit2cloud.metersphere.base.domain.User;
import com.fit2cloud.metersphere.base.domain.UserExample;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserMapper {
long countByExample(UserExample example);
int deleteByExample(UserExample example);
int deleteByPrimaryKey(String id);
int insert(User record);
int insertSelective(User record);
List<User> selectByExample(UserExample example);
User selectByPrimaryKey(String id);
int updateByExampleSelective(@Param("record") User record, @Param("example") UserExample example);
int updateByExample(@Param("record") User record, @Param("example") UserExample example);
int updateByPrimaryKeySelective(User record);
int updateByPrimaryKey(User record);
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fit2cloud.metersphere.base.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.fit2cloud.metersphere.base.domain.User">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="email" jdbcType="VARCHAR" property="email" />
<result column="phone" jdbcType="VARCHAR" property="phone" />
<result column="status" jdbcType="VARCHAR" property="status" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Update_By_Example_Where_Clause">
<where>
<foreach collection="example.oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Base_Column_List">
id, name, email, phone, status, create_time, update_time
</sql>
<select id="selectByExample" parameterType="com.fit2cloud.metersphere.base.domain.UserExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from user
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from user
where id = #{id,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
delete from user
where id = #{id,jdbcType=VARCHAR}
</delete>
<delete id="deleteByExample" parameterType="com.fit2cloud.metersphere.base.domain.UserExample">
delete from user
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</delete>
<insert id="insert" parameterType="com.fit2cloud.metersphere.base.domain.User">
insert into user (id, name, email,
phone, status, create_time,
update_time)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR},
#{phone,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
#{updateTime,jdbcType=BIGINT})
</insert>
<insert id="insertSelective" parameterType="com.fit2cloud.metersphere.base.domain.User">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="name != null">
name,
</if>
<if test="email != null">
email,
</if>
<if test="phone != null">
phone,
</if>
<if test="status != null">
status,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="updateTime != null">
update_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="email != null">
#{email,jdbcType=VARCHAR},
</if>
<if test="phone != null">
#{phone,jdbcType=VARCHAR},
</if>
<if test="status != null">
#{status,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
#{createTime,jdbcType=BIGINT},
</if>
<if test="updateTime != null">
#{updateTime,jdbcType=BIGINT},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="com.fit2cloud.metersphere.base.domain.UserExample" resultType="java.lang.Long">
select count(*) from user
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
update user
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.name != null">
name = #{record.name,jdbcType=VARCHAR},
</if>
<if test="record.email != null">
email = #{record.email,jdbcType=VARCHAR},
</if>
<if test="record.phone != null">
phone = #{record.phone,jdbcType=VARCHAR},
</if>
<if test="record.status != null">
status = #{record.status,jdbcType=VARCHAR},
</if>
<if test="record.createTime != null">
create_time = #{record.createTime,jdbcType=BIGINT},
</if>
<if test="record.updateTime != null">
update_time = #{record.updateTime,jdbcType=BIGINT},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update user
set id = #{record.id,jdbcType=VARCHAR},
name = #{record.name,jdbcType=VARCHAR},
email = #{record.email,jdbcType=VARCHAR},
phone = #{record.phone,jdbcType=VARCHAR},
status = #{record.status,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="com.fit2cloud.metersphere.base.domain.User">
update user
<set>
<if test="name != null">
name = #{name,jdbcType=VARCHAR},
</if>
<if test="email != null">
email = #{email,jdbcType=VARCHAR},
</if>
<if test="phone != null">
phone = #{phone,jdbcType=VARCHAR},
</if>
<if test="status != null">
status = #{status,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
create_time = #{createTime,jdbcType=BIGINT},
</if>
<if test="updateTime != null">
update_time = #{updateTime,jdbcType=BIGINT},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="com.fit2cloud.metersphere.base.domain.User">
update user
set name = #{name,jdbcType=VARCHAR},
email = #{email,jdbcType=VARCHAR},
phone = #{phone,jdbcType=VARCHAR},
status = #{status,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>
\ No newline at end of file
package com.fit2cloud.metersphere.config;
import com.github.pagehelper.PageInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.util.Properties;
@Configuration
@MapperScan(basePackages = "com.fit2cloud.metersphere.base.mapper", sqlSessionFactoryRef = "sqlSessionFactory")
@EnableTransactionManagement
@PropertySource(value = {"file:/opt/fit2cloud/conf/metersphere.properties"}, encoding = "UTF-8", ignoreResourceNotFound = true)
public class MybatisConfig {
@Bean
@ConditionalOnMissingBean
public PageInterceptor pageInterceptor() {
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect", "mysql");
properties.setProperty("rowBoundsWithCount", "true");
properties.setProperty("reasonable", "true");
properties.setProperty("offsetAsPageNum", "true");
properties.setProperty("pageSizeZero", "true");
pageInterceptor.setProperties(properties);
return pageInterceptor;
}
}
\ No newline at end of file
package com.fit2cloud.metersphere.config;
import com.fit2cloud.metersphere.security.LoginFilter;
import com.fit2cloud.metersphere.security.ShiroDBRealm;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import java.util.EnumSet;
import java.util.Map;
import java.util.Objects;
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager sessionManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.getFilters().put("authc", new LoginFilter());
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setSecurityManager(sessionManager);
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
shiroFilterFactoryBean.setSuccessUrl("/");
Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap();
filterChainDefinitionMap.put("/resource/**", "anon");
filterChainDefinitionMap.put("/", "anon");
filterChainDefinitionMap.put("/signin", "anon");
filterChainDefinitionMap.put("/isLogin", "anon");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/api/**", "anon");
filterChainDefinitionMap.put("/403", "anon");
filterChainDefinitionMap.put("/anonymous/**", "anon");
filterChainDefinitionMap.put("/**", "authc");
return shiroFilterFactoryBean;
}
@Bean(name = "shiroFilter")
public FilterRegistrationBean<Filter> shiroFilter(ShiroFilterFactoryBean shiroFilterFactoryBean) throws Exception {
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
registration.setFilter((Filter) Objects.requireNonNull(shiroFilterFactoryBean.getObject()));
registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
return registration;
}
@Bean
public MemoryConstrainedCacheManager memoryConstrainedCacheManager() {
return new MemoryConstrainedCacheManager();
}
/**
* securityManager 不用直接注入shiroDBRealm,可能会导致事务失效
* 解决方法见 handleContextRefresh
* http://www.debugrun.com/a/NKS9EJQ.html
*/
@Bean(name = "securityManager")
public DefaultWebSecurityManager securityManager(SessionManager sessionManager, MemoryConstrainedCacheManager memoryConstrainedCacheManager) {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
dwsm.setSessionManager(sessionManager);
dwsm.setCacheManager(memoryConstrainedCacheManager);
return dwsm;
}
@Bean(name = "shiroDBRealm")
@DependsOn("lifecycleBeanPostProcessor")
public ShiroDBRealm getShiroDBRealm() {
return new ShiroDBRealm();
}
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
daap.setProxyTargetClass(true);
return daap;
}
@Bean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager sessionManager) {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(sessionManager);
return new AuthorizationAttributeSourceAdvisor();
}
@Bean
public SessionManager sessionManager(MemoryConstrainedCacheManager memoryConstrainedCacheManager) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionIdUrlRewritingEnabled(false);
sessionManager.setGlobalSessionTimeout(1800000L);
sessionManager.setDeleteInvalidSessions(true);
sessionManager.setSessionValidationSchedulerEnabled(true);
SimpleCookie sessionIdCookie = new SimpleCookie();
sessionManager.setSessionIdCookie(sessionIdCookie);
sessionIdCookie.setPath("/");
sessionIdCookie.setName("MS_SESSION_ID");
sessionManager.setCacheManager(memoryConstrainedCacheManager);
return sessionManager;
}
/**
* 等到ApplicationContext 加载完成之后 装配shiroRealm
*/
@EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
ApplicationContext context = event.getApplicationContext();
ShiroDBRealm shiroDBRealm = (ShiroDBRealm) context.getBean("shiroDBRealm");
((DefaultWebSecurityManager) context.getBean("securityManager")).setRealm(shiroDBRealm);
}
}
package com.fit2cloud.metersphere.config;
import com.fit2cloud.metersphere.interceptor.TestInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TestInterceptor());
}
}
package com.fit2cloud.metersphere.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
package com.fit2cloud.metersphere.controller;
import com.fit2cloud.metersphere.user.SessionUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping
public class IndexController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView index() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
return modelAndView;
}
@GetMapping(value = "/login")
public String login() {
if (SessionUtils.getUser() == null) {
return "login";
} else {
return "redirect:/";
}
}
}
package com.fit2cloud.metersphere.controller;
import com.fit2cloud.metersphere.controller.request.LoginRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping
public class LoginController {
@GetMapping(value = "/isLogin")
public ResultHolder isLogin() {
if (SecurityUtils.getSubject().isAuthenticated()) {
return ResultHolder.success("");
}
return ResultHolder.error("");
}
@PostMapping(value = "/signin")
public ResultHolder login(@RequestBody LoginRequest request) {
String msg;
String username = StringUtils.trim(request.getUsername());
String password = StringUtils.trim(request.getPassword());
if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
return ResultHolder.error("user or password can't be null");
}
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
if (subject.isAuthenticated()) {
return ResultHolder.success("");
} else {
return ResultHolder.error("login fail");
}
} catch (ExcessiveAttemptsException e) {
msg = "excessive attempts";
} catch (LockedAccountException e) {
msg = "the user has been locked.";
} catch (DisabledAccountException e) {
msg = "the user has been disabled. ";
} catch (ExpiredCredentialsException e) {
msg = "user expires. ";
} catch (AuthenticationException e) {
msg = e.getMessage();
} catch (UnauthorizedException e) {
msg = "not authorized. " + e.getMessage();
}
return ResultHolder.error(msg);
}
@GetMapping(value = "/signout")
public ResultHolder logout() {
SecurityUtils.getSubject().logout();
return ResultHolder.success("");
}
}
package com.fit2cloud.metersphere.controller;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
public class ResultHolder {
public ResultHolder() {
this.success = true;
}
private ResultHolder(Object data) {
this.data = data;
this.success = true;
}
private ResultHolder(boolean success, String msg) {
this.success = success;
this.message = msg;
}
private ResultHolder(boolean success, String msg, Object data) {
this.success = success;
this.message = msg;
this.data = data;
}
// 请求是否成功
private boolean success = false;
// 描述信息
private String message;
// 返回数据
private Object data = "";
public boolean isSuccess() {
return this.success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static ResultHolder success(Object obj) {
return new ResultHolder(obj);
}
public static ResultHolder error(String message) {
return new ResultHolder(false, message, null);
}
public static ResultHolder error(String message, Object object) {
return new ResultHolder(false, message, object);
}
public String toString() {
return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
package com.fit2cloud.metersphere.controller;
import com.fit2cloud.metersphere.user.SessionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/test")
public class TestController {
@GetMapping(value = "/{str}")
public Object getString(@PathVariable String str) throws InterruptedException {
if (StringUtils.equals("error", str)) {
throw new RuntimeException("test error");
}
if (StringUtils.equals("warning", str)) {
return ResultHolder.error("test warning");
}
if (StringUtils.equals("user", str)) {
return ResultHolder.success(SessionUtils.getUser());
}
if (StringUtils.equals("sleep", str)) {
Thread.sleep(2000L);
return ResultHolder.success(str);
}
return ResultHolder.success(str);
}
}
\ No newline at end of file
package com.fit2cloud.metersphere.controller.request;
public class LoginRequest {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.fit2cloud.metersphere.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// response.setHeader("Authentication-Status", "invalid");
return true;
}
}
package com.fit2cloud.metersphere.security;
import com.alibaba.fastjson.JSONObject;
import com.fit2cloud.metersphere.controller.ResultHolder;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginFilter extends FormAuthenticationFilter {
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS")) {
return true;
}
return super.isAccessAllowed(request, response, mappedValue);
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
if (httpServletRequest.getServletPath().endsWith("login")) {
return super.onAccessDenied(request, response);
}
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json");
httpServletResponse.setHeader("authentication-status", "invalid");
ResultHolder result = ResultHolder.error("Authentication Status Invalid");
httpServletResponse.getWriter().write(JSONObject.toJSON(result).toString());
return true;
}
}
package com.fit2cloud.metersphere.security;
import com.fit2cloud.metersphere.user.SessionUser;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 自定义Realm 注入service 可能会导致在 service的aop 失效,例如@Transactional,
* 解决方法:
* <p>
* 1. 这里改成注入mapper,这样mapper 中的事务失效<br/>
* 2. 这里仍然注入service,在配置ShiroConfig 的时候不去set realm, 等到spring 初始化完成之后
* set realm
* </p>
*/
public class ShiroDBRealm extends AuthorizingRealm {
private Logger logger = LoggerFactory.getLogger(ShiroDBRealm.class);
/**
* 权限认证
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
/**
* 登录认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String userId = token.getUsername();
String password = String.valueOf(token.getPassword());
SessionUser sessionUser = new SessionUser();
sessionUser.setName(userId);
sessionUser.setId(userId);
SecurityUtils.getSubject().getSession().setAttribute("user", sessionUser);
return new SimpleAuthenticationInfo(userId, password, getName());
}
@Override
public boolean isPermitted(PrincipalCollection principals, String permission) {
return true;
}
}
package com.fit2cloud.metersphere.user;
import java.io.Serializable;
public class SessionUser implements Serializable {
private static final long serialVersionUID = -7149638440406959033L;
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.fit2cloud.metersphere.user;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
public class SessionUtils {
public static SessionUser getUser() {
try {
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
return (SessionUser) session.getAttribute("user");
} catch (Exception e) {
return null;
}
}
}
package com.fit2cloud.metersphere.websocket;
import com.fit2cloud.metersphere.user.SessionUtils;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
public class ServerEndpointConfigurator extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
// 将用户信息存储到socket的配置里
System.out.println(SessionUtils.getUser());
sec.getUserProperties().put("user", SessionUtils.getUser());
super.modifyHandshake(sec, request, response);
}
}
package com.fit2cloud.metersphere.websocket;
import com.fit2cloud.metersphere.user.SessionUtils;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
@ServerEndpoint(value = "/socket", configurator = ServerEndpointConfigurator.class)
@Component
public class WebSocketServer {
@OnOpen
public void onOpen(Session session) throws IOException {
// Get session and WebSocket connection
System.out.println("open: " + session.isOpen());
System.out.println("open: " + SessionUtils.getUser());
System.out.println("open: " + session.getUserProperties().get("user"));
}
@OnMessage
public void onMessage(Session session, String message) throws IOException {
// Handle new messages
System.out.println(message);
}
@OnClose
public void onClose(Session session) throws IOException {
// WebSocket connection closes
System.out.println("close: " + session.isOpen());
}
@OnError
public void onError(Session session, Throwable throwable) {
// Do error handling here
throwable.printStackTrace();
}
}
spring.application.name=metersphere
server.port=8888
# Hikari
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
# mybatis
mybatis.configuration.cache-enabled=true
mybatis.configuration.lazy-loading-enabled=false
mybatis.configuration.aggressive-lazy-loading=true
mybatis.configuration.multiple-result-sets-enabled=true
mybatis.configuration.use-column-label=true
mybatis.configuration.auto-mapping-behavior=full
mybatis.configuration.default-statement-timeout=25000
mybatis.mapper-locations=classpath:mybatis/**/*.xml,classpath*:com/fit2cloud/metersphere/mapper/**/*.xml
logging.file.path=/opt/fit2cloud/logs/${spring.application.name}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration>
<!--配置数据库连接的位置-->
<properties url="file:///opt/fit2cloud/conf/metersphere.properties"/>
<!-- 设置mysql驱动路径 -->
<!--<classPathEntry location="/Users/liuruibin/.m2/repository/mysql/mysql-connector-java/5.1.34/mysql-connector-java-5.1.34.jar"/>-->
<!-- 此处指定生成针对MyBatis3的DAO -->
<context id="mysql" targetRuntime="MyBatis3">
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin" />
<!-- 用来除去时间信息的,这在配合类似subversion的代码管理工具时使用很有效,因为可以减少没有必要的注释迁入 -->
<commentGenerator>
<property name="suppressDate" value="true"/>
<!-- 关闭自动生成的注释 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!-- jdbc连接信息 --> <!-- EduLoanManage EduTestDataBase -->
<!--<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://192.168.20.180:3306/fit2cloud"-->
<!--userId="root" password="Fit2cloud2015!" />-->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="${spring.datasource.url}"
userId="${spring.datasource.username}" password="${spring.datasource.password}"/>
<!-- javaTypeResolver式类型转换的信息 -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- 模型对象 -->
<javaModelGenerator targetPackage="com.fit2cloud.metersphere.base.domain" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- XML映射文件 -->
<sqlMapGenerator targetPackage="com.fit2cloud.metersphere.base.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- 接口 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.fit2cloud.metersphere.base.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!--要生成的数据库表 -->
<table tableName="user"/>
</context>
</generatorConfiguration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<property resource="application.properties"/>
<!-- <property file="/opt/fruit/conf/peach.properties"/>-->
<include resource="logback-elastic.xml"/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
</encoder>
</appender>
<appender name="debugAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<File>${logging.file.path}/debug.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.file.path}/history/debug.%d{yyyyMMdd}-%i.log
</FileNamePattern>
<maxHistory>30</maxHistory>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>50MB</maxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<charset>UTF-8</charset>
<Pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</Pattern>
</encoder>
</appender>
<appender name="infoAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<File>${logging.file.path}/info.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.file.path}/history/info.%d{yyyyMMdd}-%i.log
</FileNamePattern>
<maxHistory>30</maxHistory>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>50MB</maxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<charset>UTF-8</charset>
<Pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</Pattern>
</encoder>
</appender>
<appender name="errorAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<File>${logging.file.path}/error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.file.path}/history/error.%d{yyyyMMdd}-%i.log
</FileNamePattern>
<maxHistory>30</maxHistory>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>50MB</maxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<charset>UTF-8</charset>
<Pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</Pattern>
</encoder>
</appender>
<appender name="warnAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<File>${logging.file.path}/warn.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.file.path}/history/warn.%d{yyyyMMdd}-%i.log
</FileNamePattern>
<maxHistory>30</maxHistory>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>50MB</maxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<charset>UTF-8</charset>
<Pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</Pattern>
</encoder>
</appender>
<appender name="consoleAsyncAppender" class="ch.qos.logback.classic.AsyncAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<queueSize>10000</queueSize>
<appender-ref ref="console" />
</appender>
<appender name="debugAsyncAppender" class="ch.qos.logback.classic.AsyncAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<queueSize>10000</queueSize>
<appender-ref ref="debugAppender" />
</appender>
<appender name="infoAsyncAppender" class="ch.qos.logback.classic.AsyncAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<queueSize>10000</queueSize>
<appender-ref ref="infoAppender" />
</appender>
<appender name="errorAsyncAppender" class="ch.qos.logback.classic.AsyncAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<queueSize>10000</queueSize>
<includeCallerData>true</includeCallerData>
<appender-ref ref="errorAppender" />
</appender>
<appender name="warnAsyncAppender" class="ch.qos.logback.classic.AsyncAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
<queueSize>10000</queueSize>
<includeCallerData>true</includeCallerData>
<appender-ref ref="warnAppender" />
</appender>
<root level="INFO">
<appender-ref ref="infoAsyncAppender" />
<appender-ref ref="console" />
</root>
<logger name="com.fruit" additivity="false">
<level value="${logger.level:INFO}" />
<appender-ref ref="debugAsyncAppender" />
<appender-ref ref="infoAsyncAppender" />
<appender-ref ref="warnAsyncAppender" />
<appender-ref ref="errorAsyncAppender" />
</logger>
<logger name="com.fruit.peach.Application" additivity="false" level="${logger.level:INFO}">
<appender-ref ref="infoAsyncAppender" />
</logger>
</configuration>
\ No newline at end of file
package com.fit2cloud.metersphere;
import com.fit2cloud.metersphere.base.domain.User;
import com.fit2cloud.metersphere.base.mapper.UserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ApplicationTests {
@Resource
UserMapper userMapper;
@Test
public void test1() {
List<User> users = userMapper.selectByExample(null);
System.out.println(users);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册