SpringSecurity配置文件+注解配置笔记

这篇博客详细介绍了SpringSecurity的基本概念、核心功能,包括认证和授权,并展示了如何使用默认配置和数据库验证用户登录。内容涵盖从引入依赖、加载过滤器到配置类的编写,以及如何实现用户登录效果。

SpringSecurity配置文件+注解配置笔记

一、什么是SpringSecurity

Spring Security 最早不叫 Spring Security ,叫 Acegi Security,叫 Acegi Security 并不是说它和 Spring 就没有关系了,它依然是为 Spring 框架提供安全支持的。事实上,Java 领域的框架,很少有框架能够脱离 Spring 框架独立存在。Acegi Security 基于 Spring,可以帮助我们为项目建立丰富的角色与权限管理,但是最广为人诟病的则是它臃肿繁琐的配置,这一问题最终也遗传给了 Spring Security。

当 Acegi Security 投入 Spring 怀抱之后,先把这个名字改了,这就是大家所见到的 Spring Security 了,然后配置也得到了极大的简化。

但是和 Shiro 相比,人们对 Spring Security 的评价依然中重量级、配置繁琐。

二、有什么功能

对于一个权限管理框架而言,无论是 Shiro 还是 Spring Security,最最核心的功能,无非就是两方面:
认证
授权
通俗点说,认证就是我们常说的登录,授权就是权限鉴别,看看请求是否具备相应的权限。

Spring Security 支持多种不同的认证方式,这些认证方式有的是 Spring Security 自己提供的认证功能,有的是第三方标准组织制订的,主要有如下一些:
一些比较常见的认证方式:
HTTP BASIC authentication headers:基于IETF RFC 标准。
HTTP Digest authentication headers:基于IETF RFC 标准。
HTTP X.509 client certificate exchange:基于IETF RFC 标准。
LDAP:跨平台身份验证。
Form-based authentication:基于表单的身份验证。
Run-as authentication:用户用户临时以某一个身份登录。
OpenID authentication:去中心化认证。

除了这些常见的认证方式之外,一些比较冷门的认证方式,Spring Security 也提供了支持。
Jasig Central Authentication Service:单点登录。
Automatic “remember-me” authentication:记住我登录(允许一些非敏感操作)。
Anonymous authentication:匿名登录。

三、SpringSecurity的使用

使用默认配置的Security
1、引入依赖
<!--5.4.2-->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>${security.version}</version>
</dependency>
<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>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>${security.version}</version>
</dependency>
2、加载过滤器

俩种方式:

web.xml加载过滤器
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>
    org.springframework.web.filter.DelegatingFilterProxy
    </filter-class>
</filter>
配置类加载过滤器
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SecurityWebApplicationInitializer
        extends AbstractSecurityWebApplicationInitializer {
}
3、加载配置类
利用配置文件扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="cn.zzcfirst.config"/>

</beans>
利用配置类进行配置
public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{WebSecurityConfig.class};
	}

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{//...};
	}

    @Override
    protected String[] getServletMappings() {
        return new String[]{//...}};
    }
}
4、登陆效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-djECecW8-1611297032382)(C:\Users\Administrator\Desktop\重要文档\Hi\2020Java笔记\SpringBoot笔记\md-boot\pic\security登陆效果图.png)]

