Spring Security是什么?

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
对于安全控制,我们仅需引入spring-boot-starter-security模块,进行少量的配置,就可实现强大的安全管理(这是百度的,简介了说白了就一个安全框架和shiro一类的东西,提高网站的安全性)。

在我看来就是项目中加入和很多拦截,使得我们不能通过拼项目路径就能够访问系统内部的一些资源。

如何使用的它

1.首先要添加它的Jar包,或者Maven依赖

<properties>
<spring.version>5.0.2.RELEASE</spring.version>
<spring.security.version>5.0.1.RELEASE</spring.security.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

2.要加载核心的配置类,在web.xml配置

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:spring-security.xml</param-value>
  </context-param>
  <!-- 配置监听器 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <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>

springSecurityFilterChain 据说这个东西很重要哈!!!貌似就是注册过滤器的一个代理类。springSecurity中有很多Filter,这个类就负责将其它的类都注册。只要配置这一个类。基本上springSecurity就可以使用了。(一了百了)。

3.编写配置文件spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:security="http://www.springframework.org/schema/security"
       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/security
http://www.springframework.org/schema/security/spring-security.xsd">
    <!-- 配置不过滤的资源(静态资源及登录相关) -->

    <security:http security="none" pattern="/login.jsp" />
    <security:http security="none" pattern="/failer.jsp" />
    <security:http security="none" pattern="/css/**" />
    <security:http security="none" pattern="/img/**" />
    <security:http security="none" pattern="/plugins/**" />
    <security:http auto-config="true" use-expressions="false">
        <!-- 配置资料连接,表示任意路径都需要ROLE_USER权限 -->
        <security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN" />
        <!-- 自定义登陆页面,login-page 自定义登陆页面 authentication-failure-url 用户权限校验失败之
        后才会跳转到这个页面,如果数据库中没有这个用户则不会跳转到这个页面。
        default-target-url 登陆成功后跳转的页面。 注:登陆页面用户名固定 username,密码
        password,action:login -->
        <security:form-login login-page="/login.jsp"
                             login-processing-url="/login.do"
                             authentication-failure-url="/failer.jsp"
                             authentication-success-forward-url="/pages/main.jsp"
                             default-target-url="/index.jsp"

        />
        <!-- 登出, invalidate-session 是否删除session logout-url:登出处理链接 logout-success-
        url:登出成功页面
        注:登出操作 只需要链接到 logout即可登出当前用户 -->
        <security:logout invalidate-session="true" logout-url="/logout.do"
                         logout-success-url="/login.jsp" />
        <!-- 关闭CSRF,默认是开启的 -->
        <security:csrf disabled="true" />
    </security:http>
    <!--授权-->
   <security:authentication-manager>
        <security:authentication-provider user-service-ref="userService">
            <!-- 配置加密的方式
            <security:password-encoder ref="passwordEncoder"/>-->
        </security:authentication-provider>
    </security:authentication-manager>

    <!-- 配置加密类 -->
    <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
</beans>

这个配置文件中有几个重要的地方。
登录
正常情况下,我们是通过登录界面点击提交–>controller–>service(验证密码)–>dao(成功后提交跳转到主页)。
但是在spring-security中是不同的。这里不需要controller。直接通过login.jsp页面请求service在service来实现具体的认证授权。
请求到service 这个过程已经在配置文件中明确的写好了

<security:form-login login-page="/login.jsp"
                             login-processing-url="/login.do"
                             authentication-failure-url="/failer.jsp"
                             authentication-success-forward-url="/pages/main.jsp"
                             default-target-url="/index.jsp"

        />

这里就是登录的页面,失败跳到哪里。成功之后跳到哪里。
当你从login.jsp页面填好用户名:密码:后user-service-ref=“userService”
明确了它会调用userSerivice

<security:authentication-manager>
    <security:authentication-provider user-service-ref="userService">
        <!-- 配置加密的方式
        <security:password-encoder ref="passwordEncoder"/>-->
    </security:authentication-provider>
</security:authentication-manager>

UserService接口

public interface IUserService extends UserDetailsService {
}

实现类

点击登陆后根据配置文件直接调用service 根据用户名向数据库中查找用户信息然后密码校验。
这里spring-security它提供了我们一个User类。
当密码校验成功后我们调用,User的构造方法。
将 用户名,密码,用户拥有的角色添加进去就可以了。
这里就是类的部分内容

public class User implements UserDetails, CredentialsContainer {
    private static final long serialVersionUID = 500L;
    private String password;
    private final String username;
    private final Set<GrantedAuthority> authorities;
    private final boolean accountNonExpired;
    private final boolean accountNonLocked;
    private final boolean credentialsNonExpired;
    private final boolean enabled;

    public User(String username, String password, Collection<? extends GrantedAuthority> authorities) {
        this(username, password, true, true, true, true, authorities);
    }

这个类里面有几个难点,比如User构造方法的参数
第一个用户名,这个没什么说的。
第二个密码,这里是不加密的方式校验。{noop}这个前缀就是不加密的前缀。
第三个:用户的角色拥有的角色。这个参数类型是个集合。
ArrayList list = new ArrayList<>();
将用户所拥有的角色添加到这个集合中,然后去和配置文件中的角色进行对比。

<security:intercept-url pattern="/**" access=“ROLE_USER,ROLE_ADMIN”/>
这个地方就是配置的角色信息。要想访问系统,必须用户要具有这两个角色。否则会进行拦截。

@Service("userService")
@Transactional
public class UserServiceImpl implements IUserService {
   @Autowired
    private IUserDao userDao;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserInfo userInfo=null;
        try {
            userInfo = userDao.findByUsername(username);
        } catch (Exception e) {
            e.printStackTrace();
        }
        User user = new User(userInfo.getUsername(),"{noop}"+userInfo.getPassword(),getRoles(userInfo.getRoles()));
        return user;
    }
    //将角色拼接成合法的
    public List<SimpleGrantedAuthority> getRoles(List<Role> roles){
        ArrayList<SimpleGrantedAuthority> list = new ArrayList<>();
        for(Role r: roles){
            list.add(new SimpleGrantedAuthority("ROLE_"+r));
        }
        return list;
    }
}

这就是它最最最基本的使用
这个东西不简单啊!!!对于我来说太难了。
不过慢慢来把!!!
加油!!!