spring-security安全框架的使用

定义

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,充分利用了spirngIOC与AOP功能,为应用系统提供声明式(可以使用注解)的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

Spring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架。

作用

Spring Security是一个安全框架,只要用来做权限的校验,提到权限校验,就要引出两个关键词——认证和授权。

认证和授权

  1. 认证:认证就是系统提供的用于验证用户身份的功能,一般在登录的时候就在进行认证。用于判断当前登录的用户的角色信息。
  2. 授权:在用户认证登录成功后需要为用户授权,权限一般根据当前登录的用户从数据库中查询其对应的权限,从而授予;授予权限其实就是指定用户能够进行哪些操作,而没有权限的操作就不能进行。如该用户没有修改权限,那么就不能执行修改操作。

原理

在这里插入图片描述

可以看到,在spring security内部其实就是通过一个过滤器链来实现认证流程的,比如说,UsernamePasswordAuthenticationFilter过滤器就是拦截我们通过表单提交接口提交的用户名和密码,如果是基本提交,就会被BasicAuthenticationFilter过滤器所拦截,最后的橙色FilterSecurityInterceptor过滤器首先判断我们当前请求的url是否需要认证,如果需要认证,那么就看当前请求是否已经认证,是的话就放行到我们要访问的接口,否则重定向到认证页面。

使用

  1. web.xml文件中配置spring security过滤器链,并设置要拦截的请求

    <!--配置spring-security过滤器链(委派过滤器)-->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <!--配置要拦截的请求地址-->
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <!--拦截所有请求-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!--配置servlet-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--加载springMVC映射文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:spring-mvc.xml,classpath*:spring-security.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
  2. 创建spring-security.xml文件,在其中主要配置Spring Security的拦截规则和认证管理器

    spring-security.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:security="http://www.springframework.org/schema/security"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
    
        <!--指定不需要权限校验的资源,pattern:指定资源的请求路径-->
        <security:http security="none" pattern="/login.html"/>
        <security:http security="none" pattern="/css/**"/>
        <security:http security="none" pattern="/img/**"/>
        <security:http security="none" pattern="/js/**"/>
        <security:http security="none" pattern="/plugins/**"/>
    
        <!--
            配置要进行拦截后权限校验的资源请求
            auto-config:自动配置某些配置项,并且会提供一个默认的登录界面(可以自己指定一个登陆界面),需要用户进行登录认证
            use-expressions="true":是否使用权限校验表达式
        -->
        <security:http auto-config="true" use-expressions="true">
    
            <!--
                配置拦截请求地址与校验权限
                pattern:要拦截的请求路径
                access:指定需要的权限,当认证用户时,由相应的权限才能访问pattern配置的页面
                        isAuthenticated():判断是否已认证(登录成功就是通过认证)
            -->
            <security:intercept-url pattern="/pages/**" access="isAuthenticated()"/>
            <!--
                自定义登录页面表单
                login-page:自定义登录页面的地址
                username-parameter:表单中用户名输入框的name属性值,要和此处对应
                password-parameter:表单中密码输入框的name属性值,要和此处对应
                default-target-url:登录认证成功后的跳转页面链接
                authentication-failure-url:认证失败后跳转的页面链接
                login-processing-url:表单提交链接
            -->
            <security:form-login login-page="/login.html"
                                 username-parameter="username"
                                 password-parameter="password"
                                 default-target-url="/pages/main.html"
                                 authentication-failure-url="/login.html"
                                 login-processing-url="/login"/>
    
            <!--
                配置登出(退出)
                logout-url:登出地址
                logout-success-url:成功登出后的跳转地址
                invalidate-session:是否销毁session,因为spring-security底层就是使用session来存储登录用户的信息的。
            -->
            <security:logout logout-url="/logout" logout-success-url="/login.html" invalidate-session="true"/>
            <!--如果需要使用自定义的登录页面,需要禁用csrf过滤器-->
            <security:csrf disabled="true"/>
    
            <!--设置通过iframe访问的页面可以访问,默认为不可访问-->
            <security:headers>
                <!--
                    policy:策略方针
                    SAMEORIGIN:同源请求
                    ALLOW-FROM:允许
                    DEDY:拒绝
                -->
                <security:frame-options policy="SAMEORIGIN"/>
            </security:headers>
        </security:http>
    
    
        <!--配置密码加密bean-->
        <bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
    
        <!--配置权限认证管理器-->
        <security:authentication-manager>
            <!--
                配置权限认证提供者
                user-service-ref:引用注入到spring容器的bean,这个bean要实现UserDetailsService接口
            -->
            <security:authentication-provider user-service-ref="springSecurityService">
                <!--配置密码加密策略,因为保存到数据库中的密码是加密后的,所以在对比的时候,获取的登录时的密码需要加密后在做对比-->
                <security:password-encoder ref="bCryptPasswordEncoder"/>
            </security:authentication-provider>
        </security:authentication-manager>
    
        <!--开启注解权限控制方式-->
        <security:global-method-security pre-post-annotations="enabled"/>
    </beans>
    

    注意,除了配置spring-security.xml文件外,还要配置spring的配置文件,因为后面的类需要配置到spring容器中。

  3. 自定义java类,需要实现UserDetailsService接口

    SpringSecurityService.java类名随意

    /**
     * 认证用户及授权
     */
    @Component
    public class SpringSecurityService implements UserDetailsService {
    
        @Reference
        private UserService userService;
    
        /**
         * 授权方法,该方法会在用户进行登录认证的时候被spring-security自动执行
         *
         * @param username
         * @return
         * @throws UsernameNotFoundException
         */
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //根据用户名查询用户数据
            User user = userService.findByUserName(username);
            //判断用户是否存在
            if (user == null) {
                return null;
            }
            //根据用户id,查询该用户拥有的所有角色与权限
            List<String> list = userService.findAllRoleAndPermissionByUserId(user.getId());
            //给用户授权
            //创建权限集合
            List<GrantedAuthority> grantedAuthorityList = new ArrayList();
            //将从数据库中查询到的权限封装到集合中
            list.forEach(element -> {
                grantedAuthorityList.add(new SimpleGrantedAuthority(element));
            });
    
            //使用spring-security提供的user类,完成用户的认证和权限(在这里会完成密码的校验,获取用户在登录时提交的密码与数据库中保存的密码做对比,如果密码相同则完成认证,并赋予当前用户权限)
            org.springframework.security.core.userdetails.User securityUser = new
                    org.springframework.security.core.userdetails.User(username,
                    user.getPassword(), grantedAuthorityList);
    
            return securityUser;
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值