Spring Security 的简单学习和案例

Springboot——Spring Security 的简单学习和案例(狂神说学习案例)

狂神学习视频地址:https://www.bilibili.com/video/BV1PE411i7CV?p=35

Spring Security是 一种基于 Spring AOP 和 Servlet 过滤器的安全框架。它提供全面的安全性解决方案,同时在 Web 请求级和方法调用级处理身份确认和授权

一、SpringSceurity工作流程

网上找一张图,觉得画的挺好的,比较容易理解。不然换的是源码流程图很难去理解。

img

记住下面几个类

  • AuthenticationManagerBuilder 自定义认证策略
  • WebSecurityConfigurerAdapter 自定义Security 策略
  • @EnableWebSecurity 开启WebSecurity模式

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

认证:Authentication

授权:authorization

二、项目测试

导入依赖
<!--thymeleaf -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.26</version>
    <scope>compile</scope>
</dependency>
<!--thymeleaf和springsecurity5的整合  -->
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
    <version>3.0.4.RELEASE</version>
</dependency>
<!-- 日志,引入log4j2依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- 引入springsecurity依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <!-- 日志依赖冲突 -->
    <exclusions>
        <exclusion>
            <artifactId>spring-boot-starter-logging</artifactId>
            <groupId>org.springframework.boot</groupId>
        </exclusion>
    </exclusions>
</dependency>
日志文件log4j2-spring.xml的配置

点击这里

SecurityConfig文件配置
@Configuration
@EnableWebSecurity // 开启WebSecurity模式
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 请求来到登录页
        // /login?error 重定向到这里表示登录失败 tologin 映射到login
        http.formLogin().loginPage("/tologin").loginProcessingUrl("/login")
                .usernameParameter("user") // default is username 修改默认登陆接受参数 如果表单是user 这里参数就填user
                .passwordParameter("pwd"); // default is password 修改默认登陆接受参数 如果表单是pwd 这里参数就填pwd
        //开启自动配置的注销的功能
        //注销请求 默认请求是post 地址是这个 /logout 要修改地址的话就用logoutUrl()来修改地址  invalidateHttpSession(true)这个是初始化Session
        http.logout().logoutSuccessUrl("/").deleteCookies().logoutUrl("/signout").invalidateHttpSession(true);

        //防止网站攻击,get请求不安全,因为页面里面是get请求,而注销是需要post请求所以要关闭这个,所以注销失败的原因就在这
        http.csrf().disable();
        //开启记住我的功能,默认保存14天
        http.rememberMe()
                .rememberMeParameter("remember");//自定义前端rememberMe参数 默认是remember-me
    }

    //认证,将user赋予对应的角色
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //在内存中定义,也可以在jdbc中去拿....
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("lenyuqin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2", "vip3")
                .and()
                .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1", "vip2", "vip3")
                .and()
                .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1", "vip2");


        //数据库查询
        //auth.jdbcAuthentication()
        //        .dataSource(dataSource)
        //        .withDefaultSchema()
        //        .withUser("user").password("password").roles("USER").and()
        //        .withUser("admin").password("password").roles("USER", "ADMIN");
    }
}
路径跳转
@Slf4j
@Controller
public class RouterController {

    @GetMapping({"/", "/index"})
    public String index() {
        log.info("这是登陆页面 日志测试");
        return "index";
    }

    @GetMapping("/toLogin")
    public String toLogin() {
        return "views/login";
    }

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

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

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

}

Spring Security整合thymeleaf的模板

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
判断用户是否已经登陆认证,引号内的参数必须是isAuthenticated()。
sec:authorize="isAuthenticated()"

获得当前用户的用户名,引号内的参数必须是name。
sec:authentication=“name”

判断当前用户是否拥有指定的权限。引号内的参数为权限的名称。
sec:authorize=“hasRole(‘role’)”

获得当前用户的全部角色,引号内的参数必须是principal.authorities。
sec:authentication="principal.authorities"


使用sec:authorize="isAuthenticated()" 判断是否登录 登录之后显示的页面内容
<div sec:authorize="isAuthenticated()">
    <h2><span sec:authentication="name"></span>,您好 您的身份是
        <span sec:authentication="principal.authorities"></span>
    </h2>
</div>


使用sec:authorize="hasRole('VIP1')"控制
<div sec:authorize="hasRole('VIP1')">
    <h3>我的VIP角色</h3>
    <ul>
        <li><a th:href="@{/level1/1}">免费阅读</a></li>
        <li><a th:href="@{/level1/2}">购买8折</a></li>
    </ul>
</div>
</body>
</html>

至于前端页面可以去我github网站上下载,下面是进行测试

目前定义了3个角色lenyuqin,root,guest,分别拥有不同的权限,按照定义,不同的角色是可以访问不同的页面的,下面进行登陆验证(密码均为123456)

首页

image-20201028165837054

登陆页面

image-20201028170014277

root用户

image-20201028170040801

guest用户

image-20201028170155240

lenyuqin用户

image-20201028170339996

配置可以从源码上面的例子参考

   /**
     * 通过 {@link #authenticationManager()} 方法的默认实现尝试获取一个 {@link AuthenticationManager}.
     * 如果被复写, 应该使用{@link AuthenticationManagerBuilder} 来指定 {@link AuthenticationManager}.
     *
     * 例如, 可以使用以下配置在内存中进行注册公开内存的身份验证{@link UserDetailsService}:
     *
     * // 在内存中添加 user 和 admin 用户
     * @Override
     * protected void configure(AuthenticationManagerBuilder auth) {
     *     auth
     *       .inMemoryAuthentication().withUser("user").password("password").roles("USER").and()
     *         .withUser("admin").password("password").roles("USER", "ADMIN");
     * }
     *
     * // 将 UserDetailsService 显示为 Bean
     * @Bean
     * @Override
     * public UserDetailsService userDetailsServiceBean() throws Exception {
     *     return super.userDetailsServiceBean();
     * }
     *
     */
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        this.disableLocalConfigureAuthenticationBldr = true;
    }
 
 
    /**
     * 复写这个方法来配置 {@link HttpSecurity}. 
     * 通常,子类不能通过调用 super 来调用此方法,因为它可能会覆盖其配置。 默认配置为:
     * 
     * http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
     *
     */
    protected void configure(HttpSecurity http) throws Exception {
        logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");
​
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .formLogin().and()
            .httpBasic();
    }

github地址:https://github.com/lenyuqin/study-springboot/tree/master/spring-security

每天进步一点点,一个努力改变自己的小白

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值