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

一文搞懂SpringSecurity,spring-security配置文件详解,史上最全

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

一文搞懂SpringSecurity,spring-security配置文件详解,史上最全

一、认证和授权概念

1.、在生产环境下我们如果不登录系统是否能对业务进行操作?
答案显然是否定的,要操作这些功能必须首先登录到系统才可以。
2、是不是所有用户,只要登录成功就都可以操作所有功能呢?
答案是否定的,并不是所有的用户都可以操作这些功能。不同的用户可能拥有不同的权限,这就需要进行授权了。

二、Spring Security简介

Spring Security是 Spring提供的安全认证服务的框架。 使用Spring Security可以帮助我们来简化认证和授权的过程。官网:https://spring.io/projects/spring-security


  org.springframework.security
  spring-security-web
  5.0.5.RELEASE


  org.springframework.security
  spring-security-config
  5.0.5.RELEASE

三、话不多说,接下来看入门案例

1、工程搭建
创建 maven 工程,打包方式为 war 包,引入依赖

 

  org.springframework.security
  spring-security-web
  5.0.5.RELEASE


  org.springframework.security
  spring-security-config
  5.0.5.RELEASE

 
 

    
      
        org.apache.tomcat.maven
        tomcat7-maven-plugin
        
          
          85
          
          /
        
      
    
  

2、配置web.xml
在web.xml中主要配置SpringMVC的DispatcherServlet和用于整合第三方框架的DelegatingFilterProxy,用于整合Spring Security,注意过滤器名称必须为springSecurityFilterChain,否则会抛出NoSuchBeanDefinitionException异常



  Archetype Created Web Application
  
    
    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy
  
  
    springSecurityFilterChain
    
public class SpringSecurityUserService implements UserDetailsService {

    //模拟数据库中的数据
    public static Map map = new HashMap<>();
    static {
        User user1 = new User();
        user1.setUsername("admin");
        user1.setPassword("admin");

        User user2 = new User();
        user2.setUsername("xiaoming");
        user2.setPassword("1234");

        map.put(user1.getUsername(),user1);
        map.put(user2.getUsername(),user2);
    }


    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println(username);
        User user = map.get(username);
        if (user == null){
            //用户不存在
            return null;
        }else {
            //将用户信息返回给 SpringSecurity 框架
            //框架自动进行密码比对(页面提交的密码与数据库中查询的密码进行比对)
            List list = new ArrayList<>();
            //为当前登录用户授权,后期需要改为从数据库查询当前用户对应的权限
            list.add(new SimpleGrantedAuthority("permission_A"));//授权
            list.add(new SimpleGrantedAuthority("permission_B"));//授权

            if (username.equals("admin")){
                list.add(new SimpleGrantedAuthority("ROLE_ADMIN"));//授予角色
            }
            org.springframework.security.core.userdetails.User securityUser = new org.springframework.security.core.userdetails.User(username,"{noop}"+user.getPassword(),list);
            return securityUser;
        }
    }
}

步骤2:修改 spring-security.xml 配置文件,即删除原来配置的写死用户信息


  
  
  



分析:本次我们提供了 SpringSecurityUserService 实现类,并且按照框架的要求实现了UserDetailsService接口。在spring配置文件中注册 SpringSecurityUserService ,指定其作为认证过程中根据用户名查询用户信息的处理类。当我们进行登录操作时,spring security框架会调用SpringSecurityUserService 的loadUserByUsername方法查询用户信息,并根据此方法中提供的密码和用户页面输入的密码进行比对来实现认证操作。

六、对密码进行加密

分析:前面我们使用的密码都是明文的,这是非常不安全的。一般情况下用户的密码需要进行加密后再保存到数据库中。常见的密码加密方式有:
3DES、AES、DES:使用对称加密算法,可以通过解密来还原出原始密码
MD5、SHA1:使用单向HASH算法,无法通过计算还原出原始密码,但是可以建立彩虹表进行查表破解
bcrypt:将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题,加密后的格式一般为:

$2a$10$/bTVvqqlH9UiE0ZJZ7N2Me3RIgUCdgMheyTgV0B4cMCSokPa.6oCa

