diff --git a/renren-admin/pom.xml b/renren-admin/pom.xml index b1403129..90d7eda3 100644 --- a/renren-admin/pom.xml +++ b/renren-admin/pom.xml @@ -90,11 +90,38 @@ + + + + org.springframework.boot + spring-boot-devtools + provided + true + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.9.2 + + + org.mybatis + mybatis-typehandlers-jsr310 + 1.0.2 + + ${project.artifactId} + + org.springframework.boot + spring-boot-maven-plugin + + true + + org.springframework.boot spring-boot-maven-plugin diff --git a/renren-admin/src/main/java/io/renren/common/config/JacksonConfig.java b/renren-admin/src/main/java/io/renren/common/config/JacksonConfig.java new file mode 100644 index 00000000..74c087bf --- /dev/null +++ b/renren-admin/src/main/java/io/renren/common/config/JacksonConfig.java @@ -0,0 +1,34 @@ +package io.renren.common.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +/** + * @author 李帅超 + * @Description: SpringMVC整合LocalDateTime用到jackson + * @date 2018-03-06 11:01 + */ +@Configuration +public class JacksonConfig { + + @Bean(name = "mapperObject") + public ObjectMapper getObjectMapper() { + ObjectMapper om = new ObjectMapper(); + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); + javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss"))); + om.registerModule(javaTimeModule); + return om; + } +} diff --git a/renren-admin/src/main/java/io/renren/common/config/ShiroConfig.java b/renren-admin/src/main/java/io/renren/common/config/ShiroConfig.java index 5ba87538..e8b62aa7 100644 --- a/renren-admin/src/main/java/io/renren/common/config/ShiroConfig.java +++ b/renren-admin/src/main/java/io/renren/common/config/ShiroConfig.java @@ -77,6 +77,7 @@ public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { shiroFilter.setUnauthorizedUrl("/"); Map filterMap = new LinkedHashMap<>(); + filterMap.put("/sys/captcha", "anon"); filterMap.put("/swagger/**", "anon"); filterMap.put("/v2/api-docs", "anon"); filterMap.put("/swagger-ui.html", "anon"); diff --git a/renren-admin/src/main/java/io/renren/common/utils/Constant.java b/renren-admin/src/main/java/io/renren/common/utils/Constant.java index 12bf3322..2c8dc5c1 100644 --- a/renren-admin/src/main/java/io/renren/common/utils/Constant.java +++ b/renren-admin/src/main/java/io/renren/common/utils/Constant.java @@ -85,6 +85,10 @@ public int getValue() { * 云服务商 */ public enum CloudService { + /** + * 服务器 + */ + LOCAL(0), /** * 七牛云 */ diff --git a/renren-admin/src/main/java/io/renren/modules/oss/cloud/CloudStorageConfig.java b/renren-admin/src/main/java/io/renren/modules/oss/cloud/CloudStorageConfig.java index 777f767b..587ed854 100644 --- a/renren-admin/src/main/java/io/renren/modules/oss/cloud/CloudStorageConfig.java +++ b/renren-admin/src/main/java/io/renren/modules/oss/cloud/CloudStorageConfig.java @@ -37,7 +37,7 @@ public class CloudStorageConfig implements Serializable { private static final long serialVersionUID = 1L; //类型 1:七牛 2:阿里云 3:腾讯云 - @Range(min=1, max=3, message = "类型错误") + @Range(min=0, max=3, message = "类型错误") private Integer type; //七牛绑定的域名 diff --git a/renren-admin/src/main/java/io/renren/modules/oss/cloud/LocalCloudStorageService.java b/renren-admin/src/main/java/io/renren/modules/oss/cloud/LocalCloudStorageService.java new file mode 100644 index 00000000..d585724c --- /dev/null +++ b/renren-admin/src/main/java/io/renren/modules/oss/cloud/LocalCloudStorageService.java @@ -0,0 +1,84 @@ +package io.renren.modules.oss.cloud; + +import io.renren.common.exception.RRException; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.util.ResourceUtils; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Random; + +/** + * @author 李帅超 + * @Description: TODO + * @date 2018-03-06 12:49 + */ +@Component +public class LocalCloudStorageService extends CloudStorageService { + @Value("${upload.base.dir}") + private String baseDir; + + + public LocalCloudStorageService(){ + + } + + @Override + public String upload(byte[] data, String path) { + return upload(new ByteArrayInputStream(data), path); + } + + @Override + public String upload(InputStream inputStream, String path) { + try { + FileUtils.copyInputStreamToFile(inputStream,new File(getBaseDir() + path)); + } catch (Exception e){ + throw new RRException("上传文件失败,请检查配置信息", e); + } + + return path; + } + + @Override + public String uploadSuffix(byte[] data, String suffix) { + String path = getPathBySuffix(suffix); + return upload(data, path); + } + + @Override + public String uploadSuffix(InputStream inputStream, String suffix) { + String path = getPathBySuffix(suffix); + return upload(inputStream, path); + } + + /** + * 通过文件后缀生成文件本地路径 + * @param suffix + * @return + */ + private String getPathBySuffix(String suffix) { + LocalDate localDate = LocalDate.now(); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd"); + String str = "/"; + String dir = "/resource/"; + return dir + localDate.format(dateTimeFormatter) + str +System.currentTimeMillis() + new Random().nextInt(10000)+suffix; + } + + private String getBaseDir(){ + if(StringUtils.isBlank(baseDir)){ + try { + baseDir = ResourceUtils.getURL("classpath:public").getPath(); + } catch (FileNotFoundException e) { + throw new RRException("上传文件失败,请检查本地路径配置信息", e); + } + } + return baseDir; + } +} diff --git a/renren-admin/src/main/java/io/renren/modules/oss/cloud/OSSFactory.java b/renren-admin/src/main/java/io/renren/modules/oss/cloud/OSSFactory.java index 9ec9d614..6a26b65b 100644 --- a/renren-admin/src/main/java/io/renren/modules/oss/cloud/OSSFactory.java +++ b/renren-admin/src/main/java/io/renren/modules/oss/cloud/OSSFactory.java @@ -38,8 +38,10 @@ public final class OSSFactory { public static CloudStorageService build(){ //获取云存储配置信息 CloudStorageConfig config = sysConfigService.getConfigObject(ConfigConstant.CLOUD_STORAGE_CONFIG_KEY, CloudStorageConfig.class); - - if(config.getType() == Constant.CloudService.QINIU.getValue()){ + if(config.getType() == Constant.CloudService.LOCAL.getValue()){ + //return new LocalCloudStorageService(); + return SpringContextUtils.getBean("localCloudStorageService",LocalCloudStorageService.class); + }else if(config.getType() == Constant.CloudService.QINIU.getValue()){ return new QiniuCloudStorageService(config); }else if(config.getType() == Constant.CloudService.ALIYUN.getValue()){ return new AliyunCloudStorageService(config); diff --git a/renren-admin/src/main/java/io/renren/modules/oss/controller/SysOssController.java b/renren-admin/src/main/java/io/renren/modules/oss/controller/SysOssController.java index f980ebd1..290ec9f5 100644 --- a/renren-admin/src/main/java/io/renren/modules/oss/controller/SysOssController.java +++ b/renren-admin/src/main/java/io/renren/modules/oss/controller/SysOssController.java @@ -141,7 +141,6 @@ public R upload(@RequestParam("file") MultipartFile file) throws Exception { @RequiresPermissions("sys:oss:all") public R delete(@RequestBody Long[] ids){ sysOssService.deleteBatchIds(Arrays.asList(ids)); - return R.ok(); } diff --git a/renren-admin/src/main/java/io/renren/modules/sys/controller/SysLoginController.java b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysLoginController.java index a8109014..79db8d1e 100644 --- a/renren-admin/src/main/java/io/renren/modules/sys/controller/SysLoginController.java +++ b/renren-admin/src/main/java/io/renren/modules/sys/controller/SysLoginController.java @@ -24,7 +24,9 @@ import org.apache.shiro.authc.*; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; 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.bind.annotation.ResponseBody; @@ -32,6 +34,7 @@ import javax.imageio.ImageIO; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; import java.awt.image.BufferedImage; import java.io.IOException; @@ -46,51 +49,97 @@ public class SysLoginController { @Autowired private Producer producer; - + private String errorNumber = "errorNumber"; + @Value("${captcha.error.number:5}") + private Integer captchaErrorNumber; + + /** + * 生成验证码 + * @param response + * @throws IOException + */ @RequestMapping("captcha.jpg") public void captcha(HttpServletResponse response)throws IOException { response.setHeader("Cache-Control", "no-store, no-cache"); response.setContentType("image/jpeg"); - //生成文字验证码 String text = producer.createText(); //生成图片验证码 BufferedImage image = producer.createImage(text); //保存到shiro session ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text); - ServletOutputStream out = response.getOutputStream(); ImageIO.write(image, "jpg", out); } + + /** + * 登陆是否需要输入验证码 + * @return + */ + @GetMapping("/sys/captcha") + @ResponseBody + public R geterrorNumber(HttpSession session){ + //判断次数 + Integer errorNum = (Integer) session.getAttribute(errorNumber); + if (captchaErrorNumber==null){ + captchaErrorNumber = 0; + } + if(errorNum == null||errorNum < captchaErrorNumber){ + return R.ok().put("code",0); + }else{ + return R.error("请求次数过多,需要显示验证码").put("code",1); + } + } + /** * 登录 */ @ResponseBody @RequestMapping(value = "/sys/login", method = RequestMethod.POST) - public R login(String username, String password, String captcha) { + public R login(String username, String password, String captcha,HttpSession session) { String kaptcha = ShiroUtils.getKaptcha(Constants.KAPTCHA_SESSION_KEY); - if(!captcha.equalsIgnoreCase(kaptcha)){ - return R.error("验证码不正确"); + //验证码输错次数 + Integer errorNum = (Integer) session.getAttribute(errorNumber); + if (captchaErrorNumber==null){ + captchaErrorNumber = 0; + } + if(errorNum != null&&errorNum >= captchaErrorNumber){ + if(!captcha.equalsIgnoreCase(kaptcha)){ + return R.error("验证码不正确"); + } } - + try{ Subject subject = ShiroUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); subject.login(token); }catch (UnknownAccountException e) { + addErrorNumber(session); return R.error(e.getMessage()); }catch (IncorrectCredentialsException e) { + addErrorNumber(session); return R.error("账号或密码不正确"); }catch (LockedAccountException e) { + addErrorNumber(session); return R.error("账号已被锁定,请联系管理员"); }catch (AuthenticationException e) { + addErrorNumber(session); return R.error("账户验证失败"); } return R.ok(); } - + + /** + * 增加验证错误次数 + */ + private void addErrorNumber(HttpSession session) { + Integer errorNum = (Integer) session.getAttribute(errorNumber); + session.setAttribute(errorNumber, (errorNum==null?0:errorNum) + 1); + } + + /** * 退出 */ diff --git a/renren-admin/src/main/java/io/renren/modules/sys/shiro/ShiroUtils.java b/renren-admin/src/main/java/io/renren/modules/sys/shiro/ShiroUtils.java index 614ca77f..3f17d64c 100644 --- a/renren-admin/src/main/java/io/renren/modules/sys/shiro/ShiroUtils.java +++ b/renren-admin/src/main/java/io/renren/modules/sys/shiro/ShiroUtils.java @@ -16,7 +16,6 @@ package io.renren.modules.sys.shiro; -import io.renren.common.exception.RRException; import io.renren.modules.sys.entity.SysUserEntity; import org.apache.shiro.SecurityUtils; import org.apache.shiro.crypto.hash.SimpleHash; @@ -74,9 +73,9 @@ public static void logout() { public static String getKaptcha(String key) { Object kaptcha = getSessionAttribute(key); - if(kaptcha == null){ + /*if(kaptcha == null){ throw new RRException("验证码已失效"); - } + }*/ getSession().removeAttribute(key); return kaptcha.toString(); } diff --git a/renren-admin/src/main/resources/application-dev.yml b/renren-admin/src/main/resources/application-dev.yml index d4a3765b..a7432928 100644 --- a/renren-admin/src/main/resources/application-dev.yml +++ b/renren-admin/src/main/resources/application-dev.yml @@ -4,13 +4,13 @@ spring: driverClassName: com.mysql.jdbc.Driver druid: first: #数据源1 - url: jdbc:mysql://localhost:3306/renren_security?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 - username: renren - password: 123456 + url: jdbc:mysql://192.168.29.212:3306/renren_security?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 + username: root + password: ABCabc@123. second: #数据源2 - url: jdbc:mysql://10.10.168.18:3306/renren_security?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 - username: renren - password: 123456 + url: jdbc:mysql://192.168.29.212:3306/renren_security?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 + username: root + password: ABCabc@123. initial-size: 10 max-active: 100 min-idle: 10 diff --git a/renren-admin/src/main/resources/application.yml b/renren-admin/src/main/resources/application.yml index 87b8b1e4..5a4d03ea 100644 --- a/renren-admin/src/main/resources/application.yml +++ b/renren-admin/src/main/resources/application.yml @@ -6,9 +6,19 @@ server: min-spare-threads: 30 port: 8080 context-path: /renren-admin - +#文件上传文件夹 +upload: + base: + dir: #D:/ziyuan/ +captcha: + error: + number: 5 # mysql spring: + mvc: + static-path-pattern: /** + resources: + static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${upload.base.dir} # 环境 dev|test|prod profiles: active: dev @@ -35,6 +45,7 @@ spring: freemarker: suffix: .html request-context-attribute: request + # Mybatis配置 #mybatis: # mapperLocations: classpath:mapper/**/*.xml @@ -78,4 +89,4 @@ mybatis-plus: call-setters-on-nulls: true #logging logging: - level: debug \ No newline at end of file + level: debug diff --git a/renren-admin/src/main/resources/statics/js/modules/oss/oss.js b/renren-admin/src/main/resources/statics/js/modules/oss/oss.js index ff900b48..a5a9cff1 100644 --- a/renren-admin/src/main/resources/statics/js/modules/oss/oss.js +++ b/renren-admin/src/main/resources/statics/js/modules/oss/oss.js @@ -4,8 +4,9 @@ $(function () { datatype: "json", colModel: [ { label: 'id', name: 'id', width: 20, key: true }, - { label: 'URL地址', name: 'url', width: 160 }, - { label: '创建时间', name: 'createDate', width: 40 } + { label: '图片', name: 'url', width: 10 ,index: 'dsource_alarm',align: "center", sortable: false, editable: false, formatter: alarmFormatter }, + { label: 'URL地址', name: 'url', width: 150 }, + { label: '创建时间', name: 'createDate', width: 40} ], viewrecords: true, height: 385, @@ -32,7 +33,12 @@ $(function () { $("#jqGrid").closest(".ui-jqgrid-bdiv").css({ "overflow-x" : "hidden" }); } }); + function alarmFormatter(cellvalue, options, rowdata) + { + return ''; + + } new AjaxUpload('#upload', { action: baseURL + "sys/oss/upload", name: 'file', diff --git a/renren-admin/src/main/resources/templates/index.html b/renren-admin/src/main/resources/templates/index.html index 124f77c8..449a10ec 100644 --- a/renren-admin/src/main/resources/templates/index.html +++ b/renren-admin/src/main/resources/templates/index.html @@ -27,9 +27,9 @@