SpringBoot集成SpringSecurity

一.入门(Spring Security在不进行任何配置下默认给出的用户user 密码随项目启动生成随机字符串)

1.添加依赖

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

2.访问index首页的时候,系统会默认跳转到login页面进行登录认证

 3.用户名默认是user,密码在项目启动时会自动生成

4.输入用户和密码即可正常访问

二.Spring Security用户密码配置其他方式

1.springboot配置文件中配置

spring:
  security:
    user:
      name: admin  # 用户名
      password: 123456  # 密码

2.java代码在内存中配置

 新建Security 核心配置类WebSecurityConfig继承WebSecurityConfigurerAdapter

@Configuration
@EnableWebSecurity // 启用Spring Security的Web安全支持
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 用户配置在内存中
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 在内存中配置用户,配置多个用户调用`and()`方法
        auth.inMemoryAuthentication().passwordEncoder(passwordEncoder())// 指定加密方式
                .withUser("admin").password(passwordEncoder().encode("123")).roles("ADMIN")
                .and()
                .withUser("test").password(passwordEncoder().encode("456")).roles("TEST");
    }


    /**
     * 配置加密方式
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        //BCryptPasswordEncoder:Spring Security 提供的加密工具,可快速实现加密加盐
        /*return new BCryptPasswordEncoder();*/
        return new PasswordEncoder() {

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return encodedPassword.equals(encode(rawPassword));
            }

            @Override
            public String encode(CharSequence rawPassword) {
                return Sha1.degest(rawPassword.toString());
            }
        };
    }

3.从数据库中获取用户账号、密码信息(实际中最常用方式)

自定义CustomUserDetailsService
/**
     * 用户配置在数据库中_动态认证
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
    }

三. Spring Security 配置 登录处理 与 忽略拦截 

/**
     * 登录处理
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //开启登录配置
        http.authorizeRequests()
                // 标识访问 `/index` 这个接口,需要具备`ADMIN`角色
                .antMatchers("/index").hasRole("ADMIN")
                // 允许匿名的url - 可理解为放行接口 - 多个接口使用,分割
                .antMatchers(
                        servicePrefix+"/",
                        servicePrefix+"/csrf",
                        servicePrefix + "/actuator/health/**",
                        servicePrefix + "/auth/login",
                        servicePrefix + "/public/**").permitAll()
                // 其余所有请求都需要认证
                .anyRequest().authenticated()
                .and()
                // 设置登录认证页面
                .formLogin().loginPage(servicePrefix + "/auth/login")
                // 登录成功后的处理器
                .successHandler(authenticationSuccessHandler)
                // 登录失败的处理器
                .failureHandler(authenticationFailHandler)
                .and()
                // 配置注销成功的处理
                .logout().logoutUrl(servicePrefix + "/auth/logout").deleteCookies("SESSIONID", "JSESSIONID", "TGC")
                .logoutSuccessHandler(myLogoutSuccessHandler)
                .and()
                // 配置 Http Basic 验证
                .httpBasic()
                .and()
                //关闭CSRF跨域
                .csrf().disable();
        // 配置跨域资源共享
        http.cors();
        // 是否允许配置请求缓存
        http.requestCache().disable();

    }

    /**
     * 忽略拦截
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        // 设置拦截忽略url或者js/css等静态资源,将不会经过Spring Security过滤器链
        web.ignoring().antMatchers(servicePrefix + "/swagger-ui.html",
                servicePrefix + "/swagger-resources/**",
                servicePrefix + "/v2/**",
                servicePrefix + "/webjars/springfox-swagger-ui/**",
                "/**/*.html",
                "/**/*.css", "/**/*.js",
                "/**/*.png", "/**/*.jpg", "/**/*.jpeg",
                "/**/*.ico","/**/*.svg", "/**/*.ttf","/**/*.woff", "/**/*.woff2");
    }

 最后,附上完整的security配置代码

1.WebSecurityConfig配置

