SpringSecurity框架入门

1 、Spring Security框架入门

1.1 Spring Security简介

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

1.2 Spring Security入门小Demo

1.2.1 SpringSecurity入门Demo

1.2.1.1 创建工程spring-security-demo1 ,pom.xml内容

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itheima</groupId>
    <artifactId>springsecurity-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>war</packaging>

    <properties>
        <spring.security.version>4.2.4.RELEASE</spring.security.version>
        <servlet-api.version>3.0.1</servlet-api.version>
        <jstl.version>1.2</jstl.version>
        <commons-logging.version>1.2</commons-logging.version>
    </properties>

    <dependencies>
        <!--日志包-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>${commons-logging.version}</version>
        </dependency>

        <!--spring-security-->
        <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>org.springframework.security</groupId>
            <artifactId>spring-security-cas</artifactId>
            <version>${spring.security.version}</version>
        </dependency>

        <!--JSP-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet-api.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>
    </dependencies>

</project>
1.2.1.2 创建web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!--SpringSecurity过滤器-->
    <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>


    <!--指定Spring配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring.xml</param-value>
    </context-param>

    <!--Spring监听-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>
1.2.1.3 创建html和jsp

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
    第一个SpringSecurity应用
</body>
</html>

error.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>异常处理</title>
</head>
<body>
您无权访问该页面
</body>
</html>

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<form name='f' action='/login' method='POST'>
    <table>
        <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
        <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
        <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
    </table>
</form>
</body>
</html>

创建pages/1.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
pages下的jsp
</body>
</html>

创建jsp/1.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
jsp下的jsp
</body>
</html>
1.2.1.4 创建spring配置文件 spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--包扫描-->
    <context:component-scan base-package="com" />
</beans>
1.2.1.5 创建SpringSecurityConfig配置类

该类需要继承WebSecurityConfigurerAdapter,并且该类需要加上@EnableWebSecurity注解,该类里面通常要写3个方法:

忽略某些配置的方法
public void configure(WebSecurity web) throws Exception {}
配置对应地址拦截请求的方法,例如拦截地址、关闭csrf、
protected void configure(HttpSecurity http) throws Exception {}
授权用户,比如创建某些账号,某些账号就可以登录了
protected void configure(AuthenticationManagerBuilder auth) throws Exception {}

实现代码:

@Component
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    /***
     * 忽略安全过滤
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        //忽略相关地址
        web.ignoring().antMatchers("/images/**");
        web.ignoring().antMatchers("/js/**");
        web.ignoring().antMatchers("/login.html");
        web.ignoring().antMatchers("/error.html");
    }


    /***
     * 请求拦截配置
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //拦截规则配置
        http.authorizeRequests()
                .antMatchers("/pages/**").access("hasRole('ADMIN')")    //ADMIN角色可以访问/pages/下的所有文件
                .antMatchers("/jsp/**").access("hasRole('USER')")       //USER角色可以访问/jsp/下的所有文件
                .and().formLogin().loginPage("/login.html").loginProcessingUrl("/login")        //指定登录页和处理登录的地址
                .and().logout().logoutUrl("/logout").invalidateHttpSession(true);               //指定登出页和登出后让session无效

        //关闭CSRF安全策略
        http.csrf().disable();

        //异常处理,例如403
        http.exceptionHandling().accessDeniedPage("/error.html");

        //只允许一个用户登录,如果同一个账户两次登录,那么第一个账户将被踢下线,跳转到登录页面
        http.sessionManagement().maximumSessions(1).expiredUrl("/login.html");
    }


    /***
     * 创建用户并授权
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //创建一个用户存在内存中,账号是admin,密码是123456,角色是ROLE_ADMIN
        auth.inMemoryAuthentication().withUser("admin").password("123456").roles("ADMIN");
        auth.inMemoryAuthentication().withUser("xiaohong").password("123456").roles("USER");
    }
}
1.2.1.6 自定义认证类

上面的账号密码写死了,很多时候我们需要自己写认证类,代码如下:

@Component
public class UserDetailsServiceImpl implements UserDetailsService {

    /***
     * 自定义认证类
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名去数据库中查询用户信息,这里不做演示,模拟已经查询出结果
        String password="123456";   //密码

        //用户授权信息
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));

        return new User(username,password,authorities);
    }
}

修改SpringSecurityConfig配置类

    /***
     * UserDetailsServiceImpl是UserDetailsService的实现类,这里可以直接注入进来
     */
    @Autowired
    private UserDetailsService userDetailsService;

    /***
     * 创建用户并授权
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //创建一个用户存在内存中,账号是admin,密码是123456,角色是ROLE_ADMIN
        //auth.inMemoryAuthentication().withUser("admin").password("123456").roles("ADMIN");
        //auth.inMemoryAuthentication().withUser("xiaohong").password("123456").roles("USER");

        //注册自定义认证类
        auth.userDetailsService(userDetailsService);
    }
posted @ 2021-04-27 11:01  your_棒棒糖  阅读(35)  评论(0编辑  收藏  举报