Spring Security (1)-配置篇

原文链接:http://www.jylt.cc/#/detail?id=dbfcb0d72b016dc3e52fcab29a101845

框架简介

spring security 是一款基于Spring 框架的框架,提供了一套web应用安全性的完整解决方案。

web应用的安全性一般分为:用户认证和用户授权两部分。

用户认证就是用来区分当前访问的用户、设备等身份。比如我们常用的登录操作就属于用户认证,登录之后系统便知道我们是谁。

用户授权就是辨识当前用户拥有的角色、权限。比如用户是不是管理员角色,如果是管理员角色就可以增加、删除、修改普通用户信息,这些增加、删除、修改就是用户所拥有的权限。

用户授权和用户授权如果我们自己开发,会花费较多的经历来处理各种逻辑。而spring security就可以大大简化我们的这些操作,提高开发效率,并且还能减少一些不经意的bug。


spring boot集成 spring security

添加依赖

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

配置

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.formLogin()
		.usernameParameter("account")
                .passwordParameter("password")
		.loginProcessingUrl("/user/login")
//                .successForwardUrl()
                .successHandler(new MySuccessHandler())
//              .failureForwardUrl()
                .failureHandler(new MyFailHandler());


        httpSecurity.authorizeRequests()
                .antMatchers("/content/list_contents", "/user/sendValidCode",
                        "/user/add_user").permitAll()
		.regexMatchers().permitAll()
                .anyRequest().authenticated();
	
	// 异常处理
 	httpSecurity.exceptionHandling()
		// 权限异常处理
                .accessDeniedHandler(new MyAccessDeniedHandler());

        httpSecurity.csrf().disable();
    }
}

参数说明

  • httpSecurity.formLogin():登录数据处理
方法名说明
usernameParameter自定义接收前端用户名字段,spring security框架默认只接收username字段,其他字段接收为""
passwordParameter自定义接收前端密码字段,spring security框架默认只接收password字段,其他字段接收为""
loginProcessingUrl登录接口url
successForwardUrl登录成功后跳转页面的适配器,前后端分离的时候可以使用,参考类:org.springframework.security.web.authentication.ForwardAuthenticationSuccessHandler
successHandler登录成功后跳转页面的适配器,前后端分离的时候可以使用,参考类:org.springframework.security.web.authentication.ForwardAuthenticationSuccessHandler
failureForwardUrl登录失败后跳转的页面,前后端不分离的时候可以使用
failureHandler登录失败后跳转页面的适配器,前后端分离的时候可以使用,参考类:org.springframework.security.web.authentication.ForwardAuthenticationSuccessHandler

说明:usernameParameter、passwordParameter可参考类:org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter

  • httpSecurity.authorizeRequests():授权
方法名说明
antMatchers().permitAll忽略的资源路径,这里的资源直接被框架放行,比如说:注册接口、一些静态资源文件等不需要登录就可以访问
regexMatchers().permitAll使用正则表达式忽略指定资源路径
anyRequest().authenticated()任意请求都需要是已经认证过的,即只有登录后才可以访问的接口

注意:antMatchers必须放在anyRequest之前,否则会报异常:Can't configure antMatchers after anyRequest

说明:antMatchers参数是不定参数,每个参数都是一个ant表达式,用于匹配url规则。规则如下:
?:匹配一个字符

方法名说明
匹配一个字符
*匹配0或多个字符
**匹配0或多个目录

MySuccessHandler.class 登陆成功处理器

public class MySuccessHandler implements AuthenticationSuccessHandler {


    public MySuccessHandler() {

    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException {
        PrintWriter writer = httpServletResponse.getWriter();
        ResponseKit<String> res = ResponseKit.success("登录成功");
        writer.write(JSONUtil.toJsonStr(res));
        writer.flush();
        writer.close();
    }
}

MyFailHandler.class 登陆失败处理器

public class MyFailHandler implements AuthenticationFailureHandler {


    public MyFailHandler() {

    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
        PrintWriter writer = httpServletResponse.getWriter();
        ResponseKit<String> res = ResponseKit.error(HttpStatus.FORBIDDEN.value(), "用户名或密码错误");
        writer.write(JSONUtil.toJsonStr(res));
        writer.flush();
        writer.close();
    }
}

MyAccessDeniedHandler.class 权限异常处理器

public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
        PrintWriter writer = httpServletResponse.getWriter();
        ResponseKit<Object> responseKit = ResponseKit.error(HttpStatus.FORBIDDEN.value(), "权限不足");
        writer.write(JSONUtil.toJsonStr(responseKit));
        writer.flush();
        writer.close();
    }
}

内置访问控制说明

上面授权的方法中有如:permitAll允许所有,authenticated需要授权的这些方法,以下是方法总结

