Spring Boot + Spring Security + Angular 配置

最简单配置

  • 弹出登录对话框
  • 自定义用户名密码
@Configurable
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity httpSecurity) {
        try {
            httpSecurity.authorizeRequests().anyRequest().authenticated()
                    .and()
                    .httpBasic();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Autowired
    public void ConfigureGlobal(AuthenticationManagerBuilder auth) {
        try {
            auth.inMemoryAuthentication().withUser("root").password("123456").roles("ADMIN");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

自定义 LoginForm

  • 自定义 form 提交地址
  • 认证结果不跳转
  • 登录对话框中,允许资源访问
@Configurable
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomAuthFailureHandler customAuthFailureHandler;

    @Autowired
    private CustomLoginSuccessHandler customLoginSuccessHandler;

    @Autowired
    private CustomLogoutSuccessHandler customLogoutSuccessHandler;

    Gson gson = new Gson();

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                    .anyRequest().authenticated()
                    .and()
                .formLogin()
                    .loginPage("/login").loginProcessingUrl("/auth")
                    .successHandler(customLoginSuccessHandler)
                    .failureHandler(customAuthFailureHandler)
                    .and()
                .logout().permitAll().logoutSuccessUrl("/logout")
                    .logoutSuccessHandler(customLogoutSuccessHandler)
        ;
        http.csrf().disable();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().regexMatchers(".*\\.js", ".*\\.css", ".*\\.ico", ".*\\.woff2");
    }

    @Autowired
    public void ConfigureGlobal(AuthenticationManagerBuilder auth) {
        try {
            auth.inMemoryAuthentication()
                    .withUser("root").password("123456").roles("ADMIN");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected class NoRedirectStrategy implements RedirectStrategy {
        @Override
        public void sendRedirect(HttpServletRequest request,
                                 HttpServletResponse response, String url) throws IOException {
            // no redirect
        }
    }

    @Component
    public class CustomLoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

        public CustomLoginSuccessHandler() {
            super();
            setRedirectStrategy(new NoRedirectStrategy());
        }

        @Override
        public void onAuthenticationSuccess(HttpServletRequest request,
                                            HttpServletResponse response,
                                            Authentication authentication)
                throws ServletException, IOException {
            super.onAuthenticationSuccess(request, response, authentication);
            Writer writer = response.getWriter();
            writer.write(gson.toJson("success"));
        }
    }

    @Component
    public class CustomAuthFailureHandler extends SimpleUrlAuthenticationFailureHandler {

        public CustomAuthFailureHandler() {
            super();
            setRedirectStrategy(new NoRedirectStrategy());
        }

        @Override
        public void onAuthenticationFailure(HttpServletRequest request,
                                            HttpServletResponse response,
                                            AuthenticationException exception)
                throws IOException, ServletException {
            String error = exception.getMessage();
            //getRedirectStrategy().sendRedirect(request, response, "/login?error=" + error);
            Writer writer = response.getWriter();
            writer.write(gson.toJson(error));
        }
    }

    @Component
    public class CustomLogoutSuccessHandler implements LogoutSuccessHandler {
        @Override
        public void onLogoutSuccess(HttpServletRequest request,
                                    HttpServletResponse response,
                                    Authentication authentication)
                throws IOException, ServletException {
            Writer writer = response.getWriter();
            writer.write(gson.toJson("success"));
        }
    }
}

Angular 提交

  • 登录
onLogin() {
    const url = '/auth';
    // let data = {username: this.username, password: this.password };
    // let data = "username=" + this.username + "&password=" + this.password;
    let params = new URLSearchParams();
    params.set('username', this.username);
    params.set('password', this.password);

    let header = {
      headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded'),
    };

    this.http.post(url, params.toString(), header).subscribe(
      data => {
        console.log(data);
        if (data != null && data == 'success') {
          this.router.navigateByUrl("/");
        } else {
          let snackBarRef = this.snackBar.open("Login failed. " + data, "CLOSE", {
            duration: 3000
          });
          snackBarRef.onAction().subscribe();
        }
      },
      err => {
        console.log("error: " + err.errorMsg);
      }
    );
  }
  • 登出
logout() {
  this.http.get('/logout').subscribe( data => {
    this.router.navigateByUrl('/login');
  });
}

vscode 编译调试 java 单文件代码

安装

  • Language Support for Java(TM) by Red Hat
  • Java Debug Extension for Visual Studio Code

设置

  • 需要先打开一个目录,以下配置文件生成于该目录的 .vscode 目录下
  • 编译设置

C-S-p Tasks: Configure Task Runner

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "taskName": "java build",
            "type": "shell",
            "command": "javac",
            "args": ["-d","${workspaceRoot}","${file}"],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": {
                "owner": "java",
                "fileLocation": ["absolute"],
                "pattern": {
                    "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error|fatal error):\\s+(.*)$",
                    "file": 1,
                    "line": 2,
                    "column": 3,
                    "severity": 4,
                    "message": 5
                }
            }
        }
    ]
}
  • 调试设置