加密后字符串的长度为固定的60位。其中:$是分割符,无意义;2a是bcrypt加密版本号;10是cost的值;而后的前22位是salt值;再然后的字符串就是密码的密文了。

实现步骤:
第一步:修改 spring-security.xml 配置文件,在 spring-security.xml 文件中指定密码加密对象





  
  
    
    
  



第二步:修改 SpringSecurityUserService 实现类,添加 BCryptPasswordEncoder ,

	package com.alibaba.service;

import com.alibaba.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class SpringSecurityUserService2 implements UserDetailsService {

    
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    //模拟数据库中的用户数据
    public  Map map = new HashMap<>();

    public void initUserData(){
        User user1 = new User();
        user1.setUsername("admin");
        user1.setPassword(passwordEncoder.encode("admin"));//使用bcrypt提供的方法对密码进行加密

        User user2 = new User();
        user2.setUsername("xiaoming");
        user2.setPassword(passwordEncoder.encode("1234"));

        map.put(user1.getUsername(),user1);
        map.put(user2.getUsername(),user2);
    }

    
    //根据用户名查询用户信息
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        initUserData();

        System.out.println("用户输入的用户名为:" + username);
        //根据用户名查询数据库获得用户信息(包含数据库中存储的密码信息)
        User user = map.get(username);//模拟查询根据用户名查询数据库
        if(user == null){
            //用户名不存在
            return null;
        }else{
            //将用户信息返回给框架
            //框架会进行密码比对(页面提交的密码和数据库中查询的密码进行比对)
            List list = new ArrayList<>();
            //为当前登录用户授权,后期需要改为从数据库查询当前用户对应的权限
            list.add(new SimpleGrantedAuthority("permission_A"));//授权
            list.add(new SimpleGrantedAuthority("permission_B"));

            if(username.equals("admin")){
                list.add(new SimpleGrantedAuthority("ROLE_ADMIN"));//授予角色
                list.add(new SimpleGrantedAuthority("add"));//授权
            }
            org.springframework.security.core.userdetails.User securityUser = new org.springframework.security.core.userdetails.User(username,user.getPassword(),list);
            return securityUser;
        }
    }
}

注意看此时 password 的值

六、配置多种校验规则











7、注解方式权限控制(重点)
Spring Security除了可以在配置文件中配置权限校验规则,还可以使用注解方式控制类中方法的调用。例如Controller中的某个方法要求必须具有某个权限才可以访问,此时就可以使用Spring Security框架提供的注解方式进行控制。
实现步骤:
第一步:在spring-security.xml文件中配置组件扫描,用于扫描Controller

 



第二步:在spring-security.xml文件中开启权限注解支持


第三步:创建Controller类并在Controller的方法上加入注解进行权限控制

package com.alibaba.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloController {

    @RequestMapping("/add")
    @PreAuthorize("hasAuthority('add')")//调用此方法要求当前用户必须具有add权限
    public String add(){
        System.out.println("add...");
        return "success";
    }

    @RequestMapping("/delete")
    @PreAuthorize("hasRole('ROLE_ADMIN')")//调用此方法要求当前用户必须具有ROLE_ADMIN角色
    public String delete(){
        System.out.println("delete...");
        return "success";
    }

}

第四步:验证
在浏览器输入 localhost:85 登录 username = xiaoming(不是admin角色,前面代码只赋予 admin 用户权限)这个用户,访问 localhost:85/hello/add.do 访问不了,重新返回 login.html 页面,登录 username = admin(具有权限),访问 localhost:85/hello/add.do,可以访问

七、退出登录

用户完成登录后Spring Security框架会记录当前用户认证状态为已认证状态,即表示用户登录成功了。那用户如何退出登录呢?我们可以在spring-security.xml文件中进行如下配置:

    

通过上面的配置可以发现,如果用户要退出登录,只需要请求/logout.do这个URL地址就可以,同时会将当前session失效,最后页面会跳转到login.html页面。

建议

建议收藏,谢谢

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

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

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