zoukankan      html  css  js  c++  java
  • security

    ssss

    一.SpringSecurity概述

    1.什么是安全

    • 在web开发中,安全第一位!之前使用的过滤器和拦截器都是为了安全的目的。

    • 不是网站的功能性需求

    • 应该在网站设计之初就考虑安全,防止隐私泄露等安全问题

    • shiro、SpringSecurity框架:除了类不同和名字不一样,基本很像都是认证和授权等。

    2.Spring Security简介

    (1)SpringSecurity是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,对于安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理。

    (2)几个重要的类

    • WebSecurityConfigurerAdapter:自定义Security策略

    • AuthenticationManagerBuilder:自定义认证策略

    • @EnableWebSecurity:开启WebSecurity模式,@Enablexxxx开启某个功能

    (3)SpringSecurity的两个主要目标是“认证”和“授权”(访问控制)

    • “认证”(Authentication)

    • “授权”(Authorization)

    • 这个概念是通用的,而不是只在SpringSecurity中存在

    (4)springsecurity网址

    • 官网:https://spring.io/projects/spring-security

    • JavaConfig配置:https://docs.spring.io/spring-security/site/docs/5.2.2.RELEASE/reference/htmlsingle/#jc

    3.使用Spring Security

    (0)步骤:项目根据用户权限显示不同权限用户所能见的内容

    • 新建springboot项目,添加springmvc,springsecurity,thymeleaf等模块(略)

    • pom.xml导入依赖thymeleaf-extras-springsecurity5

    • 导入静态资源和页面并配置管理thymeleaf缓存

    • 编写路由控制器

    • 以Java Config方式编写配置文件

    • 前端页面使用thymeleaf-extras-springsecurity5

    • 测试

    (1)pom.xml导入依赖thymeleaf-extras-springsecurity5

    • thymeleaf-extras-springsecurity5是thymeleaf和springsecurity所整合的包

    复制代码
    <!--thymeleaf和springsecurity整合包-->
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        <version>3.0.4.RELEASE</version>
    </dependency>
    复制代码

    (2)导入静态资源和页面并配置管理thymeleaf缓存

    spring.thymeleaf.cache=false

    (3)编写路由控制器

    • 建立controller文件夹并在其下建立RouterController.java

    复制代码
     1 import org.springframework.stereotype.Controller;
     2 import org.springframework.web.bind.annotation.PathVariable;
     3 import org.springframework.web.bind.annotation.RequestMapping;
     4 
     5 @Controller
     6 public class RouterController {
     7 
     8     @RequestMapping({"/", "/index"})
     9     public String index() {
    10         return "index";
    11     }
    12 
    13     @RequestMapping("/toLogin")
    14     public String toLogin() {
    15         return "views/login";
    16     }
    17 
    18     @RequestMapping("/level1/{id}")
    19     public String level1(@PathVariable("id") int id) {
    20         return "views/level1/" + id;
    21     }
    22 
    23     @RequestMapping("/level2/{id}")
    24     public String level2(@PathVariable("id") int id) {
    25         return "views/level2/" + id;
    26     }
    27 
    28     @RequestMapping("/level3/{id}")
    29     public String level3(@PathVariable("id") int id) {
    30         return "views/level3/" + id;
    31     }
    32 }
    复制代码

    (4)以Java Config方式编写配置文件

    • 在controller同一级添加config文件夹并在其下建立SecurityConfig.java文件

    • 重写授权方法:

      • 此处设置了四个授权:首页所有人可访问,level1目录下的页面等级vip1可访问,level2目录下的页面等级vip2可访问,level3目录下的页面等级vip3可访问

      • 如果没有权限访问默认跳转到springsecurity的登陆页面

      • 定义登出页面为首页

      • 关闭跨站脚本攻击

    • 重写认证方法

      • 设置了三个用户以及这三个用户的权限

    复制代码
     1 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
     2 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
     3 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
     4 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
     5 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
     6 
     7 //AOP
     8 @EnableWebSecurity
     9 public class SecurityConfig extends WebSecurityConfigurerAdapter {
    10 
    11     // 授权
    12     @Override
    13     protected void configure(HttpSecurity http) throws Exception {
    14 
    15 
    16         //首页所有人可以访问,功能页只有对应有权限的人才可以访问
    17         //请求授权的规则,链式编程
    18         http.authorizeRequests()
    19                 .antMatchers("/").permitAll()
    20                 .antMatchers("/level1/**").hasRole("vip1")
    21                 .antMatchers("/level2/**").hasRole("vip2")
    22                 .antMatchers("/level3/**").hasRole("vip3");
    23 
    24         // 没有权限默认会到登录页面,需要开启登录的页面login
    25         http.formLogin();
    26 
    27         // 注销,开启注销功能,注销后会跳转到/logout
    28         // 可以清空Cookie和Session
    29         //http.logout().deleteCookies("remove").invalidateHttpSession(true);
    30         http.logout().logoutSuccessUrl("/");
    31 
    32         // 防止跨站脚本攻击关闭
    33         http.csrf().disable();
    34     }
    35 
    36     // 认证,在Spring Security 5.0+中需要对密码加密passwordEncoder
    37     @Override
    38     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    39 
    40         // 这些数据正常从数据库中读,此处使用inMemoryAuthentication从内存中读
    41         auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
    42                 .withUser("wzh").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
    43                 .and()
    44                 .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
    45                 .and()
    46                 .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
    47     }
    48 }
    复制代码

    (5)前端页面使用thymeleaf-extras-springsecurity5

    • 定义命名空间: xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4" 

    • 判断是否登录: sec:authorize="!isAuthenticated()" 

    • 获得登录用户名: sec:authentication="name" 

    • 获得登录用户权限: sec:authentication="principal.authorities" 

    • 判断是否有xxx权限: sec:authorize="hasRole('vip1')" 

    复制代码
    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
        <title>首页</title>
        <!--semantic-ui-->
        <link href="https://cdn.bootcss.com/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet">
        <link th:href="@{/qinjiang/css/qinstyle.css}" rel="stylesheet">
    </head>
    <body>
    
    <!--主容器-->
    <div class="ui container">
    
        <div class="ui segment" id="index-header-nav" th:fragment="nav-menu">
            <div class="ui secondary menu">
                <a class="item"  th:href="@{/index}">首页</a>
    
                <!--登录注销-->
                <div class="right menu">
    
    
                    <!--未登录显示登录按钮-->
                    <div sec:authorize="!isAuthenticated()">
                        <a class="item" th:href="@{/toLogin}">
                            <i class="address card icon"></i> 登录
                        </a>
                    </div>
    
                    <!--已登录显示用户名-->
                    <div sec:authorize="isAuthenticated()">
                        <a class="item">
                            用户名:<span sec:authentication="name"></span>&nbsp;&nbsp;
                            角色:<span sec:authentication="principal.authorities"></span>&nbsp;&nbsp;
                        </a>
    
    
                    </div>
    
                    <!--已登录显示注销按钮-->
                    <div sec:authorize="isAuthenticated()">
                        <a class="item" th:href="@{/logout}">
                            <i class="sign-out icon"></i> 注销
                        </a>
                    </div>
    
                    <!--已登录
                    <a th:href="@{/usr/toUserCenter}">
                        <i class="address card icon"></i> admin
                    </a>
                    -->
                </div>
            </div>
        </div>
    
        <div class="ui segment" style="text-align: center">
            <h3>Spring Security Study by 秦疆</h3>
        </div>
    
        <div>
            <br>
            <div class="ui three column stackable grid">
                <div class="column" sec:authorize="hasRole('vip1')">
                    <div class="ui raised segment">
                        <div class="ui">
                            <div class="content">
                                <h5 class="content">Level 1</h5>
                                <hr>
                                <div><a th:href="@{/level1/1}"><i class="bullhorn icon"></i> Level-1-1</a></div>
                                <div><a th:href="@{/level1/2}"><i class="bullhorn icon"></i> Level-1-2</a></div>
                                <div><a th:href="@{/level1/3}"><i class="bullhorn icon"></i> Level-1-3</a></div>
                            </div>
                        </div>
                    </div>
                </div>
    
                <div class="column" sec:authorize="hasRole('vip2')">
                    <div class="ui raised segment">
                        <div class="ui">
                            <div class="content">
                                <h5 class="content">Level 2</h5>
                                <hr>
                                <div><a th:href="@{/level2/1}"><i class="bullhorn icon"></i> Level-2-1</a></div>
                                <div><a th:href="@{/level2/2}"><i class="bullhorn icon"></i> Level-2-2</a></div>
                                <div><a th:href="@{/level2/3}"><i class="bullhorn icon"></i> Level-2-3</a></div>
                            </div>
                        </div>
                    </div>
                </div>
    
                <div class="column" sec:authorize="hasRole('vip3')">
                    <div class="ui raised segment">
                        <div class="ui">
                            <div class="content">
                                <h5 class="content">Level 3</h5>
                                <hr>
                                <div><a th:href="@{/level3/1}"><i class="bullhorn icon"></i> Level-3-1</a></div>
                                <div><a th:href="@{/level3/2}"><i class="bullhorn icon"></i> Level-3-2</a></div>
                                <div><a th:href="@{/level3/3}"><i class="bullhorn icon"></i> Level-3-3</a></div>
                            </div>
                        </div>
                    </div>
                </div>
    
            </div>
        </div>
        
    </div>
    
    
    <script th:src="@{/qinjiang/js/jquery-3.1.1.min.js}"></script>
    <script th:src="@{/qinjiang/js/semantic.min.js}"></script>
    
    </body>
    </html>
    复制代码

    (6)测试

    • guest用户

    • wzh用户

    • root用户

    4.登录定制和记住我功能

    (1)步骤:

    • 修改SecurityConfig.java文件

    • 修改login.html

    • 测试

    (2)修改SecurityConfig.java文件

    • 登录页面为控制器的/toLogin方法跳转的页面,Security处理的登录请求为/login,用户名从user参数中拿到,密码从pwd参数中拿到,记住我从remember参数中拿到

    1 http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login").usernameParameter("user").passwordParameter("pwd");
    2 http.rememberMe().rememberMeParameter("remember");
    • 完整代码

    复制代码
     1 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
     2 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
     3 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
     4 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
     5 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
     6 
     7 //AOP
     8 @EnableWebSecurity
     9 public class SecurityConfig extends WebSecurityConfigurerAdapter {
    10 
    11     // 授权
    12     @Override
    13     protected void configure(HttpSecurity http) throws Exception {
    14 
    15 
    16         //首页所有人可以访问,功能页只有对应有权限的人才可以访问
    17         //请求授权的规则,链式编程
    18         http.authorizeRequests()
    19                 .antMatchers("/").permitAll()
    20                 .antMatchers("/level1/**").hasRole("vip1")
    21                 .antMatchers("/level2/**").hasRole("vip2")
    22                 .antMatchers("/level3/**").hasRole("vip3");
    23 
    24         // 1.没有授权会自动跳转到Spring Security自带的登录页面 http://localhost:8080/login
    25         // 2.定制登录页:配置loginPage("/toLogin") 会调用控制器方法跳转到http://localhost:8080/toLogin
    26         //   表单点击提交后跳转到 http://localhost:8080/login(因为要认证用户,使用Spring Security),表单的action动作为th:action="@{/login}"
    27         //   其对应 http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login")
    28         // 3.配置表单提交来的用户名为user,密码为pwd
    29         //   <input type="text" placeholder="Username" name="user">
    30         //   <input type="password" name="pwd">
    31         http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login")
    32                 .usernameParameter("user").passwordParameter("pwd");
    33 
    34         // 注销,开启注销功能,注销后会跳转到/logout
    35         // 可以清空Cookie和Session
    36         //http.logout().deleteCookies("remove").invalidateHttpSession(true);
    37         http.logout().logoutSuccessUrl("/");
    38 
    39         // 防止跨站脚本攻击关闭
    40         http.csrf().disable();
    41 
    42         // 开启记住我功能,默认Cookie为14天过期,自定义接收前端参数
    43         // <input type="checkbox" name="remember">记住我
    44         http.rememberMe().rememberMeParameter("remember");
    45     }
    46 
    47     // 认证,在Spring Security 5.0+中需要对密码加密passwordEncoder
    48     @Override
    49     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    50 
    51         // 这些数据正常从数据库中读,此处使用inMemoryAuthentication从内存中读
    52         auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
    53                 .withUser("wzh").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
    54                 .and()
    55                 .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
    56                 .and()
    57                 .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
    58     }
    59 }
    复制代码

    (3)修改login.html

    • 提交/login

    • 参数user,pwd,remember

    复制代码
     1 <form th:action="@{/login}" method="post">
     2     <div class="field">
     3         <label>Username</label>
     4         <div class="ui left icon input">
     5             <input type="text" placeholder="Username" name="user">
     6             <i class="user icon"></i>
     7         </div>
     8     </div>
     9     <div class="field">
    10         <label>Password</label>
    11         <div class="ui left icon input">
    12             <input type="password" name="pwd">
    13             <i class="lock icon"></i>
    14         </div>
    15     </div>
    16     <div class="field">
    17         <input type="checkbox" name="remember">记住我
    18     </div>
    19     <input type="submit" class="ui blue submit button"/>
    20 </form>
    复制代码

    (4)测试成功

     
  • 相关阅读:
    Hadoop错误之namenode宕机的数据恢复
    Hadoop双namenode配置搭建(HA)
    Hadoop2之NameNode HA详解
    基于zookeeper的高可用Hadoop HA集群安装
    Spring Boot集成JPA的Column注解命名字段无效的问题
    Spring Boot使用Druid连接池基本配置
    Java设计模式六大原则之场景应用分析
    下半部和推后运行的工作
    SecureCRT连接linux,vim颜色显示问题
    Objective-C MacOS以管理员权限执行程序
  • 原文地址:https://www.cnblogs.com/yu0824/p/13796959.html
Copyright © 2011-2022 走看看