SpringSecurity学习总结

一、spring security 简介

  • 认证:(你是谁)身份认证,使用系统的任何用户,系统对于他来讲必须要能够进行识别,这个识别的过程我们就称之为认证。在此过程中牵涉到两个表,用户表和角色表,他们能够确定用户的权限。
  • 授权(你能干什么):对于一个指定的用户,系统必须能够知道他具体有什么权限。权限表能够确定用户拥有什么权限。一个完整的系统,必须能够进行认证和鉴权,否则系统不具有安全性,系统的功能也不具有任何意义!
  • 攻击防护:(防止伪造身份)

  
 
       
       
              
              
       
       
       
              
              
                     
                     
                            
                            
                     
              
       

以上配置没有指定需要使用的登录页面,可认证的用户在文件中写死了,访问相关资源时,由框架提供默认的登陆页面,其他用户都不可用!

SpringSecurity学习总结_第1张图片

输入错误密码:

SpringSecurity学习总结_第2张图片

输入正确的密码:

SpringSecurity学习总结_第3张图片

直接访问http://localhost:88/pages/a.html:

结果是可以直接进去,因为spring-security配置了不对a.html进行拦截

SpringSecurity学习总结_第4张图片

二、自定义登录页面




    
    自定义登录页面


username:
password:

配置文件:


    
    
        
        
        
        
        
        
        
        
        
        
        
        
    

案例一:输入错误的密码

结果:输入错误的密码后他并不会显示提示信息,但是失败后还会跳转到登录页面! 

SpringSecurity学习总结_第5张图片

案例二:输入正确的密码

SpringSecurity学习总结_第6张图片

 结果:完成登录!

 三、如何使固定的账号密码变成动态的从数据库中拿到?

答案是:使用user-service-ref来得到外部引入的bean,该bean是我们开发人员自己手动实现的!

UserService.class

/**
 * @author Dragon code!
 * @create 2022-04-12 10:41
 */
public class UserService implements UserDetailsService {
    //定义一个map
    private Map map = new HashMap<>();
    //模拟从数据库中查询到的用户
    private void initDate(){
        User user1 = new User();
        user1.setUsername("admin");
        user1.setPassword("123");
        User user2 = new User();
        user2.setUsername("lay");
        user2.setPassword("456");
        map.put(user1.getUsername(),user1);
        map.put(user2.getUsername(),user2);
    }

    //通过用户名得到用户对象
    //当用户登录后进行提交会调用这个方法,该方法可以得到用户输入的用户名,注意是输入的。
    //基于用户名到表中查询用户表,然后返回当前用户的身份,包含名称和密码,用user对象进行封装,
    //如果未返回用户的身份表示该用户其实是不存在的那么必然通不过认证,此时方法应该返回null
    //如果用户存在,此时框架(下面的方法)就要进行密码的比对,判断是否正确,所以返回的对象中就必须要包含从数据库中查询出来的用户名和密码,以便框架比对
    //如果密码验证通过,此时进行鉴权!就是检查当前用户的角色和权限,所以该对象中还需要一份包含了当前用户的角色和权限的list
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("username="+username);
        initDate();
        User userInDb = map.get(username);//实际项目中此处应该调用service的查询用户的功能!而不是模拟map
        if (userInDb == null){
            return null;
        }
        String passwordInDb = "{noop}"+userInDb.getPassword();

        //此泛型还是一个接口 ,所以里面要给他的实现类对象作为集合的元素
        List list = new ArrayList<>();
        if (userInDb.getUsername().equals("admin")){
            //该对象的参数名为role,意思是当前用户的角色到底是什么
            list.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        }
        if (userInDb.getUsername().equals("lay")){
            //注意此时给的不是角色 而是add权限!由开发者自己指定是角色名还是权限名。
            //通过角色名还是通过权限名进行访问完全是由开发者决定的
            list.add(new SimpleGrantedAuthority("add"));
        }

        //由于此方法要求返回一个userdetails对象,所以必须返回security的user对象。
        UserDetails userDetails = new org.springframework.security.core.userdetails.User(userInDb.getUsername(),passwordInDb,list);

        return userDetails;
    }
}

写死方式:

动态方式:

   
        
     

        


   

案例演示:

  • 使admin用户可以访问index.jsp首页面,但是访问不了a.html
  • 是lay用户可以访问a.html页面但是访问不了首页面

service实现层代码见上方UserService.class

配置文件的修改如下:spring-security.xml

注意点:

  • 关闭对于login页面的不拦截处理!
  • 通过security:intercept-url来对不同的页面进行角色或者是权限的验证,注意access中对二者字符串的不同处理不要搞错!


    

    
    
    
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    
    
    
        
        
           
        

    

    

对于service类的解释:

重点在下面这段代码:

  • 返回对象是securitey自带的User对象,而不是我们写的!
  • 该对象包含了用户名和密码,然后还有包含如
    new SimpleGrantedAuthority("add")对象的list对象!

        该对象的实质就是当前用户的权限或者角色

  • 最后将方法的userDetails对象返回出去,至此不同情况下的拦截完成!

        //由于此方法要求返回一个userdetails对象,所以必须返回security的user对象。
        UserDetails userDetails = new org.springframework.security.core.userdetails.User(userInDb.getUsername(),passwordInDb,list);

效果如下:

一、登录admin账号

SpringSecurity学习总结_第7张图片

访问首页面成功!

SpringSecurity学习总结_第8张图片

 访问a.html失败!

SpringSecurity学习总结_第9张图片

二、登录lay账号

SpringSecurity学习总结_第10张图片

首页面拦截成功!

SpringSecurity学习总结_第11张图片

a.html成功访问!

SpringSecurity学习总结_第12张图片

四、密码加密:

  
    
        
        
            
        
    


    

    
    

更新init方法

  //注入加密工具类
    @Autowired
    private PasswordEncoder passwordEncoder;
    //模拟从数据库中查询到的用户
    private void initDate(){
        User user1 = new User();
        user1.setUsername("admin");
        user1.setPassword(passwordEncoder.encode("123"));
        User user2 = new User();
        user2.setUsername("lay");
        user2.setPassword(passwordEncoder.encode("456"));
        map.put(user1.getUsername(),user1);
        map.put(user2.getUsername(),user2);
    }

 

 

五、注解的方式实现对方法的拦截





    
    
    
    

    
    
    
    
    
        
        
        
        
        
        
        
        
        

     
        
        
        
        
        
        
        
        

        
        

        
        
    
    
    
        
        
            
        
    

    
    

    

    
    

  


控制器类:

核心是@PreAuthorize这个注解:它规定了只有带有某个权限或者是角色才可以访问此方法!否则浏览器403错误。

/**
 * @author Dragon code!
 * @create 2022-04-12 15:30
 */
@RestController
@RequestMapping("/security")
public class MyController {

    //该注解的使用还必须在配置文件中配置
    //
    //设置请求是否能访问方法
    @PreAuthorize("hasAuthority('add')")
    @RequestMapping("/add")
    public String add(){
        return "add success!";
    }

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @RequestMapping("/delete")
    public String delete(){
        return "delete success!";
    }

}

你可能感兴趣的:(springsecurity,java)