Debug -> Start Debugging

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "java",
            "name": "Debug (Launch)",
            "request": "launch",
            "sourcePaths": [
                "$(workspaceRoot)"
            ],
            "classPaths": [
                "",            
                "$(workspaceRoot)"
            ],
            "mainClass": "${fileBasenameNoExtension}",
            "args": ""
        },
        {
            "type": "java",
            "name": "Debug (Attach)",
            "request": "attach",
            "hostName": "localhost",
            "port": 0
        }
    ]
}

快捷键

  • 编译 C-S-b
  • 调试 F5

vscode 编译调试 C++ 单文件代码

安装

  • 安装 vscode
  • 安装插件 c/c++ c/c++ snippets

设置

  • 需要先打开一个目录,以下配置文件生成于该目录的 .vscode 目录下
  • IntelliSense 设置

C-S-p c/cpp: Edit Configurations..

{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "D:/mingw540-x64/x86_64-w64-mingw32/include/c++",
                "${workspaceRoot}"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE"
            ],
            "intelliSenseMode": "msvc-x64",
            "browse": {
                "path": [
                    "D:/mingw540-x64/x86_64-w64-mingw32/include/c++",
                    "${workspaceRoot}"
                ],
                "limitSymbolsToIncludedHeaders": true,
                "databaseFilename": ""
            }
        }
    ],
    "version": 3
}
  • 编译设置

C-S-p Tasks: Configure Task Runner

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "taskName": "g++ build",
            "type": "shell",
            "command": "g++.exe",
            "args": ["-g","${file}","-o","${file}.exe", "-std=c++1y"], 
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": {
                "owner": "cpp",
                "fileLocation": ["absolute"],
                "pattern": {
                    "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error|fatal error):\\s+(.*)$",
                    "file": 1,
                    "line": 2,
                    "column": 3,
                    "severity": 4,
                    "message": 5
                }
            }
        },
        {
            "taskName": "clang++ build",
            "type": "shell",
            "command": "clang++.exe",
            "args": ["-target", "x86_64-pc-windows-gnu", "-g","${file}","-o","${file}.exe", "-std=c++1y"], 
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": {
                "owner": "cpp",
                "fileLocation": ["absolute"],
                "pattern": {
                    "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error|fatal error):\\s+(.*)$",
                    "file": 1,
                    "line": 2,
                    "column": 3,
                    "severity": 4,
                    "message": 5
                }
            }
        }
    ]
}
  • 调试设置

Debug -> Start Debugging

{
        "version": "0.2.0",
        "configurations": [
            {
                "name": "(gdb) Launch",
                "type": "cppdbg",
                "request": "launch",
                "program": "${file}.exe",
                "args": [],
                "stopAtEntry": false,
                "cwd": "${workspaceRoot}",
                "environment": [],
                "externalConsole": true,
                "MIMode": "gdb",
                "miDebuggerPath": "gdb.exe",
                "setupCommands": [
                    {
                        "description": "Enable pretty-printing for gdb",
                        "text": "-enable-pretty-printing",
                        "ignoreFailures": true
                    }
                ]
            }
        ]
    }

快捷键

  • 编译 C-S-b
  • 调试 F5

ubuntu16.04 修改 pthread 库的 PTHREAD_KEYS_MAX 宏定义

编译说明

  • pthread 是 glibc 的子库,需要编译整个 glibc。
  • 需要安装编译套件 gcc, make 等工具。

编译 glibc

  • 查看 glibc 当前版本
$ /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.23-0ubuntu9) stable release version 2.23, by Roland McGrath et al.
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 5.4.0 20160609.
Available extensions:
        crypt add-on version 2.1 by Michael Glad and others
        GNU Libidn by Simon Josefsson
        Native POSIX Threads Library by Ulrich Drepper et al
        BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.
  • 下载 glibc-2.23
apt install axel
axel -n 10 http://ftp.gnu.org/gnu/glibc/glibc-2.23.tar.bz2
tar xjf glibc-2.23.tar.bz2
  • 修改 PTHREAD_KEYS_MAX 宏大小
    • 不能改太大,改成 10240 创建线程时会崩溃
    • 仅修改相关 PC 体系下的头文件,如下是修改完的
$ cd /home/share/glibc-2.23
$ ag "define PTHREAD_KEYS_MAX"
glibc-2.23/sysdeps/unix/sysv/linux/aarch64/bits/local_lim.h
65:#define PTHREAD_KEYS_MAX     2048

glibc-2.23/sysdeps/unix/sysv/linux/bits/local_lim.h
64:#define PTHREAD_KEYS_MAX     2048