@Configuration
@EnableWebSecurity // 启用Spring Security的Web安全支持
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${spring.mvc.servlet.path}")
    private String servicePrefix;

    @Resource
    private AuthenticationSuccessHandler authenticationSuccessHandler;

    @Resource
    private AuthenticationFailHandler authenticationFailHandler;

    @Resource
    private MyLogoutSuccessHandler myLogoutSuccessHandler;

    @Resource
    private CustomUserDetailsService customUserDetailsService;/**
     * 用户配置在内存中_静态认证
     * @param auth
     * @throws Exception
     */
    /*@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 在内存中配置用户,配置多个用户调用`and()`方法
        auth.inMemoryAuthentication().passwordEncoder(passwordEncoder())// 指定加密方式
                .withUser("admin").password(passwordEncoder().encode("123")).roles("ADMIN")
                .and()
                .withUser("test").password(passwordEncoder().encode("456")).roles("TEST");
    }*/

    /**
     * 用户配置在数据库中_动态认证
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
    }

    /**
     * 配置加密方式
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        //BCryptPasswordEncoder:Spring Security 提供的加密工具,可快速实现加密加盐
        /*return new BCryptPasswordEncoder();*/
        return new PasswordEncoder() {
            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return encodedPassword.equals(encode(rawPassword));
            }

            @Override
            public String encode(CharSequence rawPassword) {
                return Sha1.degest(rawPassword.toString());
            }
        };
    }

    /**
     * 登录处理
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //开启登录配置
        http.authorizeRequests()
                // 标识访问 `/index` 这个接口,需要具备`ADMIN`角色
                .antMatchers("/index").hasRole("ADMIN")
                // 允许匿名的url - 可理解为放行接口 - 多个接口使用,分割
                .antMatchers(
                        servicePrefix+"/",
                        servicePrefix+"/csrf",
                        servicePrefix + "/actuator/health/**",
                        servicePrefix + "/auth/login",
                        servicePrefix + "/public/**").permitAll()
                // 其余所有请求都需要认证
                .anyRequest().authenticated()
                .and()
                // 设置登录认证页面
                .formLogin().loginPage(servicePrefix + "/auth/login")
                // 登录成功后的处理器
                .successHandler(authenticationSuccessHandler)
                // 登录失败的处理器
                .failureHandler(authenticationFailHandler)
                .and()
                // 配置注销成功的处理
                .logout().logoutUrl(servicePrefix + "/auth/logout").deleteCookies("SESSIONID", "JSESSIONID", "TGC")
                .logoutSuccessHandler(myLogoutSuccessHandler)
                .and()
                // 配置 Http Basic 验证
                .httpBasic()
                .and()
                //关闭CSRF跨域
                .csrf().disable();
        // 配置跨域资源共享
        http.cors();
        // 是否允许配置请求缓存
        http.requestCache().disable();

    }

    /**
     * 忽略拦截
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        // 设置拦截忽略url或者js/css等静态资源,将不会经过Spring Security过滤器链
        web.ignoring().antMatchers(servicePrefix + "/swagger-ui.html",
                servicePrefix + "/swagger-resources/**",
                servicePrefix + "/v2/**",
                servicePrefix + "/webjars/springfox-swagger-ui/**",
                "/**/*.html",
                "/**/*.css", "/**/*.js",
                "/**/*.png", "/**/*.jpg", "/**/*.jpeg",
                "/**/*.ico","/**/*.svg", "/**/*.ttf","/**/*.woff", "/**/*.woff2");
    }
}

2.自定义 CustomUserDetailsService 

@Component
public class CustomUserDetailsService implements UserDetailsService {

    @Resource
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {

        UserInfo loginUser = userMapper.selectOneByUserLoginId(userName);
        if (loginUser == null) {
            throw new UsernameNotFoundException("用户名为" + userName + "的用户不存在");
        }

        List<Role> roles = loginUser.getRoles();
        List<SimpleGrantedAuthority> authoritys = this.getAuthority(roles);

        /*
        这里构建一个Security自带的User对象返回,其构造方法:
        username: 用户登录名
        password: 用户登录密码
        enabled: 用户是启用还是禁用 true-启用 false-禁用
        accountNonExpired: 用户的帐户是否已过期 true-有效 false-过期
        accountNonLocked: 用户是锁定还是解锁 true-未锁定 false-锁定
        credentialsNonExpired: 用户的凭据(密码)是否已过期 true-凭据有效 false-凭据无效
        authorities :用户权限(角色)集合
        */
        User userDetails = new User(loginUser.getUserLoginId(),loginUser.getPassword(), loginUser.getStatus() != 0,true,true,true,authoritys);
        return userDetails;
    }

    private List<SimpleGrantedAuthority> getAuthority(List<Role> roles) {
        List<SimpleGrantedAuthority> authoritys = new ArrayList<>();
        for (Role role : roles) {
            authoritys.add(new SimpleGrantedAuthority("ROLE_"+role.getRoleName()));
        }
        return authoritys;
    }
}

3.登陆成功处理器

@Component
public class AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private UserMapper userMapper;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        String username = userDetails.getUsername();
        UserInfo userInfo = userMapper.selectOneByUserLoginId(username);

        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(RestResponse.success(userInfo)));

    }
}

4.登陆失败处理器

@Component
public class
AuthenticationFailHandler extends SimpleUrlAuthenticationFailureHandler {

    @Resource
    private ObjectMapper objectMapper;

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {

        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(RestResponse.AUTHC_ERROR));
    }

}

5.注销成功处理器

@Component
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {

    @Resource
    private ObjectMapper objectMapper;

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

        request.getSession().invalidate();
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(RestResponse.notify("注销成功")));

    }
}

 ......

springsecurity方法级权限注解详见链接: https://www.cnblogs.com/Baker-Street/p/12893414.html

原文地址:https://www.cnblogs.com/Baker-Street/p/12810275.html