SpringSecurity--密码加密、方法安全

密码加密

Spring Security提供了多种密码加密方案,官方推荐使用BCryptPasswordEncoder,BCryptPasswordEncoder使用BCrypt强哈希函数,开发者在使用时可以选择提供strength和SecureRandom实例。strength越大,密钥的迭代次数越多,密钥迭代次数为2^strength。strength取值在4~31之间,默认为10.

在Spring boot中配置密码加密非常容易,只需要修改上文配置的PasswordEnoder这个Bean的实现即可:

	@Bean
    PasswordEncoder passwordEncoder(){
    	//参数10就是strength,即密钥的迭代次数(默认为10)
        return new BCryptPasswordEncoder(10);
    }

同时,配置内存用户的密码也不再是123了,代码如下:

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqi1Xzbz50dceRsga.WYiq")
                .roles("ADMIN", "USER")
                .and()
                .withUser("sang")
                .password("$2a$10$eUHbAOMq4bpxTvOVz33LIehLe3fu6NwqC9tdOcxJXEHyz4simqXTC")
                .roles("USER");
    }

这里的密码就是使用BCryptPasswordEncoder加密后的密码,因为BCryptPasswordEncoder每次加密的结果都不一样,所以几乎匹配不上,上述代码只是说明原理而已。

一般情况下,用户信息是存储在数据库中的,因此需要在用户注册时对密码进行加密处理,代码如下:

@Service
public class RegService {
    
    public int reg(String username, String password){
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(10);
        String encodePassword = encoder.encode(password);
        return saveToDb(username, password);
    }
}

用户将密码从前端传来之后,通过调用BCryptPasswordEncoder实例中的encode方法对密码进行加密处理,加密完成后将密文存入数据库。

方法安全

除了基于URL的认证与授权,开发者也可以通过注解来灵活地配置方法安全,要使用相关注解,首先要通过@EnableGlobalMethodSecurity注解开启基于注解的安全配置:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig {
}
  • prePostEnabled=true会解锁@PreAuthorize和@PostAuthorize两个注解

    • @PreAuthorize注解会在方法执行前进行验证
    • @PostAuthorize注解在方法执行后进行验证
  • securedEnabled=true会解锁@Secured注解

创建一个MethodService进行测试:

@Service
public class MethodService {

    //表示该访问该方法需要ADMIN角色,注意:需要加前缀ROLE_
    @Secured("ROLE_ADMIN")
    public String admin(){
        return "hello admin";
    }

    //表示访问该方法需要ADMIN和DBA角色
    @PreAuthorize("hasRole('ADMIN') and hasRole('DBA')")
    public String adminAndDba(){
        return "hello admin and dba";
    }

    //表示访问该方法需要ADMIN、DBA或者USER角色
    @PreAuthorize("hasAnyRole('ADMIN', 'DBA', 'USER')")
    public String adminOrDbaOrUser(){
        return "hello admin or dba or user";
    }
}

Controller:

@RestController
public class HelloController {

    @Autowired
    MethodService methodService;

    @GetMapping("/admin")
    public String admin(){
        return methodService.admin();
    }

    @GetMapping("/adminAndDba")
    public String adminAndDba(){
        return methodService.adminAndDba();
    }

    @GetMapping("/adminOrDbaOrUser")
    public String adminOrDbaOrUser(){
        return methodService.adminOrDbaOrUser();
    }
}

配置角色:

@Configuration
public class MyWebSecurityConfig6 extends WebSecurityConfigurerAdapter {
    @Bean
    PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("root").password("123").roles("ADMIN", "DBA")
                .and()
                .withUser("admin").password("123").roles("ADMIN", "USER")
                .and()
                .withUser("sang").password("123").roles("USER");
    }
}

测试:

  • root用户: 可以访问全部三个路径:
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • admin用户: 可以访问"/admin"、"/adminOrDbaOrUser"
    在这里插入图片描述
    在这里插入图片描述

  • sang用户: 只能访问"/adminOrDbaOrUser"路径:
    在这里插入图片描述

发布了716 篇原创文章 · 获赞 2079 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/cold___play/article/details/104217984