SpringBoot + Spring Security + UEditor整合笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq1107533660/article/details/80857160

UEditor 已经停止维护,最后版本停留在16年,但胜在插件多,所有一直在使用。
UEditor的核心控制器是JSP写的,但是SpringBoot抛弃了JSP,导致兼容性出现很大的问题。
所以需要将Ueditor改造一番,让其能与SpringBoot兼容。

  • 导入Ueditor的依赖
<!--UEditor依赖的jar包 -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20180130</version>
        </dependency>

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.11</version>
        </dependency>
  • 将uedito的jar包解开,放入工程

这里写图片描述

  • 解开之后,就需要修改一些方法

ConfigManager是读取配置文件的类,修改getConfigPath方法,让其可以顺利读取到config.json,我这里将config.json放到了resources目录下。

private String getConfigPath() {
        try {    
            //获取classpath下的config.json路径          
            String path  = this.getClass().getClassLoader().getResource("config.json").getPath();
            System.out.println(path);
            return path;
        } catch (Exception e) {
            return null;
        }
    }

BinaryUploader是文件上传类,修改save方法

public static final State save(HttpServletRequest request, Map<String, Object> conf) {
        if (!ServletFileUpload.isMultipartContent(request)) {
            return new BaseState(false, 5);
        } else {

            try {
                MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
                MultipartFile multipartFile = multipartRequest.getFile(conf.get("fieldName").toString());
                if(multipartFile==null){
                    return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
                }

                String savePath = (String) conf.get("savePath");
                String originFileName = multipartFile.getOriginalFilename();
                String suffix = FileType.getSuffixByFilename(originFileName);

                originFileName = originFileName.substring(0,
                        originFileName.length() - suffix.length());
                savePath = savePath + suffix;

                long maxSize = ((Long) conf.get("maxSize")).longValue();

                if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
                    return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
                }

                savePath = PathFormat.parse(savePath, originFileName);


                String basePath=(String) conf.get("basePath");
                String physicalPath = basePath + savePath;

                InputStream is = multipartFile.getInputStream();
                State storageState = StorageManager.saveFileByInputStream(is,
                        physicalPath, maxSize);
                is.close();

                if (storageState.isSuccess()) {
                    storageState.putInfo("url", PathFormat.format(savePath));
                    storageState.putInfo("type", suffix);
                    storageState.putInfo("original", originFileName + suffix);
                }

                return storageState;

            } catch (IOException var15) {
                return new BaseState(false, 4);
            }
        }
    }

在上面用到一个config.json没有的参数basePath,所有需要config.json添加该参数,指向文件保存的路径

  • 新建一个controller,替代原有的controller.jsp


import com.baidu.ueditor.ActionEnter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Controller
@RequestMapping("/")
public class UEditorController {

