栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringSecurity

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringSecurity

准备条件

            org.springframework.boot
            spring-boot-starter-security

 

            org.thymeleaf.extras
            thymeleaf-extras-springsecurity5

@Controller
public class RouterController {
    @RequestMapping({"/", "/index"})
    public String toIndex() {
        return "index";
    }

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

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

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

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

}

1、启动项目在控制台会打印如下信息


此时在浏览器输入http://localhost:8001,会跳转到登录页面:

默认用户名为user,密码就是控制台打印的。

以上信息说明SpringSecurity生效了!正确输入上面的用户和密码即可登陆将进入首页!

2、SpringSecurity简介


点击到达SpringSecurity学习文档

3、以Aop横切的方式配置javaConfig继承WebSecurityConfigurerAdapter,使用@EnableWebSecurity开启此功能,并且重写protected void configure(HttpSecurity http) throws Exception方法

授权操作

 @Override
    protected void configure(HttpSecurity http) throws Exception {
        //授权
        //首页所有的人都可以访问,功能页只有对应有权限的人才可以访问
        //请求授权的规则
       http.authorizeRequests()
               .antMatchers("/").permitAll()
               .antMatchers("/level1/**").hasRole("vip1")
               .antMatchers("/level2/**").hasRole("vip2")
               .antMatchers("/level3/**").hasRole("vip3");
    }

登陆ip地址http://localhost:8001即可直接成功访问首页


随便点击一个链接,出现禁止访问的提示!

在配置类中的方法protected void configure(HttpSecurity http) throws Exception添加“如果没有权限访问就到登陆页面” 这个登陆页面是SpringSecurity自定义的

//没有权限默认会到登陆页面
       http.formLogin();


在配置类中添加认证操作的方法protected void configure(AuthenticationManagerBuilder auth) throws Exception

//认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //这些数据正常是从数据库中读出的
        //从内存中认证,也可以从数据库中查询相应角色的数据进行认证
        auth.inMemoryAuthentication()
                .withUser("ml").password("123456").roles("vip1","vip2")
                .and()
                .withUser("root").password("123").roles("vip1","vip2","vip3")
                .and()
                .withUser("guest").password("1").roles("vip1");

    }

登陆iphttp://localhost:8001/访问首页,点击level1下的链接,使用

登陆

出现下面的错误!

解决方法,修改上面的配置类(原因是SpringSecurity认为使用.withUser("ml").password("123456").roles("vip1","vip2")。设置密码太简单,如果使用反编译,密码是极为不方便的。所以将明文加密防止反编译)
配置类修改如下

//认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //这些数据正常是从数据库中读出的
        //从内存中认证,也可以从数据库中查询相应角色的数据进行认证
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("ml").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2")
                .and()
                .withUser("root").password(new BCryptPasswordEncoder().encode("123")).roles("vip1","vip2","vip3")
                .and()
                .withUser("guest").password(new BCryptPasswordEncoder().encode("12")).roles("vip1");
    }

重启项目,使用下面的账号、密码登陆测试!


可以看到使用ml、123456登陆可以访问vip1和vip2下的.antMatchers("/level1/**").hasRole("vip1") .antMatchers("/level2/**").hasRole("vip2")

但是使用ml、123456登陆却不可以访问 .antMatchers("/level3/**").hasRole("vip3")

4、注销及权限控制 (1)在配置类中的方法protected void configure(HttpSecurity http) throws Exception添加注销功能
//开启注销功能,跳到到首页
        http.logout();


上面的toLogin是@Controller中请求的路径(请求登陆),而logout不是我们自己写的@Controller中的请求,是根据http.logout点击进去的源码得来的,说明源码中已经给我们定义好了注销功能的路径,不用我们再自己写

即可使用该密码、账号访问对应的页面!

点击右上角的“注销”功能!

点击退出到登陆页面

当然也可以直接使用我们自己定义好的路由直接退出到首页。修改上面的视图(这个是错误的,上面是正确的的。原因在下面)

这样即使点击“注销”,但是事实上并没有注销,即使退回到首页,但是我们还可以再次点击访问但是可以不通过账号、密码就可以访问刚才的页面。所以这样的做法是不科学的!所以前面的操作才是正确的
继续正确的操作(注销后再次访问刚才已经访问过的密码必须使用账号、密码),继续修改使

//开启注销功能,跳到到首页
        http.logout().logoutSuccessUrl("/");

这样就可以做到即使注销也可以直接退出到首页,并且保证再次访问与刚才一样的页面也必须是使用账号、密码登陆才可以,保护了数据的安全!这也就是为什么不能使用上面的那种方式,直接在页面添加路由跳转到首页的原因!

(2)、权限控制(根据不同的用户显示不同的版块)

不仅需要security包还需要thymeleafSpringsecurity包进行整合!


            org.springframework.boot
            spring-boot-starter-security

 

            org.thymeleaf.extras
            thymeleaf-extras-springsecurity5

在index.html页面中添加xmlns:sec="http://www.thymeleaf.org/extras/spring-security"命名空间会出现themleaf和springSecurity的整合代码提示"


             

使用ip http://localhost:8001/登陆首页如下,只有“登陆”字样,没有“用户名和注销”

随便点击一个,使用对应拥有权限的的密码和账户登陆,我选择auth.inMemoryAuthentication() .withUser("ml").password("123456").roles("vip1","vip2"),登陆如下

点击登陆之后可以看到有对应的“用户名和注销操作”


点击“注销操作”之后可以看到没有了对应权限操作的“用户名和注销操作”

