美文网首页
SpringSecurity4入门篇

SpringSecurity4入门篇

作者: 咻咻咻i | 来源:发表于2019-03-05 23:10 被阅读0次

    一、jar包依赖

    <!--对应的版本-->
    <spring.version>4.3.22.RELEASE</spring.version>
    <security.version>4.2.11.RELEASE</security.version>
    
    <!--spring security-->
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-web</artifactId>
      <version>${security.version}</version>
    </dependency>
    
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
      <version>${security.version}</version>
    </dependency>
    

    二、基本配置

    • 通过使用@EnableWebSecurity注解开启配置支持
    • 继承WebSecurityConfigurerAdapter类,进行各种配置

    1、用户储存认证配置

    在spring security中提供四种认证方式

    • 基于内存的用户存储

    该种方式适合单一用户,个人项目使用,具体操作如下

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
        auth.inMemoryAuthentication()
                .withUser("lkl").password("lkl").roles("ADMIN")
                .and()
                .withUser("admin").password("admin").authorities("ROLE_ADMIN");
    }
    
    • 数据库表用户存储认证

    该方式在一定程度上使用数据库,较上一方式用户可以动态更新

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(datasource)
                // 根据用户名查询用户语句
                .usersByUsernameQuery("select account,password from user where account=?") 
                // 根据用户名查询用户认证权限语句
                .authoritiesByUsernameQuery("select account,role,true from user where account=?");
    }
    
    • 配置自定义的用户存储认证

    该方式通过向认证器提供一个认证service实现,认证service需实现UserDetailsService接口,该方法最为灵活,推荐使用

    // 实现接口,提供认证service
    @Service
    public class SecurityService implements UserDetailsService {
    
        @Override
        public UserDetails loadUserByUsername(String username)
                throws UsernameNotFoundException {
    
            List<GrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority("ADMIN"));
    
            return new User("admin", "admin", authorities);
        }
    }
    
    // 仅需一句话即可完成配置
    @Autowired
    private SecurityService securityService;
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(securityService);
    }
    
    • 基于LDAP进行用户存储认证

    不会

    二、密码加密策略

    共提供了九种加密方式和一种自定义接口,简单列举几个如下

    • BCryptPasswordEncoder 强hash方式加密,推荐使用
    • Pbkdf2PasswordEncoder
    • SCryptPasswordEncoder
    • 实现org.springframework.security.crypto.password.PasswordEncoder接口 自定义加密方式

    除此外还提供了PasswordEncoderFactories.createDelegatingPasswordEncoder()以委托的方式创建加密策略。使用比较简单,只需要在用户储存配置后在配置一下即可。

    auth.userDetailsService(securityService)
        .passwordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
    

    三、请求拦截策略

    • 编码式配置权限拦截

    请求拦截通过重载configure(HttpSecurity)方法实现,支持两种匹配风格,ant和正则。

     @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // .antMatchers("/user/**").anonymous() 匿名访问
                .antMatchers("/user/**").hasAuthority("ADMIN");
                // .regexMatchers("").anonymous(); // 正则方式
        http.requiresChannel().antMatchers("/admin/info")
                // .requiresInsecure() 强制http请求
                .requiresSecure(); // 强制https请求
    }
    

    请求保护方法一览

    access(String)     如果给定的SpEL表达式计算结果为true,就允许访问
    anonymous()        允许匿名用户访问
    authenticated()    允许认证过的用户访问
    denyAll()          无条件拒绝所有访问
    permitAll()        无条件允许访问
    fullyAuthenticated()   如果用户是完整认证的话(不是通过Remember-me功能认证的),就允许访问
    hasAnyAuthority(String...)   如果用户具备给定权限中的某一个的话,就允许访问
    hasAnyRole(String...)   如果用户具备给定角色中的某一个的话,就允许访问
    hasAuthority(String)   如果用户具备给定权限的话,就允许访问
    hasIpAddress(String)   如果请求来自给定IP地址的话,就允许访问
    hasRole(String)   如果用户具备给定角色的话,就允许访问
    not()   对其他访问方法的结果求反
    rememberMe()   如果用户是通过Remember-me功能认证的,就允许访问
    requiresChannel() // 请求通道配置
    
    • 声明式权限过滤

    共提供了三组注解来实现声明式配置

    • @PreAuthorize 前置访问授权控制,支持Spring-EL表达式,如:@PreAuthorize("hasAuthority('ROLE_ADMIN')")推荐长期使用。不需要过多介绍,自动提示做的很好。
    • @PostAuthorize 后置访问授权控制,可以拿到返回的结果returnObject,使用的不多
    • @Secured 因不支持spring自家的Spring-EL而遭到嫌弃,效果也还是可以达到的
    • JSR-250 详情查看jsr-250标准

    ==注:在我看的文档中说到要使用注解需要先显示的声明启用注解@EnableGlobalMethodSecurity(prePostEnabled = true),测试中发现并不需要,使用版本为4.2.11.RELEASE,文档版本3.2.2.RELEASE。==

    四、自定义登录登出

    研究半天才发现,security它尽然是自带登录处理的,一直在想shiro中使用SecurityUtils.login来登录,这用什么呢?没想到啥都不用,默认提供好了。当然咯默认的都是很简单的还是需要自定义才好。默认的登录也还是需要显示启用下的,简单一句配置就行。

    // http请求拦截中声明
    http.authorizeRequests().anyRequest().authenticated()
                    .and()
                    .formLogin().permitAll() // 重点一句
    

    自定义也很简单

    .formLogin().loginPage("/mylogin").permitAll()
    

    需要自己写个mylogin页面

    @RequestMapping("/mylogin")
    public String login() {
        return "/login";
    }
    // 自定义登录页面
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>security登录</title>
    </head>
    <body>
    <form method="post" action="/mylogin">
        <input type="text" name="username"><br>
        <input type="password" name="password"><br>
        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
        <input type="submit" value="登录">
    </form>
    </body>
    </html>
    

    ==注:表单的提交地址要和自定义的登录地址一样,springsecurity会自动帮我们处理。==

    自定义登出稍微复杂一点,需要在控制器中写不少代码了~

    // 配置一下自定义的登出url
    .logout().logoutUrl("/logout").permitAll();
    

    提供一个登出控制器,代码如下

    @RequestMapping("/logout")
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
            logoutHandler.logout(request, response, auth);
        }
        return "redirect:/login?logout";
    }
    

    五、让Security记住我

    记住我是一个比较通用的功能,一般记住我都是使用cookie来实现的,spring security当然也不例外,接下来就实现记住我功能。

    • 简单的配置实现记住我
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ....省略其他配置
        http.rememberMe().rememberMeCookieName("remember-me")
                .rememberMeParameter("remember-me")
                .userDetailsService(userDetailsService);
    }
    

    OK了,没其他配置了,就这样就行了,在提交表单时加一个remember-me=true就可以了。

    至此一个简单的springsecurity入门就结束了,更灵活的自定义在慢慢研究~~
    源码

    相关文章

      网友评论

          本文标题:SpringSecurity4入门篇

          本文链接:https://www.haomeiwen.com/subject/uoaauqtx.html