# 安全管理

# 快速启动

在使用spring security时,可以参考以下步骤

  1. 在项目中加入 spring security依赖
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

2 在项目中加入以下代码

下面的代码用户应该保证能被 @ComponentScan扫描到。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends AbstractSecurityConfig {
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		super.configure(http);
	}

}

该代码的示例代码可参见 com.yishuifengxiao.common.security.SecurityConfig

  1. 实现 UserDetailsService 接口,完成自己的授权逻辑,并将其注入到spring 之中。

【特别注意】在用户未按照本步骤配置自己的授权逻辑时,组件会默认进行一个缺省实现。在缺省实现的情况下,用户能使用任意用户名配合密码(12345678)进行登录。

加入上述配置之后,只有组件中内置的默认路径能通过授权,访问其他的url都被重定向到 /index这个地址,具体的配置及原因请参照后续说明。

# 资源管理说明

授权资源管理是本组件中的重要部分,在本组件中所有的授权资源由以下几部分组成

资源组成

  1. 非管理资源
  2. 匿名资源
  3. 自定义授权逻辑资源
  4. 保护资源

也就是说 授权资源 = 非管理资源 + 匿名资源 + 自定义授权逻辑资源 + 保护资源

非管理资源

指的是不经过spring security管理,用户可以不经过授权直接无障碍访问的资源,在本组件中,默认 静态资源和swagger-ui请求路径为 非管理资源

匿名资源

指的是经过spring security管理,但是用户无需登录,通过匿名用户就能访问的资源。

自定义授权逻辑资源

指的的是需要程序根据设定自定决定是否给予访问权限的资源

保护资源

指的是需要用户登陆后才能访问的资源,该部分资源只要用户登陆成功后,无论其权限如何都能访问。

# 非管理资源

组件中内置的非管理资源的属性配置为

# 是否默认包含静态资源,默认为true
yishuifengxiao.security.ignore.containStaticResource=true
# 是否包含swagger-ui的资源,默认为true
yishuifengxiao.security.ignore.containSwaagerUiResource=true
# 是否包含actuator相关的路径,默认为true
yishuifengxiao.security.ignore.containActuator=true
# 是否包含webJars资源,默认为true
yishuifengxiao.security.ignore.containWebjars=true
# 是否包含所有的资源,默认为false
yishuifengxiao.security.ignore.containAll=false

【特别注意】请勿轻易将yishuifengxiao.security.ignore.containAll属性配置为true,否则组件会给系统中所有的资源给予访问权限。

对于其他需要自定义为非管理资源的路径资源,用户还可以通过以下配置进行扩展

