Spring Security入门

简介

Spring 是非常流行和成功的 Java 应用开发框架,Spring Security 正是 Spring 家族中的成员。Spring Security为基于J2EE企业应用软件提供了全面安全服务。 特别是使用领先的J2EE解决方案-spring框架开发的企业软件项目。

安全方面的两个主要区域是“认证”和“授权”(或者访问控制),一般来说,Web 应用的安全性包括**用户认证(Authentication)和用户授权 ** **(Authorization)**两个部分,这两点也是 Spring Security 重要核心功能。

(1)用户认证指的是:验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。通俗点说就是系统认为用户是否能登录

(2)用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。通俗点讲就是系统判断用户是否有权限去做某些事情。

在用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID 和 LDAP 等。在用户授权方面,Spring Security 提供了基于角色的访问控制和访问控制列表(Access Control List,ACL),可以对应用中的领域对象进行细粒度的控制。

Spring Security与Shiro的比较

官方网站:

https://spring.io/projects/spring-security

Spring Security

  • 和 Spring 无缝整合。

  • 全面的权限控制。

  • 专门为 Web 开发而设计。

    ◼旧版本不能脱离 Web 环境使用。

    ◼新版本对整个框架进行了分层抽取,分成了核心模块和 Web 模块。单独引入核心模块就可以脱离 Web 环境。

  • 重量级。

Shiro

Apache 旗下的轻量级权限控制框架。Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

官网:https://shiro.apache.org/documentation.html

特点:

​ 轻量级。Shiro 主张的理念是把复杂的事情变简单。针对对性能有更高要求的互联网应用有更好表现。

通用性。

​ 好处:不局限于 Web 环境,可以脱离 Web 环境使用。

​ 缺陷:在 Web 环境下一些特定的需求需要手动编写代码定制。

入门案例

添加依赖
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

编写Controller

@RestController
public class TestController {
   

    @GetMapping("/")
    public String hello(){
   
        return "hello";
    }
}
启动程序访问/

因安全框架的原因会将请求拦截自动跳转到认证页面,security默认提供的username为user,password在启动页会自动生成,输入默认账号密码认证成功后才会跳转显示hello!!!!
在这里插入图片描述
在这里插入图片描述

核心过滤器认识

在这里插入图片描述

在我们添加了SpringSecurity 依赖后,在项目的启动日志中,可以直观的看到SpringSecurity 的实现是通过filter chain实现的。

org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFil

ter

org.springframework.security.web.context.SecurityContextPersistenceFilter 

org.springframework.security.web.header.HeaderWriterFilter

org.springframework.security.web.csrf.CsrfFilter

org.springframework.security.web.authentication.logout.LogoutFilter 

org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter 

org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter 

org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter

org.springframework.security.web.savedrequest.RequestCacheAwareFilter

org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter

org.springframework.security.web.authentication.AnonymousAuthenticationFilter 

org.springframework.security.web.session.SessionManagementFilter 

org.springframework.security.web.access.ExceptionTranslationFilter 

org.springframework.security.web.access.intercept.FilterSecurityInterceptor

FilterSecurityInterceptor :

动态实现根据用户访问的url进行权限管理

在动态实现根据访问的url进行权限认证时可以自定义FilterInvocationSecurityMetadataSource实现认证规则的配置(例根据用户请求url获取对应url的角色信息),修改FilterSecurityInterceptor自带MetadataSource,同时自定义AccessDecisionManager ,实现访问决策管理(根据登录用户查询到用户的角色,接着比对用户角色与当前url的角色,一致即可访问),最后在配置类中通过

http.authorizeRequests().withObjectPostProcessor(
	new ObjectPostProcessor<FilterSecurityInterceptor>() {
   
					@Override
					public <O extends FilterSecurityInterceptor> O postProcess(O object) {
   
						object.setSecurityMetadataSource(new CustomerFilterInvocationSecurityMetadataSource());
						object.setAccessDecisionManager(new CustomerAccessDecisionManger());
						return object;
					}
				}

实现根据url动态认证授权。。。。。。

//一个位于底层的针对http安全控制的拦截器
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements
      Filter{
   
      //.......
      //核心方法 doFilter
      public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
   
		FilterInvocation fi = new FilterInvocation(request, response, chain);
		invoke(fi);
	}
		
	 //过滤器链执行   	
      public void invoke(FilterInvocation fi) throws IOException, ServletException {
   
		if ((fi.getRequest() != null)
				&& (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
				&& observeOncePerRequest) {
   
			// filter already applied to this request and user wants us to observe
			// once-per-request handling, so don't re-do security checking
			//进行过滤器链中过滤器的执行
			fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
		}
		else {
   
			// first time this request being called, so perform security checking
			if (fi.getRequest() != null && observeOncePerRequest) {
   
				fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
			}
			//查看之前的filter是否通过
			InterceptorStatusToken token = super.beforeInvocation(fi);

			try {
   
			//调用服务执行filter过滤器
				fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
			}
			finally {
   
				super.finallyInvocation(token);
			}

			super.afterInvocation(token, null);
		}
      } 
 } 
      

UsernamePasswordAuthenticationFilter:

通过默认认证页输入用户名密码后,对/login的post请求做拦截,校验表单数据

//核心方法:
//默认用户名密码认证的url是/login,提交方式是post方式
public UsernamePasswordAuthenticationFilter() {
   
   super(new AntPathRequestMatcher("/login", "POST"));
}

// ~ Methods
// 默认提供的认证机制,默认只是获取到输入的用户名和密码进行比对,没有去查询数据库

public Authentication attemptAuthentication(HttpServletRequest request,
      HttpServletResponse response) throws AuthenticationException {
   
   if (postOnly && !request.getMethod().equals("POST")) {
   
      throw new AuthenticationServiceException(
            "Authentication method not supported: " + request.getMethod());
   }

   String username = obtainUsername(request);
   String password = obtainPassword(request);

   if (username == null) {
   
      username = "";
   }

   if (password == null) {
   
      password = "";
   }

   username = username.trim();

   UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
         username, password);

   // Allow subclasses to set the "details" property
   setDetails(request, authRequest);

   return this.getAuthenticationManager().authenticate(authRequest);
}

核心接口

UserDetailsService

Security中加载用户数据的核心接口,当配置中没有账号密码时,通过实现此接口可以自定义逻辑(连接数据库)控制账号、密码认证。

在我们自定义服务时,实现此接口即可。

public interface UserDetailsService {
   
   // ~ Methods
   // ========================================================================================================

   /**
    * Locates the user based on the username. In the actual implementation, the search
    * may possibly be case sensitive, or case insensitive depending on how the
    * implementation instance is configured. In this case, the <code>UserDetails</code>
    * object that comes back may have a username that is of a different case than what
    * was actually requested..
    *
    * @param
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值