glibc-2.23/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h
64:#define PTHREAD_KEYS_MAX     1024

glibc-2.23/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h
64:#define PTHREAD_KEYS_MAX     1024

glibc-2.23/sysdeps/unix/sysv/linux/mips/bits/local_lim.h
64:#define PTHREAD_KEYS_MAX     1024

glibc-2.23/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h
64:#define PTHREAD_KEYS_MAX     1024

glibc-2.23/sysdeps/unix/sysv/linux/tile/bits/local_lim.h
64:#define PTHREAD_KEYS_MAX     1024

glibc-2.23/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h
64:#define PTHREAD_KEYS_MAX     1024

glibc-2.23/sysdeps/nacl/bits/local_lim.h
29:#define PTHREAD_KEYS_MAX        2048
  • 编译 glibc-2.23
apt install gawk
mkdir build
cd build
../configure CC=gcc --disable-sanity-checks

安装前的准备

  • 查看 pthread 所在目录
$ locate pthread.so
/lib/x86_64-linux-gnu/libpthread.so.0
/usr/lib/x86_64-linux-gnu/libpthread.so
/usr/lib/x86_64-linux-gnu/samba/vfs/aio_pthread.so
  • 查看运行库
$ cd /lib/x86_64-linux-gnu/
$ l *pthread*
-rwxr-xr-x 1 root root 136K Jun 17 04:57 libpthread-2.23.so
lrwxrwxrwx 1 root root   18 Jun 17 04:57 libpthread.so.0 -> libpthread-2.23.so
  • 查看链接库
$ cd /usr/lib/x86_64-linux-gnu
$ l *pthread*
-rw-r--r-- 1 root root 2.4M Jun 17 04:52 libpthread.a
-rw-r--r-- 1 root root 7.6K Jun 17 04:52 libpthread_nonshared.a
-rw-r--r-- 1 root root  252 Jun 17 04:52 libpthread.so
  • 查看头文件位置
$ locate local_lim.h
/usr/include/x86_64-linux-gnu/bits/local_lim.h

替换链接库

  • 备份链接库
cd /usr/lib/x86_64-linux-gnu
mv libpthread.so libpthread.so.bak
mv libpthread.a libpthread.a.bak
mv libpthread_nonshared.a libpthread_nonshared.a.bak
  • 替换链接库 编译完成后记得还原
cd /usr/lib/x86_64-linux-gnu
cp /home/share/glibc-2.23/glibc-2.23/build/nptl/libpthread.so .
cp /home/share/glibc-2.23/glibc-2.23/build/nptl/libpthread.a .
cp /home/share/glibc-2.23/glibc-2.23/build/nptl/libpthread_nonshared.a .

替换运行库

  • 备份运行库

    • 部分 shell 命令依赖 libpthread.so.0,如 cp,mv。
    cd /lib/x86_64-linux-gnu/
    cp libpthread.so.0 libpthread.so.0.bak
    
    • ln 仍然可用,可用于紧急情况下恢复。
    ln -s -f libpthread-2.23.so libpthread.so.0 
    
  • 替换运行库

    • 放到执行目录下
    export LD_LIBRARY_PATH=./
    cd /home/share/glibc-2.23/glibc-2.23/build/nptl
    cp *.so* /var/data/testprogram
    
    • 放到系统目录下 危险,尽量不要使用这种方法
    cd /lib/x86_64-linux-gnu/
    cp /home/share/glibc-2.23/glibc-2.23/build/nptl/libpthread.so libpthread.spider.so
    ln -s -f libpthread.spider.so libpthread.so.0
    
  • 修改头文件 编译完成后记得还原
vim /usr/include/x86_64-linux-gnu/bits/local_lim.h
#define PTHREAD_KEYS_MAX 10240

flex 布局

浏览器版本支持

  • chrome 21, opera 12.1, firefox 22, safari 6.1, ie 10

指定 flex 布局

  • 块元素 display: flex;
  • 行内元素 display: inline-flex;
  • webkit 内核 display: -webkit-flex display: -webkit-inline-flex
  • 影响设置 flex 而已后, float , clear , vertcal-align 都失效

窗口属性

  • flex-direction row | row-reverse | column | column-reverse
  • flex-wrap nowrap | wrap | wrap-reverse
  • flex-flow <flex-direction> || <flex-wrap>
  • justify-content flex-start | flex-end | center | space-between | space-around
  • align-items flex-start | flex-end | center | baseline | stretch
  • align-content flex-start | flex-end | center | space-between | space-around | stretch

元素属性

  • order <integer>
  • flex-grow <number> /*default 0*/
  • flex-shrink <number> /*default 0*/
  • flex-basis <number | auto /*default auto*/
  • flex none | [ <flex-grow> <flex-shrink>? || <flex-basis> ]
  • align-self auto | flex-start | flex-end | center | baseline | stretch