yishuifengxiao.security.ignore.urls.demo1=/aaa
yishuifengxiao.security.ignore.urls.demo2=/cc/**,/dsd/**

在上面的示例配置中demo1demo2由用户自行配置,可以配置成任意符合规范的值,这些配置属性的值即为需要配置的资源,多个授权资源间用半角逗号分开。

# 自定义授权逻辑资源

yishuifengxiao.security.custom.urls.demo1=/aaa
yishuifengxiao.security.custom.urls.demo2=/cc/**,/dsd/**

与非管理资源的扩展配置类似,配置中demo1demo2由用户自行配置,可以配置成任意符合规范的值,这些配置属性的值即为需要配置的资源,多个授权资源间用半角逗号分开。

【特别注意】使用此功能需要用户配置自己的自定义授权提供器,假如用户没有进行配置,组件的缺省实现会将此部分资源直接方形。

自定义授权提供器的实例代码如下:

@Component("customAuthority")
public class CustomAuthorityImpl implements CustomAuthority {
    @Override
	public boolean hasPermission(HttpServletRequest request, Authentication auth){
	    //执行自己的授权逻辑,true表示通过授权,false表示拒绝授权
	}
}

# 匿名资源

由于此资源的功能与匿名资源类似,因此组件不提供用户自定义配置功能。 组件默认的匿名资源为

# 权限拦截时默认的跳转地址,默认为/index
yishuifengxiao.security.core.redirectUrl
# 默认的表单登陆时form表单请求的地址,默认为 /auth/form
yishuifengxiao.security.core.formActionUrl
# 默认的处理登出请求的URL的路径【即请求此URL即为退出操作】,默认为 /loginOut
yishuifengxiao.security.core.loginOutUrl
# /oauth/token
/oauth/token
# session失效时跳转的地址,默认为 /session/invalid
yishuifengxiao.security.session.sessionInvalidUrl=

# 保护资源

在系统中所有的资源,除了非管理资源配置、自定义授权逻辑资源、匿名资源之外,其他所有的资源都需要经过登陆之后才能让访问。

# 全局配置参数

# 是否关闭cors保护,默认为false
yishuifengxiao.security.close-cors=false
# 关闭csrf功能,默认为true
yishuifengxiao.security.close-csrf=true
# 是否开启httpBasic访问,默认为true
yishuifengxiao.security.http-basic=true
# 资源名称,默认为yishuifengxiao
yishuifengxiao.security.realm-name=yishuifengxiao
# 加解密中需要使用的密钥
yishuifengxiao.security.secret-key=

在spring security的官方要求中,需要用户在spring security中注入一个 PasswordEncoder接口的实例,本组件默认采用的是 【易水工具组件】中DES加密,该加密工具是基于DES对称加密算法而来,在本组件中利用其进行加密时的密钥由yishuifengxiao.security.secret-key的值决定,用户也可以不配此值,使用系统缺省密钥值。

在使用本组件时,推荐使用组件内置的默认加密工具,在用户的系统有特殊的加密需求时,可以通过向spring 中注入一个 名为 passwordEncoderPasswordEncoder实例来实现自定义加密。

示例如下

	/**
	 * 注入自定义密码加密类
	 * 
	 * @return
	 */
	@Bean("passwordEncoder")
	public PasswordEncoder passwordEncoder(SecurityProperties securityProperties) {
		return new CustomPasswordEncoderImpl(securityProperties.getSecretKey());
	}

# 登陆表单配置

表单登陆时默认的配置参数如下:

# 表单提交时 默认的用户名参数名字,默认为 username
yishuifengxiao.security.core.usernameParameter=username
#  表单提交时 默认的密码参数名字,默认为 pwd
yishuifengxiao.security.core.passwordParameter=pwd
# 权限拦截时默认的跳转地址,默认为/index
yishuifengxiao.security.core.redirectUrl=/index
# 默认的表单登陆时form表单请求的地址,默认为 /auth/form
yishuifengxiao.security.core.formActionUrl=/auth/form
# 默认的处理登出请求的URL的路径【即请求此URL即为退出操作】,默认为 /loginOut
yishuifengxiao.security.core.loginOutUrl=/loginOut

对于登陆表单配置相关的参数,系统均有默认值,如无特殊需求,用户可以采用组件的默认值。

上面提到,在访问非授权资源时,用户请求会被自动重定向到 /index ,这是由yishuifengxiao.security.core.redirectUrl这个配置决定的,当用户有特殊需求时,可以配置此属性来配置 非授权路径的重定向地址。

在表单登陆时,用户可以参考下面的表单配置

<form action="/auth/form" method="POST">

    用户名 <input name="username" /> <br /> 
    密码 <input name="pwd" /> <br />
    <button>登陆</button>

</form>

登录表单中,action提交目标由yishuifengxiao.security.core.formActionUrl决定,用户名和密码的请求参数分别由 yishuifengxiao.security.core.usernameParameteryishuifengxiao.security.core.passwordParameter决定。

在完成配置后,用户即可通过表单登陆系统了,根据用户参数的正确与否,分别有登录成功处理和登陆失败处理进行不同的逻辑处理,关于这两处理器,在后续章节会有明确介绍。

# 并发登陆管理

# 同一个用户在系统中的最大session数,默认1 
yishuifengxiao.security.session.maximumSessions=1
# 达到最大session时是否阻止新的登录请求,默认为false,不阻止,新的登录会将老的登录失效掉
yishuifengxiao.security.session.maxSessionsPreventsLogin=false
# session失效时跳转的地址
yishuifengxiao.security.session.sessionInvalidUrl=/session/invalid

当因多终端登录造成前置的登陆用户的登陆状态实现,可以实现 SessionInformationExpiredStrategy 接口并将其注入到spring之中,这样就可以记录由此导致的相关信息了。

# 记住我功能

