SpringBoot-集成SpringSecurity

在 Web 开发中,安全一直是非常重要的一个方面。

安全虽然属于应用的非功能性需求,但是从应用开发的第一天就应该把安全相关的因素考虑进来,并在整个应用的开发过程中。

Spring Security官网介绍

Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.

Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它实际上是保护基于spring的应用程序的标准。

Spring Security是一个框架,侧重于为Java应用程序提供身份验证和授权。与所有Spring项目一样,Spring安全性的真正强大之处在于它可以轻松地扩展以满足定制需求。

 

Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。

对于上面提到的两种应用情景,Spring Security 框架都有很好的支持。在用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID 和 LDAP 等。在用户授权方面,Spring Security 提供了基于角色的访问控制和访问控制列表(Access Control List,ACL),可以对应用中的领域对象进行细粒度的控制。

 

应用

 

------------恢复内容开始------------

在 Web 开发中,安全一直是非常重要的一个方面。

安全虽然属于应用的非功能性需求,但是从应用开发的第一天就应该把安全相关的因素考虑进来,并在整个应用的开发过程中。

Spring Security官网介绍

Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.

Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它实际上是保护基于spring的应用程序的标准。

Spring Security是一个框架,侧重于为Java应用程序提供身份验证和授权。与所有Spring项目一样,Spring安全性的真正强大之处在于它可以轻松地扩展以满足定制需求。

 

Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。

对于上面提到的两种应用情景,Spring Security 框架都有很好的支持。在用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID 和 LDAP 等。在用户授权方面,Spring Security 提供了基于角色的访问控制和访问控制列表(Access Control List,ACL),可以对应用中的领域对象进行细粒度的控制。

 

应用

 添加依赖

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

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

        <!--thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

 

编写一些具有层级关系的简单页面,方便后面的模拟访问:

 

 

 为这些页面对应的写上控制层:

package com.hwl.securitydemo.controller;

@Controller
public class RouterController {

    @RequestMapping({"/","/index"})
    public String index(){
        return "index";
    }

    @RequestMapping("/toLogin")
    public String toLogin(){
        return "router/login";
    }

    @RequestMapping("/level1/{id}")
    public String level1( @PathVariable("id") int id ){
        return "/router/level1/"+id;
    }

    @RequestMapping("/level2/{id}")
    public String level2( @PathVariable("id") int id ){
        return "router/level2/"+id;
    }

    @RequestMapping("/level3/{id}")
    public String level3( @PathVariable("id") int id ){
        return "router/level3/"+id;
    }
}

 

关闭 thymeleaf 方便开发测试:

spring.thymeleaf.cache=false

 

此时,测试运行项目,访问,进入到了Spring Security默认的登录页面,说明Security已经生效!

实际情况我们很少会使用默认的配置,所有这里也是通过定义自己的SecurityConfig来接管默认的配置:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //请求授权规则 首页人人都能访问 功能页有权限才可访问
        http.authorizeRequests().antMatchers("/").permitAll()
                .antMatchers("/level1/**").hasRole("VIP1")
                .antMatchers("/level2/**").hasRole("VIP2")
                .antMatchers("/level3/**").hasRole("VIP3");

        //没有权限默认去登录页 需要开启登录的页面- /login
        http.formLogin();
       
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //正常情况应该从数据读取
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("VIP1")
                .and()
                .withUser("me").password(new BCryptPasswordEncoder().encode("123456")).roles("VIP2", "VIP3")
                .and()
                .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("VIP1", "VIP2", "VIP3");
    }
}

 

这个配置里,我们开放了默认页面,并设置3个VIP等级分别对应3个level组的访问权限,之后再模拟三个真实角色,分别为他们授权,例如me这个真实角色具有VIP2、VIP3这两个等级,对应的具有了level2、level3的访问权限。

注意:这里在实际项目中是用来自数据库的数据,这里为了更快更方便的测试,直接写数据模拟。

 

现在测试访问:

 

 正在进入主页,测试访问任意一个功能链接:

 

 

因为没有登录过,被security拦截送去了默认的登录页面了。

现在登录me这个真实角色,正常返回具有权限后的主页,访问me具有的level2、level3下的功能:

 

 level2、level3成功访问到,现在测试me这个角色没访问权限的level1下的菜单:

 

没有访问到,返回了Error Page,这基本就完成了登录和访问拦截了。

 

现在虽然实现了角色的权限访问控制,但是还有优化空间,就是让没有权限的项目直接不让角色看到:

导入thymeleaf-springsecurity整合包

        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
            <version>3.0.4.RELEASE</version>
        </dependency>

页面添加命名空间

xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"

 

在页面上添加角色判断:

sec:authorize="hasRole('VIP1')"

<div class="col-md-3" sec:authorize="hasRole('VIP1')" >
            <p>
                L1
            </p>
            <p>
                <a th:href="@{/level1/1}"><li class="bullhorn icon"></li>Level-1-1</a>
            </p>
            <p>
                <a th:href="@{/level1/2}"><li class="bullhorn icon"></li>Level-1-2</a>
            </p>
            <p>
                <a th:href="@{/level1/3}"><li class="bullhorn icon"></li>Level-1-3</a>
            </p>
        </div>

 

VIP2、VIP3相同。

 

注销:

页面添加对应的:

                <a class="item" th:href="@{/logout}">
                    <i class="glyphicon glyphicon-log-out"></i> 注销
                </a>

 

在SecurityConfig中 configure(HttpSecurity http) 添加

        // 处理请求方式问题
         http.csrf().disable();
        //注销
        http.logout().logoutSuccessUrl("/");    

 

因为页面这样的请求方式是get,所需要 http.csrf().disable();

此时从主页注销后,可以发现再次去点击功能的时候已经没有使用权限了,被送回了登录页面,注销能用。

 

posted @ 2021-10-06 23:47  四叶笔记  阅读(316)  评论(0编辑  收藏  举报