    @RequestMapping(value="/config")
    public void config(HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("application/json");
        String rootPath = request.getSession().getServletContext().getRealPath("/");
        try {
            String exec = new ActionEnter(request, rootPath).exec();
            PrintWriter writer = response.getWriter();
            writer.write(exec);
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
  • 导入ueditor的相关文件
    这里写图片描述

  • 更改ueditor.config.js访问的controller
    这里写图片描述

  • 修改application.yml配置文件

spring:
    resources:
        static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${file.upload.savePath}
    mvc:
        static-path-pattern: /**
file:
    upload:
        savePath: /User/Qianyuan/Ueditor/File/
    download:
        url: http://127.0.0.1:8891/
  • 页面引入并初始化

<body>
...
 <script id="container" name="content" type="text/plain"></script>
...
</body>
...
<script src="/ueditor/ueditor.config.js"></script>
<script src="/ueditor/ueditor.all.js"></script>
<script>
    var ue = UE.getEditor('container');
</script>

如果正确配置config.json中的imageUrlPrefix 和 imagePathFormat,此时启动项目,ueditor已经可以正常使用,但是打包后无法正确读取配置文件,并且配置不太方便,所以准备移除config.json文件

  • 新建配置文件类
    public static String path;

    public static String url;

    public static String config = "{\n" +
            "  \"imageActionName\": \"uploadimage\",\n" +
            "  \"imageFieldName\": \"upfile\",\n" +
            "  \"imageMaxSize\": 2048000,\n" +
            "  \"imageAllowFiles\": [\n" +
            "    \".png\",\n" +
            "    \".jpg\",\n" +
            "    \".jpeg\",\n" +
            "    \".gif\",\n" +
            "    \".bmp\"\n" +
            "  ],\n" +
            "  \"imageCompressEnable\": true,\n" +
            "  \"imageCompressBorder\": 1600,\n" +
            "  \"imageInsertAlign\": \"none\",\n" +
            "  \"imageUrlPrefix\": \"\",\n" +
            "  \"imagePathFormat\": \"image/{yyyy}{mm}{dd}/{time}{rand:6}\",\n" +
            "  \"scrawlActionName\": \"uploadscrawl\",\n" +
            "  \"scrawlFieldName\": \"upfile\",\n" +
            "  \"scrawlPathFormat\": \"image/{yyyy}{mm}{dd}/{time}{rand:6}\",\n" +
            "  \"scrawlMaxSize\": 2048000,\n" +
            "  \"scrawlUrlPrefix\": \"\",\n" +
            "  \"scrawlInsertAlign\": \"none\",\n" +
            "  \"snapscreenActionName\": \"uploadimage\",\n" +
            "  \"snapscreenPathFormat\": \"image/{yyyy}{mm}{dd}/{time}{rand:6}\",\n" +
            "  \"snapscreenUrlPrefix\": \"\",\n" +
            "  \"snapscreenInsertAlign\": \"none\",\n" +
            "  \"catcherLocalDomain\": [\n" +
            "    \"127.0.0.1\",\n" +
            "    \"localhost\",\n" +
            "    \"img.baidu.com\"\n" +
            "  ],\n" +
            "  \"catcherActionName\": \"catchimage\",\n" +
            "  \"catcherFieldName\": \"source\",\n" +
            "  \"catcherPathFormat\": \"image/{yyyy}{mm}{dd}/{time}{rand:6}\",\n" +
            "  \"catcherUrlPrefix\": \"\",\n" +
            "  \"catcherMaxSize\": 2048000,\n" +
            "  \"catcherAllowFiles\": [\n" +
            "    \".png\",\n" +
            "    \".jpg\",\n" +
            "    \".jpeg\",\n" +
            "    \".gif\",\n" +
            "    \".bmp\"\n" +
            "  ],\n" +
            "  \"videoActionName\": \"uploadvideo\",\n" +
            "  \"videoFieldName\": \"upfile\",\n" +
            "  \"videoPathFormat\": \"video/{yyyy}{mm}{dd}/{time}{rand:6}\",\n" +
            "  \"videoUrlPrefix\": \"\",\n" +
            "  \"videoMaxSize\": 102400000,\n" +
            "  \"videoAllowFiles\": [\n" +
            "    \".flv\",\n" +
            "    \".swf\",\n" +
            "    \".mkv\",\n" +
            "    \".avi\",\n" +
            "    \".rm\",\n" +
            "    \".rmvb\",\n" +
            "    \".mpeg\",\n" +
            "    \".mpg\",\n" +
            "    \".ogg\",\n" +
            "    \".ogv\",\n" +
            "    \".mov\",\n" +
            "    \".wmv\",\n" +
            "    \".mp4\",\n" +
            "    \".webm\",\n" +
            "    \".mp3\",\n" +
            "    \".wav\",\n" +
            "    \".mid\"\n" +
            "  ],\n" +
            "  \"fileActionName\": \"uploadfile\",\n" +
            "  \"fileFieldName\": \"upfile\",\n" +
            "  \"filePathFormat\": \"file/{yyyy}{mm}{dd}/{time}{rand:6}\",\n" +
            "  \"fileUrlPrefix\": \"\",\n" +
            "  \"fileMaxSize\": 51200000,\n" +
            "  \"fileAllowFiles\": [\n" +
            "    \".png\",\n" +
            "    \".jpg\",\n" +
            "    \".jpeg\",\n" +
            "    \".gif\",\n" +
            "    \".bmp\",\n" +
            "    \".flv\",\n" +
            "    \".swf\",\n" +
            "    \".mkv\",\n" +
            "    \".avi\",\n" +
            "    \".rm\",\n" +
            "    \".rmvb\",\n" +
            "    \".mpeg\",\n" +
            "    \".mpg\",\n" +
            "    \".ogg\",\n" +
            "    \".ogv\",\n" +
            "    \".mov\",\n" +
            "    \".wmv\",\n" +
            "    \".mp4\",\n" +
            "    \".webm\",\n" +
            "    \".mp3\",\n" +
            "    \".wav\",\n" +
            "    \".mid\",\n" +
            "    \".rar\",\n" +
            "    \".zip\",\n" +
            "    \".tar\",\n" +
            "    \".gz\",\n" +
            "    \".7z\",\n" +
            "    \".bz2\",\n" +
            "    \".cab\",\n" +
            "    \".iso\",\n" +
            "    \".doc\",\n" +
            "    \".docx\",\n" +
            "    \".xls\",\n" +
            "    \".xlsx\",\n" +
            "    \".ppt\",\n" +
            "    \".pptx\",\n" +
            "    \".pdf\",\n" +
            "    \".txt\",\n" +
            "    \".md\",\n" +
            "    \".xml\"\n" +
            "  ],\n" +
            "  \"imageManagerActionName\": \"listimage\",\n" +
            "  \"imageManagerListPath\": \"/ueditor/jsp/upload/image/\",\n" +
            "  \"imageManagerListSize\": 20,\n" +
            "  \"imageManagerUrlPrefix\": \"\",\n" +
            "  \"imageManagerInsertAlign\": \"none\",\n" +
            "  \"imageManagerAllowFiles\": [\n" +
            "    \".png\",\n" +
            "    \".jpg\",\n" +
            "    \".jpeg\",\n" +
            "    \".gif\",\n" +
            "    \".bmp\"\n" +
            "  ],\n" +
            "  \"fileManagerActionName\": \"listfile\",\n" +
            "  \"fileManagerListPath\": \"file/\",\n" +
            "  \"fileManagerUrlPrefix\": \"\",\n" +
            "  \"fileManagerListSize\": 20,\n" +
            "  \"fileManagerAllowFiles\": [\n" +
            "    \".png\",\n" +
            "    \".jpg\",\n" +
            "    \".jpeg\",\n" +
            "    \".gif\",\n" +
            "    \".bmp\",\n" +
            "    \".flv\",\n" +
            "    \".swf\",\n" +
            "    \".mkv\",\n" +
            "    \".avi\",\n" +
            "    \".rm\",\n" +
            "    \".rmvb\",\n" +
            "    \".mpeg\",\n" +
            "    \".mpg\",\n" +
            "    \".ogg\",\n" +
            "    \".ogv\",\n" +
            "    \".mov\",\n" +
            "    \".wmv\",\n" +
            "    \".mp4\",\n" +
            "    \".webm\",\n" +
            "    \".mp3\",\n" +
            "    \".wav\",\n" +
            "    \".mid\",\n" +
            "    \".rar\",\n" +
            "    \".zip\",\n" +
            "    \".tar\",\n" +
            "    \".gz\",\n" +
            "    \".7z\",\n" +
            "    \".bz2\",\n" +
            "    \".cab\",\n" +
            "    \".iso\",\n" +
            "    \".doc\",\n" +
            "    \".docx\",\n" +
            "    \".xls\",\n" +
            "    \".xlsx\",\n" +
            "    \".ppt\",\n" +
            "    \".pptx\",\n" +
            "    \".pdf\",\n" +
            "    \".txt\",\n" +
            "    \".md\",\n" +
            "    \".xml\"\n" +
            "  ]\n" +
            "}";
  • 添加启动任务,加载属性配置
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Order(2)
@Component
public class Mission implements CommandLineRunner {

    @Value("${file.upload.savePath}")
    private String path;

    @Value("${file.download.url}")
    private String url;


    @Override
    public void run(String... args) throws Exception {
        UEditorProperties.path = path;
        UEditorProperties.url = url;
    }
}
  • 修改ConfigManager的initEnv方法
private void initEnv() {
        File file = new File(this.originalPath);
        if (!file.isAbsolute()) {
            file = new File(file.getAbsolutePath());
        }

        this.parentPath = file.getParent();
        String configContent = UEditorProperties.config;

        try {
            JSONObject jsonConfig = new JSONObject(configContent);
            this.jsonConfig = jsonConfig;
        } catch (Exception var4) {
            this.jsonConfig = null;
        }
    }
  • 修改UEditorController的config方法
@RequestMapping(value="/config")
    public void config(HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("application/json");
        String rootPath = request.getSession().getServletContext().getRealPath("/");
        try {
            String exec = new ActionEnter(request, rootPath).exec();
            JSONObject object = JSONObject.parseObject(exec);
            object.put("basePath",UEditorProperties.path);
            object.put("imageUrlPrefix",UEditorProperties.url);
            exec = JSON.toJSONString(object);
            PrintWriter writer = response.getWriter();
            writer.write(exec);
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

至此 ,SpringBoot和UEditor的整合完成

开始整合Security

  • 导入依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
  • 新建Security的配置
import com.megvii.cms.service.impl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启security注解
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Autowired
    private UserDetailsServiceImpl userDetailsService;


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .headers()
                .addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsHeaderWriter.XFrameOptionsMode.SAMEORIGIN))
                .and()
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/image/**", "/css/**", "/js/**", "/api/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/")
                .failureUrl("/login")
                .permitAll()
                .and()
                .rememberMe()
                .tokenValiditySeconds(1209600)
                .key("mykey")
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login")
                .permitAll();

    }

.headers().addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsHeaderWriter.XFrameOptionsMode.SAMEORIGIN))
.csrf().disable()
因为Ueditor兼容性问题,所以必须加上

  • 导入thymeleaf依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
  • 配置静态页面模板位置

spring:
    thymeleaf:
        prefix: classpath:/templates
        suffix: .html

  • 新建登录页面
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>Megvii-CMS-登录</title>
    <link href="/css/bootstrap.min.css" rel="stylesheet">
    <link href="/css/login/signin.css" rel="stylesheet">
</head>

<body class="text-center">
<form class="form-signin" action='/login' method='POST' >
    <h1 class="h3 mb-3 font-weight-normal">Megvii-CMS</h1>
    <input type="username" name="username" class="form-control" placeholder="用户名或邮箱">
    <input type="password" name="password" class="form-control" placeholder="密码">
    <button class="btn btn-lg btn-primary btn-block" type="submit">登录</button>
</form>
</body>
</html>
  • 新建Controller指向login.html
@Controller
@RequestMapping("/")
public class WebController {

    @GetMapping("/login")
    public String login(){
        return "/login";
    }
}
  • 实现userDetailsService里的loadUserByUsername()方法

  • 退出登录

<a href="/logout">退出登录</a>

至此,完成SpringBoot + Spring Security + UEditor完整整合,UEditor各项功能正常使用,Security验证正常,打包后运行正常

猜你喜欢

转载自blog.csdn.net/qq1107533660/article/details/80857160