# 记住我产生的token,默认为 yishuifengxiao
yishuifengxiao.security.remeberMe.key=yishuifengxiao
# 登陆时开启记住我的参数,默认为 rememberMe
yishuifengxiao.security.remeberMe.rememberMeParameter=rememberMe

# 验证码拦截

首先需要按照 【验证码使用】这一章节中发送验证码所有需要的相关的配置,然后进行如下配置

yishuifengxiao.security.code.filter.image=需要进行图形验证码验证的路径,多个路径之间用半角逗号隔开
yishuifengxiao.security.code.filter.sms=需要进行短信验证码验证的路径,多个路径之间用半角逗号隔开
yishuifengxiao.security.code.filter.email=需要进行邮件验证码验证的路径,多个路径之间用半角逗号隔开

进行上述配置之后,用户在请求相应的资源时将 【验证码使用】进行验证码验证时需要携带的请求参数放在本请求之后即可。这样就无需使用 【验证码使用】中的方法显式验证了。

此外,用户还可以用 yishuifengxiao.security.code.isFilterGet属性来修改是否过滤get方法。

即系统默认会对设置的GET请求进行验证码校验,如果不需要校验GET请求和将此值设置为true。

# 短信登陆

短信登陆是与表单登陆并列的功能。在某些情况下,用户需要开发短信登陆系统功能,本组件也支持此方法。

快速开启

用户可以通过配置以下熟悉开启短信登陆功能

# 开启短信登陆需要设置
yishuifengxiao.security.code.smsLoginUrl=短信登陆地址
# 短信登陆参数,默认为 mobile
yishuifengxiao.security.code.smsLoginParam=mobile

在短信登陆时,用户可以参考下面的表单配置

<form action="短信登陆地址" method="POST">

    手机号 <input name="mobile" /> <br /> 
    验证码 <input name="code" /> <br />
    <button>登陆</button>

</form>

其中手机号的参数由属性yishuifengxiao.security.code.smsLoginParam决定

# 流程处理器

# 基础概念

在本组件中,spring security涉及到的处理有 登陆成功处理、登陆失败处理、 退出成功处理器。 对于本组件中的流程处理器,在流程运行到处理器时,处理器一般有三种处理处理策略

  1. 返回json格式的数据
  2. 重定向到指定的url
  3. 由spring security根据上下文决定返回json格式的数据还是重定向

对于这几种情况,组件抽象了击中处理方式

    /**
	 * 重定向
	 */
	REDIRECT("redirect"),
	/**
	 * 返回JSON数据
	 */
	JSON("json"),
	/**
	 * 采用内容协商的方式处理
	 */
	AUTO("auto"),
	/**
	 * 原始的处理方式
	 */
	DEFAULT("default")

对于击中情况下,最终的流程处理方式由项目配置和用户请求参数共同决定:

  1. 系统配置为 redirect 时,处理器的处理方式为 重定向到指定地址
  2. 系统配置为 json 时,处理器的处理方式为 返回JSON数据
  3. 系统配置为 default 时,处理器的处理方式为 由spring security根据上下文决定返回json格式的数据还是重定向
  4. 系统配置为 auto 时,处理器的处理方式为此时根据用户请求决定,这种配置下,又分为以下几种情况
  1. 从请求头中通过制定的参数名(yishuifengxiao.security.handler.headerName属性决定)获取处理方式
  2. 判断请求中Accept请求头是否包含了json关键字,如果包含则流程处理器的处理方式为 json
  3. 从请求的url中获取指定参数(yishuifengxiao.security.handler.paramName属性决定)的值,根据参数获取处理方式
  4. 当前三步中未获取到明确的处理方式时,设置默认的处理方式为 redirect

这些属性的系统配置如下:

# 默认的header名称 type
yishuifengxiao.security.handler.headerName=type
# 默认的从请求参数获取处理方法的参数的名称 yishuifengxiao
yishuifengxiao.security.handler.paramName=yishuifengxiao

# 协助处理器

在默认情况下,各种处理器的最终流程处理都要经过 协助处理器 来实现。在 协助处理器中,组件根据根据系统的配置进行重定向或者返回json格式的数据。 协助处理器的接口定义如下:

  /**
 * 协助处理器<br/>
 * 用于处理各种 系统handler的情况
 * 
 * @author yishui
 * @Date 2019年4月2日
 * @version 1.0.0
 */
