随机名言

SpringSecurity



最近要学太多东西了,学得太浅容易忘记,所以决定拿个实际项目练手,近期会整理笔记上传


1. Spring Security

进入Spring官网的Security可以看到下面这样一个简介:

Spring Security是一个功能强大且高度可定制的身份认证和访问控制框架,它是用于保护基于Spring的应用程序的实际标准。Spring Security是一个框架,致力于为Java应用程序提供身份认证和授权。与所有Spring项目一样,Spring Security的真正强大之处在于可以轻松扩展以满足自定义要求


特点

  • 全面可扩展的身份认证与授权
  • 防止攻击,跨站请求
  • Servlet API集成
  • 与SpringMVC可选集成

以前我们用拦截器或过滤器来做身份认证和权限等功能,类比Spring Security,其底层是一组过滤器链FilterChain,所以学好基础有助于框架的学习


通过pom.xml的依赖关系知道Spring Security是依赖于AOP的,有切面编程的成分,即不需要修改我们原有的代码


总的来说:Spring Security是提供身份认证与授权功能的框架




2. HelloWorld

Spring Security各版本更新变化挺大的,所以列出使用的版本。笔者使用SpringBoot 2.2.5.RELEASE,也就是 Spring Security 5.2.2.RELEASE


2.1 导包

导入了最基本的依赖

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2.2 启动项目

直接启动Springboot项目然后打开,就会看到有登录页面了(Spring Security自带的)表示Spring Security运行正常,当然我们什么也没有配置,到这里就是HelloWorl的过程了





3. 身份认证

这里我们新建几个页面,其中index全体人员可以访问,page1-3只有对应权限的人可以访问,admin可以访问所有的页面


3.1 新建配置类SecurityConfig

用注解配置,里面的方法会注释说明

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {  // 使用了适配器模式
    @Override
    // 参数我们使用Http,因为现在我们使用的是http
    // 下面的方式调用可以是链式调用
    // 其中方法做简要解释,其实看英文就大概知道什么意思了
    protected void configure(HttpSecurity http) throws Exception {  
        http.authorizeRequests()  // 表示http要请求授权
                .antMatchers("/").permitAll()  // 匹配地址"/",所有人都可访问
                .antMatchers("/page1**").hasRole("page1VIP")  // 访问对应地址,需要角色"page1VIP"
                .antMatchers("/page2**").hasRole("page2VIP")  // 而角色属于权限和数据库方面知识
                .antMatchers("/page3**").hasRole("page3VIP")
            	.and() // 将上面的配置合并下面的配置
            	.formLogin()  // 打开自带的登录页面
            	.and()
            	.rememberMe() // 记住我功能
        		.and()
                .logout();  // 注销
    }

    @Override
    // 为了简便而不使用数据库,直接在内存构造一些用户数据
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 新版本需要密码编码,因为用户信息写死在代码中会被反编译获取
        auth.inMemoryAuthentication()
            .passwordEncoder(new BCryptPasswordEncoder())  // 添加密码编码
                .withUser("admin")  // 添加用户名
                .password(new BCryptPasswordEncoder().encode("admin")) // 添加用户密码,加了编码
                .roles("page1VIP", "page2VIP","page3VIP")  // 给予权限
                .and()  // 将上面的配置合并下面的配置
            	.withUser("page1")
                .password(new BCryptPasswordEncoder().encode("page1"))
                .roles("page1VIP");
    }
}
  • 没有权限则会自动跳转登录页,登陆后返回刚才的页面
  • 该类需要继承WebSecurityConfigurerAdapter并重写里面的方法才能实现定制配置
  • @EnableWebSecurity表示开启配置类,内部有各种组合注解属于Springboot原理

3.2 认证授权测试

  • 主页谁都可以访问
  • 状态码403表示无权访问
  • 记住我功能是加了cookie(remember)实现
  • 注销即删除了相应的cookie




4. 自定义配置

我们不满足于Security提供的页面及其传参地址,那么就需要自定义


4.1 查看默认配置

.and().formLogin这个是提供默认登录表单的,我们点进去看原码,注意看其上的注释注释注释,这里截取部分

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/**").hasRole("USER")
    .and().formLogin()
	.usernameParameter("username") // default is username,默认的用户名接参name
    .passwordParameter("password) // default is password,默认的密码接参name
	.loginPage("authentication/login") // default is /login with an HTTP get,默认的登录页地址
	.failureUrl("authentication/login?failed") // default is /login?error,默认登录失败跳转地址
	.loginProcessingUrl("/authentication/login/process");// default is /login with an HTTP post
                       // 默认的登录处理url,即传表单的地址
}

看过一个方法的注释,我们就可以举一反三,各个函数都可通过注释来了解其有什么可定制的功能


4.2 修改默认配置

此时可以添加自定义的登录页面和注销提交地址,那么其配置可改成如下

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/").permitAll()
        .antMatchers("/page1**").hasRole("page1VIP")
        .antMatchers("/page2**").hasRole("page2VIP")
        .antMatchers("/page3**").hasRole("page3VIP")

        .and()
        .formLogin()
        .loginPage("/login.html")  // 自定义了一个登录页
        .usernameParameter("user")
        .passwordParameter("pwd")
        .loginProcessingUrl("/login")  // 表单提交的地址

        .and()
        .rememberMe().rememberMeParameter("remember") // 记住我传参名

        .and()
        .logout().logoutUrl("/logout").logoutSuccessUrl("/index.html")   // 注销提交地址和返回页面

        .and().csrf().disable(); // 防止csrf的,不然get、post都不能访问
}

主页和登录页的传参名和提交地址

<!doctype html>
<html lang="en">
<head>
    <title>主页</title>
</head>
<body>
    <a href="/login.html">登录</a>
    <a href="/logout">注销</a>
    <h1>这里是主页</h1>
    <a href="page1.html">page1</a>
    <a href="page2.html">page2</a>
    <a href="page3.html">page3</a>
</body>
</html>


<!doctype html>
<html lang="en">
<head>
    <title>登录页</title>
</head>
<body>
    <h1>自定义的登录页</h1>
    <form action="/login" method="post">
        <input type="text" name="user" placeholder="username">
        <input type="text" name="pwd" placeholder="password">
        <input type="checkbox" name="remember"> 记住我
        <input type="submit" value="提交">
    </form>
</body>
</html>

4.3 自定义测试


至此基本的身份验证和授权功能已经完成配置,算是入门了把,往后会有深入配置的笔记





5. 后期补充

http.authorizeRequests()
.antMatchers("/","/login.html").permitAll()  // 匹配地址"/","/login.html",别忘记登录页要排除
.anyRequest().authenticated()  // 表示登录后,其余地址都能访问



参考
https://docs.spring.io/spring-security/site/docs/5.2.3.RELEASE/reference/htmlsingle/![]

posted @ 2020-04-22 09:26  Howlet  阅读(239)  评论(0编辑  收藏  举报

Copyright © By Howl