使用数据库进行用户登陆验证
1、引入依赖
2、创建配置类
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
	private UserService userService;

    @Bean
    public PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
	}

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/test/**").authenticated()
                .and()
                .formLogin()
                .loginProcessingUrl("/test/login")
                .successHandler(new AuthenticationSuccessHandler(){
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        PrintWriter out = httpServletResponse.getWriter();
                        out.write("{\"status\":\"success\",\"message\":\"登录成功!\"}");
                        out.flush();
                        out.close();
                    }
                })
                .failureHandler(new AuthenticationFailureHandler(){
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        PrintWriter out = httpServletResponse.getWriter();
                        out.write("{\"status\":\"error\",\"message\":\"账号或密码错误!\"}");
                        out.flush();
                        out.close();
                    }
                })
                .and()
                .exceptionHandling()
                .authenticationEntryPoint((request, response, authException) -> {
                    response.setContentType("application/json;charset=utf-8");
                    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                    PrintWriter out = response.getWriter();
                    out.write("{\"status\":\"error\",\"message\":\"授权已过期,请重新登录。\"}");
                    out.flush();
                    out.close();
                })
                .accessDeniedHandler((request, response, authException) -> {
                    response.setContentType("application/json;charset=utf-8");
                    response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                    PrintWriter out = response.getWriter();
                    out.write("{\"status\":\"error\",\"message\":\"您没有权限进行此操作!\"}");
                    out.flush();
                    out.close();
                })
                .and()
                .logout()
                .logoutUrl("/test/logout")
                .logoutSuccessHandler((request, response, authentication) -> {
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write("{\"status\":\"success\",\"message\":\"注销成功!\"}");
                    out.flush();
                    out.close();
                })
                .and()
                .userDetailsService(userService)
                .csrf().disable();
    }

}
3、创建UserDetailService实现类
//接口
public interface UserService extends UserDetailsService{
    User getUserById(String uid);
    List<User> getUsers();
}

//接口实现类
@Service
public class UserServiceImpl implements UserService {

    @Autowired
	private UserMapper userMapper;

    @Override
    public User loadUserByUsername(String s) throws UsernameNotFoundException {
        User inputUser = new User();
        inputUser.setUsername(s);
        User user = userMapper.selectOne(inputUser);
        if (user == null) {
            throw new UsernameNotFoundException("找不到用户名为: " + s + "的用户");
        }
        return user;
	}

    @Override
    public User getUserById(String uid) {
        return userMapper.selectByPrimaryKey(uid);
	}

    @Override
    public List<User> getUsers() {
        return userMapper.selectAll();
    }

}
//实体类需要实现接口
public class User  implements UserDetails
4、登陆效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7yYKn5K1-1611297032394)(C:\Users\Administrator\Desktop\重要文档\Hi\2020Java笔记\SpringBoot笔记\md-boot\pic\security登陆效果图2.png)]

四、SpringSecurity配置详解

配置段落含义
http
.authorizeRequests()
.antMatchers("/test/**")
.authenticated()
authorizeRequests()方法返回一个配置类,
antMatchers()在这个配置类上设置路径,
authenticated()表示test路径下的所有资源都需要进行认证。
.and()
.formLogin()
.loginProcessingUrl("/api/login")
.successHandler(
(request, response, authentication) -> {
…逻辑
})
.failureHandler(
(request, response, exception) -> {
…逻辑
})
and()方法使得上面一部分配置完成之后,返回到HttpSecurity方便进行下一项配置。
formLogin()会获取配置登陆的配置类,
loginProcessingUrl()中配置的路径为登陆用户名和密码所提交的url,
successHandler()和failureHandler()分别对应登陆成功和登陆失败后需要进行的操作。
.and()
.exceptionHandling()
.authenticationEntryPoint(
(request, response, authException) -> {
…逻辑
}).accessDeniedHandler(
(request, response, authException) -> {
…逻辑
})
exceptionHandling()方法返回出现异常时的配置类,
authenticationEntryPoint()方法处理认证出现异常的情况,
accessDeniedHandler()方法处理权限异常。
.and()
.logout()
.logoutUrl("/test/logout")
.logoutSuccessHandler(
(request, response, authentication) -> {
…逻辑
})
logout()返回用户注销时的配置类,
logoutUrl()设置注销时访问的Url,
logoutSuccessHandler()处理注销成功之后的逻辑。
.and()
.userDetailsService(userService)
.csrf()
.disable();
userDetailService()方法设置从数据库读取用户信息的类。
此类需要实现UserDetailsService接口并重写loadUserByUsername方法。
csrf().disable()关闭跨站请求伪造保护。

五、SpringSecurity配置类相关

1、配置类需要继承适配器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OWkS0mtx-1611297032397)(C:\Users\Administrator\Desktop\重要文档\Hi\2020Java笔记\SpringBoot笔记\md-boot\pic\security需要继承的类.png)]

2、配置的三个方法
方法作用
configure(AuthenticationManagerBuilder auth)通过重载配置user-detail服务
configure(WebSecurity web)通过重载配置Security的Filter链
configure(HttpSecurity http)通过重载配置如何保护请求
3、了解用户是谁

1、通过给方法注入Authentication对象 通过对象的getPrincipal()获取

@GetMapping("/showuser")
public User showuser(Authentication auth){
    System.out.println(auth.getPrincipal());
    return (User)auth.getPrincipal();
}

2、在Controller方法上添加注解@AuthenticationPrincipal User user即可自动注入用户相关信息。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值