Spring Security配置

第一步,空Spring Boot环境。

  暂时不添加了Spring Security依赖。

第二步,确保项目能够正常运行。

  启动启动项 Application.java 

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
@EnableAutoConfiguration
public class AuthorityApplication {

public static void main(String[] args) {
SpringApplication.run(AuthorityApplication.class, args);
}

// localhost:8080/
@RequestMapping(value = "/")
public String home() {
return "这是根路径";
}

// localhost:8080/hello
@RequestMapping(value = "/hello")
public String hello() {
return "hello";
}
}

  确保Spring Boot项目能够正常启动。

 

  

 

第三步,添加了Spring Security依赖。

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

  重启Application,访问 localhost:8080/ ,出现以下界面,自动跳转至 http://localhost:8080/login ,需要登录,实现了认证功能。

  

 

 

 

 

 

  

第四步,自定义Spring Security配置文件 SpringSecurityCustomConfig.java 。

  1.实现对主路径放行、其他路径请求需要验证、注销操作允许任意权限访问、表单登录允许任意权限访问。

  2.对js、css、images不做拦截。

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration// 配置文件
@EnableWebSecurity// 打开web支持
public class SpringSecurityCustomConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 决定那些请求被拦截
        http.authorizeRequests()
                .antMatchers("/").permitAll()// 主路径放行
                .anyRequest().authenticated()// 其他请求需经过验证
                .and()
                .logout().permitAll()// 注销操作允许任意权限访问
                .and()
                .formLogin().permitAll();// 表单登录允许任意权限访问
        
        http.csrf().disable();// 关闭默认的csrf认证
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js'/**", "/css/**", "/images/**");// 对js、css、images不做拦截
    }
}

  访问主路径 http://localhost:8080/ ,不需要验证。

   

 

 

 

  访问其他路径 http://localhost:8080/hello ,需要验证。出现以下界面,自动跳转至 http://localhost:8080/login

 

 

  

 

Spring Security常见案例

案例一:只需登录

  不希望花太多时间做登录功能,也不希望数据库存储登录用户名和密码。

  自定义Spring Security配置文件 SpringSecurityCustomConfig.java  ,通知系统在内存中有一个用户名为“admin”,用户密码为“123456”的用户,该用户角色为“ADMIN”。

  访问需要验证的路径 http://localhost:8080/hello ,分别输入错误信息和正确信息。

 

 

 

 

 

 

 

 

  访问 http://localhost:8080/login?logout 即可登出。

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration// 配置文件
@EnableWebSecurity// 打开web支持
public class SpringSecurityCustomConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// Spring Security提供了一套基于内存的验证
auth.inMemoryAuthentication()
.withUser("admin")
.password("123456")
.roles("ADMIN");// 自定义角色
// 可以添加若干个auth.inMemoryAuthentication()
}

@Override
protected void configure(HttpSecurity http) throws Exception {
// 决定那些请求被拦截
http
.authorizeRequests()
.antMatchers("/").permitAll()// 主路径放行
.anyRequest().authenticated()// 其他请求需经过验证
.and()
.formLogin().permitAll()// 表单登录允许任意权限访问
.and()
.logout().permitAll();// 注销操作允许任意权限访问

http.csrf().disable();// 关闭默认的csrf认证
}

@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js'/**", "/css/**", "/images/**");// 对js、css、images不做拦截
}
}

 

案例二:指定角色,权限按角色分配

  自定义Spring Security配置文件 SpringSecurityCustomConfig.java ,通知系统在内存中有一个用户名为“caiji”,用户密码为“caiji”的用户,该用户角色为“USER”。

   访问需要验证的路径 http://localhost:8080/hello

  访问需要验证的路径 http://localhost:8080/roleAuth ,caiji无权限访问,admin可以访问

Application.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
@EnableAutoConfiguration// Spring Boot会自动根据jar依赖自动配置项目
@EnableGlobalMethodSecurity(prePostEnabled = true)// 启动注解@PreAuthorize的作用
public class AuthorityApplication {

    public static void main(String[] args) {
        SpringApplication.run(AuthorityApplication.class, args);
    }

    // localhost:8080/
    @RequestMapping(value = "/")
    public String home() {
        return "这是根路径";
    }

    // localhost:8080/hello
    @RequestMapping(value = "/hello")
    public String hello() {
        return "hello ADMIN";
    }

    // localhost:8080/hello
    @PreAuthorize("hasRole('ROLE_ADMIN')")// RoleVote中定义需要添加前缀
    @RequestMapping(value = "/roleAuth")
    public String roleAuth() {
        return "hello USER";
    }
}
SpringSecurityCustomConfig.jaca

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // Spring Security提供了一套基于内存的验证
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password("123456")
                .roles("ADMIN");// 自定义角色
        // 可以添加若干个auth.inMemoryAuthentication()
        auth.inMemoryAuthentication().withUser("caiji").password("caiji").roles("USER");// USER用户
    }

 

案例三:数据库管理用户

  新增 UserService 类,实现 UserDetailsService 。

UserService.java

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

@Component
public class UserService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        return null;
    }
}

  将用户admin、caiji放入数据库,使用UserService管理。

SpringSecurityCustomConfig.java

@Autowired
    private UserService userService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // Spring Security提供了一套基于内存的验证
//        auth.inMemoryAuthentication()
//                .withUser("admin")
//                .password("123456")
//                .roles("ADMIN");// 自定义角色
//        // 可以添加若干个auth.inMemoryAuthentication()
//        auth.inMemoryAuthentication().withUser("caiji").password("caiji").roles("USER");// USER用户

        auth.userDetailsService(userService);
    }

  自定义密码管理验证,新建 PasswordCustomEncoder 类,实现 PasswordEncoder 接口。

  Spring Security提供了许多对密码加密的封装类,此处以MD5加密为例。

PasswordCustomEncoder.java
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @author tabjin
 * create at 2019-06-29 09:05
 * @program authority
 * @description
 */
public class PasswordCustomEncoder implements PasswordEncoder {

    private final static String SALT = "123456";
    /**
     * 加密方法,对原始密码加密
     * @param charSequence
     * @return
     */
    @Override
    public String encode(CharSequence charSequence) {
        Md5PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder();
        return md5PasswordEncoder.encodePassword(charSequence.toString(), SALT);// 加密并附加123456
    }

    /**
     * 匹配方法,对原始密码和加密后密码匹配
     * @param charSequence
     * @param s
     * @return
     */
    @Override
    public boolean matches(CharSequence charSequence, String s) {
        Md5PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder();
        return md5PasswordEncoder.isPasswordValid(s, charSequence.toString(), SALT);// 保证盐值和加密时一样
    }
}

  回到定义认证的类 SpringSecurityCustomConfig.java 

SpringSecurityCustomConfig.java

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

        // 自定义处理
        auth.userDetailsService(userService).passwordEncoder(new PasswordCustomEncoder());// 指定好UserService后添加自定义密码验证器
        // Spring Security 默认数据库处理,表结构位于users.ddl
        auth.jdbcAuthentication().usersByUsernameQuery("").passwordEncoder(new PasswordCustomEncoder());
    }

 

posted @ 2019-06-28 16:40  Tabjin  阅读(526)  评论(0)    收藏  举报