但是以上还存在的问题是在没有任何相应权限的用户登陆的时候,应该在首页什么都不显示;而在登陆之后应该显示其具有权限操作的版块


这样在没有任何相应权限的用户登陆的时候,应该在首页什么都不显示

但是使用账号、密码登陆ip http://localhost:8001/login之后可以看见显示具有相应权限的版块! .antMatchers("/").permitAll() .antMatchers("/level1/**").hasRole("vip1") .antMatchers("/level2/**").hasRole("vip2") .antMatchers("/level3/**").hasRole("vip3"); .withUser("ml").password("123456").roles("vip1","vip2") .and() .withUser("root").password("123").roles("vip1","vip2","vip3") .and() .withUser("guest").password("1").roles("vip1");

这样可以直接点击访问想要的操作!
同理使用 .withUser("root").password("123").roles("vip1","vip2","vip3")登陆可以看见所有权限的版块


至此“权限控制操作”到此结束!

5、记住我以及首页定制 (1)、记住我

在配置类中的protected void configure(HttpSecurity http) throws Exception方法中添加

//防止网站工具:get、post
        http.csrf().disable(); //关闭csrf功能,登陆失败可能存在的原因
        http.logout().logoutSuccessUrl("/");
        //开启记住我的功能 cookie,默认保存两天
        http.rememberMe();

使用 http.rememberMe();就开启了记住我功能

可以与之前的登陆页面比较一下“记住我”功能就有了!

然后关掉浏览器,再次使用iphttp://localhost:8001/访问,可以发现不用账号、密码可以直接访问之前访问过的页面,这就是记住我的功能的实现!

可以发现“记住我的功能”是通过cookie实现的,时间是两周

所以要是清除掉cookie,那么“记住我的功能”就会失效!

(2)、首页定制(登陆页面)因为之前演示的操作都是使用springSecurity中已经写好的登陆页面



要使用我们自己定义好的只需要在在配置类中的protected void configure(HttpSecurity http) throws Exception方法中修改

//没有权限默认会到登陆页面,修改springSecurity到我们自己定义好的登陆页面,这样原来springSecurity中定义好的页面就不能使用,失效了
        http.formLogin().loginPage("/toLogin");



所以使用我们自己定义好的登陆页面,没有了“记住我的功能”

但是登陆失败,可以看到路由,我们没有这个请求路径http://localhost:8001/usr/login

将login.html中的跳转路由修改如下(修改前)

login.html中的跳转路由修改修改后

再次登陆测试

成功!

当然也可以这样修改!login.html中的登陆请求依然使用springSecurity规定的请求路径“/login”,而不是使用上面我们自己定义好的“toLogin”,并且在配置类中的方法 protected void configure(HttpSecurity http) throws Exception中添加修改如下

//没有权限默认会到登陆页面,修改springSecurity到我们自己定义好的登陆页面,这样原来springSecurity中定义好的页面就不能使用,失效了
        http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login");

这样也可以访问成功!

这样也会出现各种问题:因为在我们自己定义好的login.html中登陆请求的是 和 ,而按照 http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login");虽然走的是“/toLogin”但是还是走的是springSecurity默认的路径参数规定。此时必须保证formLogin中的username、password和前端中的username、password相同,否则还是登陆不了

在配置类中做出如下修改:

//没有权限默认会到登陆页面,修改springSecurity到我们自己定义好的登陆页面,这样原来springSecurity中定义好的页面就不能使用,失效了
        http.formLogin().usernameParameter("username").passwordParameter("password").loginPage("/toLogin").loginProcessingUrl("/login");

这样即使前端中的name属性中的值和人家底层默认的不一样,我们还是可以在这里修改与前端中的一样保证不出错!
所以两种方式定义首页

第一种
//没有权限默认会到登陆页面,修改springSecurity到我们自己定义好的登陆页面,这样原来springSecurity中定义好的页面就不能使用,失效了
        http.formLogin().loginPage("/toLogin");

index.html页面跳转到登陆页面

login.html页面登陆

第二种
//没有权限默认会到登陆页面,修改springSecurity到我们自己定义好的登陆页面,这样原来springSecurity中定义好的页面就不能使用,失效了
        http.formLogin().usernameParameter("username").passwordParameter("password").loginPage("/toLogin").loginProcessingUrl("/login");



当然在定制首页中再加一个“记住我的功能”

 //开启记住我的功能 cookie
        http.rememberMe().rememberMeParameter("remember");

首页定制成功!

6、上面用到的java配置类
package com.ml.springSecurity.config;


import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

//Aop横切的方式
@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");
        //没有权限默认会到登陆页面,修改springSecurity到我们自己定义好的登陆页面,这样原来springSecurity中定义好的页面就不能使用,失效了
        http.formLogin().usernameParameter("username").passwordParameter("password").loginPage("/toLogin").loginProcessingUrl("/login");
        //开启注销功能,跳到到首页
        //防止网站工具:get、post
        http.csrf().disable(); //关闭csrf功能,登陆失败可能存在的原因
        http.logout().logoutSuccessUrl("/");
        //开启记住我的功能 cookie
        http.rememberMe().rememberMeParameter("remember");
    }

    //认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //这些数据正常是从数据库中读出的
        //从内存中认证,也可以从数据库中查询相应角色的数据进行认证
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("ml").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2")
                .and()
                .withUser("root").password(new BCryptPasswordEncoder().encode("123")).roles("vip1","vip2","vip3")
                .and()
                .withUser("guest").password(new BCryptPasswordEncoder().encode("12")).roles("vip1");
    }


}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1004312.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号