侧边栏壁纸
博主头像
qingtian博主等级

喜欢是一件细水流长的事,是永不疲惫的双向奔赴~!

  • 累计撰写 85 篇文章
  • 累计创建 40 个标签
  • 累计收到 0 条评论

Spring Security

qingtian
2021-02-08 / 0 评论 / 0 点赞 / 813 阅读 / 6,909 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2021-02-08,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

Spring Security

启用Spring Security

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

配置Spring Security

/**
 * @author qingtian
 * @date 2021-02-07 10:24
 */

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {


}

储存用户信息

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

//    //基于内存的用户存储
//
//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//
//        auth.inMemoryAuthentication()
//                .withUser("buzz")
//                .password("infinity")
//                .authorities("ROLE_USER")
//                .and()
//                .withUser("woody")
//                .password("bullseye")
//                .authorities("ROLE_USER");
//    }

//    //基于jdbc的用户储存
//    @Autowired
//    private DataSource dataSource;
//
//
//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//
//        auth.jdbcAuthentication()
//                .dataSource(dataSource)
//                .usersByUsernameQuery(
//                        "select username,password,enabled from Users"+"where username=?"
//                )
//                .authoritiesByUsernameQuery(
//                        "select username, authority from UserAuthorities"+"where username=?"
//                )
//        //使用转码后的密码
//        .passwordEncoder(new BCryptPasswordEncoder());
//    }

    //以LDAP作为后端的用户储存


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

//        auth.ldapAuthentication()
//                .userSearchFilter("(uid={0})")//搜索用户
//                .groupSearchFilter("member = {0}");//搜索组
        //在默认情况下用户和组的搜索都是空的,就是表明从LDAP的根目录开始搜索
        //可以更改
        auth.ldapAuthentication()
                .userSearchBase("ou = people")//为用户查询提供了基础查询
                .userSearchFilter("(uid = {0})")
                .groupSearchBase("ou = groups")//查找组提供了基础查询,在groups下查询
                .groupSearchFilter("member = {0}")
                //设置密码比对
                .passwordCompare()
                .passwordEncoder(new BCryptPasswordEncoder())
                //设置密码属性的名称
                .passwordAttribute("passcode");
        //默认情况下Spring假设LDAP服务器监听本机的33389端口,如果LDAP服务器在另一台机器上,可以通过contextSource()方法配置地址

    }
}

保护web请求

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(userDetailsService);
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //具备ROLE_USER权限的用户才能访问"/design"和"/orders"
        //其他请求允许所有用户访问
        http.authorizeRequests()
                .antMatchers("/design","/orders")
                .hasRole("ROLE_USER")
                .antMatchers("/","/**").permitAll();
    }
}

用来定义如何保护路径的配置方法

image-20210207140459594

Spring Security对Spring表达式语言的扩展

image-20210207143631181

重写以上的表达式规则

我们只允许具备ROLE_USER权限的用户在星期二创建新taco

@Override
    protected void configure(HttpSecurity http) throws Exception {

//        http.authorizeRequests()
//                .antMatchers("/design","/orders")
//                .hasRole("ROLE_USER")
//                .antMatchers("/","/**").permitAll();

        http.authorizeRequests()
                .antMatchers("/design","/orders")
                .access("hasRole('ROLE_USER')&&"+"T(java.util.Calendar).getInstance().get("+"T(java.util.Calendar).DAY_OF_WEEK) == "+"T(java.util.Calendar).THURSDAY")
                .antMatchers("/","/**").access("permitAll()");

    }

创建自定义的登录页

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
            .antMatchers("/design","/orders")
            .hasRole("ROLE_USER")
            .antMatchers("/","/**").permitAll()
    .and()
    .formLogin()
    .loginPage("/login");
@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
            .antMatchers("/design","/orders")
            .hasRole("ROLE_USER")
            .antMatchers("/","/**").permitAll()
    .and()
    .formLogin()
     //登录
    .loginPage("/login")
    .loginProcessingUrl("/authenticate")
    .usernameParameter("user")
    .passwordParameter("pwd")
     //退出
    .defaultSuccessUrl("/design",true)
            .and()
            .logout()
            .logoutSuccessUrl("/")
    .and()
    .csrf().disable();

了解当前的用户

/**
 * @author qingtian
 * @date 2021-02-08 10:05
 */

@Controller
public class OrderControlller {

    @Autowired
    private UserRepository userRepository;

    //了解用户是谁

    /**
     * 注入Principal对象到控制器方法中
     * @param order
     * @param errors
     * @param sessionStatus
     * @param principal
     * @return
     */
    @PostMapping
    public String ProcessOrder(Order order, Errors errors, SessionStatus sessionStatus, Principal principal) {

        User user = userRepository.findByUsername(principal.getName());

        order.setUser(user);

        return "ok";

    }

    /**
     * 注入Authentication对象到控制器方法中
     * @param order
     * @param errors
     * @param sessionStatus
     * @param authentication
     * @return
     */
    @PostMapping
    public String ProcessOrder(Order order, Errors errors, SessionStatus sessionStatus, Authentication authentication) {

        User user = (User) authentication.getPrincipal();

        order.setUser(user);

        return "ok";

    }

    @PostMapping
    public String ProcessOrder(Order order, Errors errors, SessionStatus sessionStatus, @AuthenticationPrincipal User user) {

        //使用@AuthenticationPrincipal的好处是不需要类型转换
        order.setUser(user);

        return "ok";

    }

    /**
     * 还有另外一种方法能够识别当前的认证用户是谁,但是这种方法有点麻烦,他会包含大量安全性相关的代码。我们
     * 可以从安全上下文中获取一个Authentication对象
     */
    @PostMapping
    public String ProcessOrder(Order order, Errors errors, SessionStatus sessionStatus) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        User principal = (User) authentication.getPrincipal();

        order.setUser(principal);

        return "ok";

    }
0

评论区