方法名说明
permitAll允许所有资源访问
denyAll禁止所有资源访问
anonymous允许匿名访问的资源
authenticated只允许认证后可访问的资源
remember自动登录后能访问的资源

官方说明:

ExpressionDescription
hasRole(String role)Returns true if the current principal has the specified role. For example, hasRole(‘admin’) By default if the supplied role does not start with ‘ROLE_’ it will be added. This can be customized by modifying the defaultRolePrefix on efaultWebSecurityExpressionHandler.
hasAnyRole(String…​ roles)Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings). For example, hasAnyRole(‘admin’, ‘user’) By default if the supplied role does not start with ‘ROLE_’ it will be added. This can be customized by modifying the defaultRolePrefix on DefaultWebSecurityExpressionHandler.
hasAuthority(String authority)Returns true if the current principal has the specified authority. For example, hasAuthority(‘read’)
hasAnyAuthority(String…​ authorities)Returns true if the current principal has any of the supplied authorities (given as a comma-separated list of strings) For example, hasAnyAuthority(‘read’, ‘write’)
principalAllows direct access to the principal object representing the current user
authenticationAllows direct access to the current Authentication object obtained from the SecurityContext
permitAllAlways evaluates to true
denyAllAlways evaluates to false
isAnonymous()Returns true if the current principal is an anonymous user
isRememberMe()Returns true if the current principal is a remember-me user
isAuthenticated()Returns true if the user is not anonymous
isFullyAuthenticated()Returns true if the user is not an anonymous or a remember-me user
hasPermission(Object target, Object permission)Returns true if the user has access to the provided target for the given permission. For example, hasPermission(domainObject, ‘read’)
hasPermission(Object targetId, String targetType, Object permission)Returns true if the user has access to the provided target for the given permission. For example, hasPermission(1, ‘com.example.domain.Message’, ‘read’)

角色权限控制

基于代码控制资源访问

基于权限进行访问

在配置spring security的时候,可以对指定资源加上特定的访问权限,只有用户拥有该权限时才可以访问该资源。例如:

httpSecurity.authorizeRequests()
                .antMatchers("/content/list_contents", "/user/sendValidCode",
                        "/user/add_user").permitAll()
                .regexMatchers().permitAll()
                .antMatchers("/edit").hasAnyAuthority("edit,edit_or_update")
                .antMatchers("/update").hasAuthority("edit_or_update")
                .anyRequest().authenticated();

说明:上面代码中的.antMatchers("/edit").hasAnyAuthority("edit,edit_or_update"),表示只有拥有edit或者edit_or_update权限的用户才可以访问/edit资源;其中hasAnyAuthority()表示只要拥有任一权限都可访问前面定义的资源;
.antMatchers("/update").hasAuthority("edit_or_update")说明只有拥有edit_or_update权限的用户才可以访问/update资源;其中hasAuthority()表示只用该权限的才可以访问前面定义的资源。

基于角色进行访问

在配置spring security的时候,可以对指定资源加上特定的访问角色,只有用户拥有该角色时才可以访问该资源。例如:

httpSecurity.authorizeRequests()
                .antMatchers("/content/list_contents", "/user/sendValidCode",
                        "/user/add_user").permitAll()
                .regexMatchers().permitAll()
                .antMatchers("/edit").hasAnyRole("admin,user")
                .antMatchers("/update").hasRole("admin")
                .anyRequest().authenticated();

说明,haseRole()hasAnyRole()使用跟上面hasAnyAuthority()hasAuthority类似。
注意: 角色不能以ROLE_开头。

基于IP地址进行访问

在工作中有时候可能只允许特定IP访问服务,这个时候可以根据IP地址进行授权。

httpSecurity.authorizeRequests()
                .antMatchers("/content/list_contents", "/user/sendValidCode",
                        "/user/add_user").permitAll()
                .regexMatchers().permitAll()
                .antMatchers("/edit").hasIpAddress("127.0.0.1")
                .anyRequest().authenticated();

其中hasIpAddress()就是允许访问的IP地址。

基于注解控制资源访问

开启注解

使用注解之前需要先开启注解控制功能,在启动类上打开注解功能:@EnableGlobalMethodSecurity(prePostEnabled = true)

使用

@PreAuthorize(String val):该注解用于方法或类上,在类或方法执行之前先判断是否拥有指定角色或者权限,其中参数与上面说到的基于代码控制资源访问内容相似,可以有以下写法:

  • @PreAuthorize(“hasRole(value)”):拥有value角色才可访问
  • @PreAuthorize(“hasAnyRole(admin,user)”):拥有admin、user任一角色都可访问
@PreAuthorize("hasRole(admin)")
@PostMapping("/save")
public void saveO() {
        
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

记忆旅途

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值