public interface ProcessHandler {

	/**
	 * 对系统中的各种handler进行协助处理
	 * 
	 * @param request  HttpServletRequest
	 * @param response HttpServletResponse
	 * @param isRedict 是否跳转
	 * @param url      希望跳转的路径
	 * @param result   传输过来的信息,如果是异常时就是异常,如果是正常时就是授权信息
	 * @throws IOException
	 * @throws ServletException
	 */
	@SuppressWarnings("rawtypes")
	public void handle(HttpServletRequest request, HttpServletResponse response, Boolean isRedict, String url,
			Response result) throws IOException, ServletException;

}

在组件,默认是由 DefaultProcessHandler来进行处理的,如果用户需要实现自定义处理逻辑,可以通过在 spring 的上下文中注入一个 ProcessHandler实例来实现。

示例代码如下:

	@Bean
	public ProcessHandler handlerProcessor(ObjectMapper objectMapper) {
		DefaultProcessHandler customHandle = new DefaultProcessHandler();
		customHandle.setObjectMapper(objectMapper);
		customHandle.setSecurityProperties(securityProperties);
		return customHandle;
	}

# 登陆成功处理器

登录成功处理器主要是在用户登录成功后发生作用,负责处理用户登录成功后的业务逻辑。

基础属性配置如下

# 流程处理器处理方式
yishuifengxiao.security.handler.suc.returnType=default
# 登陆成功后重定向的地址
yishuifengxiao.security.handler.suc.redirectUrl=/

在组件中,系统默认由CustomAuthenticationSuccessHandler处理登陆成功后的逻辑。处理流程如下:

  1. 发送一个名为 AuthenticationSuccessEvent的消息事件,告知系统已经登陆成功
  2. 将用户的认证信息存储到session中,存储的键名为 yishuifengxiao.msg.suc
  3. 获取登陆请求的处理方式
  4. 将登陆成功后逻辑交给协助处理器处理

在某些情况下,如果用户希望自定义登陆成功后的处理逻辑,可以通过在spring的上下文中注入自定义AuthenticationSuccessHandler实例即可

# 登陆失败处理器

登录成功处理器主要是在用户登录失败后发生作用,负责处理用户登录失败后的业务逻辑。

常见的登陆失败的场景有:

  1. 输入的用户名错误或不存在
  2. 输入的密码错误

基础属性配置如下

# 流程处理器处理方式
yishuifengxiao.security.handler.fail.returnType=auto
# 登陆失败后重定向的地址,
yishuifengxiao.security.handler.fail.redirectUrl=/index

在组件中,系统默认由CustomAuthenticationFailureHandler处理登陆失败后的逻辑。处理流程如下:

  1. 发送一个名为 AuthenticationFailureEvent的消息事件,告知系统已经登陆失败
  2. 将造成登陆失败的原因存储到session中,存储的键名为 yishuifengxiao.msg.fail
  3. 获取登陆失败请求的处理方式
  4. 将登陆失败后逻辑交给协助处理器处理

在某些情况下,如果用户希望自定义登陆失败后的处理逻辑,可以通过在spring的上下文中注入自定义AuthenticationFailureHandler实例即可

# 退出成功处理器

退出成功处理器主要是在用户退出成功后发生作用,负责处理用户退出成功后的业务逻辑。

基础属性配置如下

# 流程处理器处理方式
yishuifengxiao.security.handler.exit.returnType=redirect
# 登陆失败后重定向的地址,
yishuifengxiao.security.handler.exit.redirectUrl=/index
# 退出成功后需要删除的cookie的名字
yishuifengxiao.security.handler.exit.cookieName=JSESSIONID

在组件中,系统默认由CustomLogoutSuccessHandler处理登陆失败后的逻辑。处理流程如下:

  1. 发送一个名为 LogoutSuccessEvent的消息事件,告知系统已经退出成功
  2. 将用户的认证信息存储到session中,存储的键名为 yishuifengxiao.msg.exit
  3. 获取退出成功请求的处理方式
  4. 将退出成功后逻辑交给协助处理器处理

在某些情况下,如果用户希望自定义退出成功后的处理逻辑,可以通过在spring的上下文中注入自定义LogoutSuccessHandler实例即可

Last Updated: 1/13/2020, 9:58:22 PM