spring-boot-learning-spring Security
阅读原文时间:2023年07月09日阅读:4

SpringSecurity的简单原理:

一旦启用了Spring Security,Spring IoC容器就会为你创建一个名称为springSecurityFilterChain 的Spring Bean。
它的类型为FilterChainProxy,事实上它也实现了Filter接口, 只是它是一个特殊的拦截器。在Spring Security 操作的
过程中它会提供Servlet 过滤器DelegatingFilterProxy , 这个过滤器会通过Spring Web IoC 容器去获取
Spring Security所自动创建的FilterChainProxy 对象,这个对象上存在一个拦截器列表( List ),列表上存在用户验证
的拦截器、跨站点请求伪造等拦截器,这样它就可以提供多种拦截功能。于是焦点又落到了FilterChainProxy 对象上,通过它
还可以注册Filter ,也就是允许注册自定义的Filter 来实现对应的拦截逻辑,以满足不同的需要。当然,Spring Security
也实现了大部分常用的安全功能,并提供了相应的机制来简化开发者的工作,所以大部分情况下并不需要自定义开发,使用它提供
的机制即可

怎么开启spring security

web工程可以使用@EnableWebSecurity来驱动spring security启动。

非web工程,使用@EnableGlobalAuthentication

实际上,@EnableWebSecurity这个注解上面已经标注了@EnableGlobalAuthentication注解****

WebSecurityConfigurerAdapter中的方法:

/\*\*  
 \* WebSecurityConfigurerAdapter虽然实现了接口WebSecurityConfigurer  
 \* 但是这个实现是空实现来的,不存在任何配置  
 \*  AuthenticationManagerBuilder定义用户,密码,角色。默认不会创建任何用户和  
 \*  密码==有登录页面没有登录用户  
 \*/  
public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigurer<WebSecurity> {

/\*\*  
 \*配置用户签名服务,user-details机制,可以给用户赋予角色  
 \*  
 \* @param auth 签名管理构造器,用于构建用户权限控制  
 \* @throws Exception  
 \*/  
protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
    this.disableLocalConfigureAuthenticationBldr = true;  
}

/\*\*  
 \* 用于配置Filter链  
 \* @param web  
 \* @throws Exception  
 \*/  
public void configure(WebSecurity web) throws Exception {  
}

/\*\*  
 \* 用于配置拦截保护请求,比如什么请求放行,什么请求验证  
 \* HttpSecurity参数方法:指定用户和角色对对应URL的访问权限。  
 \* @param http  
 \* @throws Exception  
 \*/  
protected void configure(HttpSecurity http) throws Exception {  
    this.logger.debug("Using default configure(HttpSecurity). " +  
            "If subclassed this will potentially override subclass configure(HttpSecurity).");  
    ((HttpSecurity)((HttpSecurity)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)  
            http.authorizeRequests().anyRequest()).authenticated().and())  
            .formLogin().and()).httpBasic();  
}

使用内存签名服务

package com.quan.security;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
* springSecurit默认没有任何用户配置,springboot中,如果没有,自动生成一个
* 名称为user,密码通过随机生成,可以在日志中知道。
* 自定义用户签名服务=密码:内存签名服务,数据库签名服务,自定义签名服务
*/
@SpringBootApplication
//@EnableWebSecurity
public class SpringbootsecurityApplication extends WebSecurityConfigurerAdapter {

/\*\*  
 \* spring5后都要求使用密码编码器。  
 \* 11建立密码编码器实例BCryptPasswordEncoder,实现接口PasswordEncoder  
 \*      是单向不可逆的密码加密方式。  
 \* 22inMemoryAuthentication(),这个方法将返回内存保存用户信息的管理配置InMemoryUserDetailsManagerConfigurer  
 \*      启用内存缓存机制保存用户信息  
 \* 33passwordEncoder,设置密码编码器  
 \* 44withUser 返回UserDetailsBuilder用户详情构造器对象  
 \*   用于配置用户信息  
 \* 55password,设置密码,密码设置必须是经过密码编码器加密后的字符串,使用密码登录的时候是用加密前  
 \* 66赋予角色类型。之后通过角色赋予权限  
 \*      备注:role方法是对authorities方法的简写,role给的角色名称实际上还会加上ROLE\_,如下面的源码展示  
 \* 77and方法表示连接,开启另一个用户的注册。  
 \*  
 \* @param auth  
 \* @throws Exception  
 \*/  
@Override  
protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();  
    String p1 = passwordEncoder.encode("hllhll");  
    String p2 = passwordEncoder.encode("HLLHLL");

    //这里是更便捷的方式  

// InMemoryUserDetailsManagerConfigurer userConfig = auth.inMemoryAuthentication().passwordEncoder(passwordEncoder);
// //因为使用了authorities,所以必须加入前缀
// userConfig.withUser("quanadmin")
// .password(p1).authorities("ROLE_USER","ROLE_ADMIN");
//
// userConfig.withUser("quanuser")
// .password(p2).authorities("ROLE_USER");

            auth.inMemoryAuthentication()  
            .passwordEncoder(passwordEncoder)  
            .withUser("quanadmin")  
            .password(p1)  
            .roles("USER","ADMIN")  
            .and()  
            .withUser("quanuser")  
            .password(p2)  
            .roles("USER");  
}

/\*\*InMenoryUserDetailsManagerConfigurer方法  
 \*  public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication() throws Exception {  
 \*         return (InMemoryUserDetailsManagerConfigurer)this.apply(new InMemoryUserDetailsManagerConfigurer());  
 \*     }  
 \*  
 \*/

/\*\*role方法  
 \*   public User.UserBuilder roles(String... roles) {  
 \*             List<GrantedAuthority> authorities = new ArrayList(roles.length);  
 \*             String\[\] var3 = roles;  
 \*             int var4 = roles.length;  
 \*  
 \*             for(int var5 = 0; var5 < var4; ++var5) {  
 \*                 String role = var3\[var5\];  
 \*                 Assert.isTrue(!role.startsWith("ROLE\_"), () -> {  
 \*                     return role + " cannot start with ROLE\_ (it is automatically added)";  
 \*                 });  
 \*                 authorities.add(new SimpleGrantedAuthority("ROLE\_" + role));  
 \*             }  
 \*  
 \*             return this.authorities((Collection)authorities);  
 \*         }  
 \* @param  
 \*/

public static void main(String\[\] args) {  
    SpringApplication.run(SpringbootsecurityApplication.class, args);  
}

}

使用数据库定义用户认证

@SpringBootApplication
//@EnableWebSecurity
public class SpringbootsecurityApplication extends WebSecurityConfigurerAdapter {

@Autowired  
private DataSource dataSource = null;  
String pwdQ = "select user\_name,pwd,available from t\_user where user\_name = ?";  
String roleQ = "select u.user\_name,r.role\_name from t\_user as u, t\_user\_role as ur,t\_role as r " +  
        "where u.id = ur.user\_id and r.id = ur.role\_id  AND u.user\_name = ?";

/\*\*  
 \* 11新建数据库和数据库表以及加入相关数据  
 \* 22通过@Autowire注入数据源,注入数据源之前要加入依赖  
 \*      这里使用jdbc数据源,和mysql-connection-java驱动  
 \* 33重写方法configure(AuthenticationManagerBuilder auth)  
 \* 44准备查询语句 如上面的pwdQ和roleQ  
 \* 55使用AuthenticationManagerBuilder的jdbcAuthentication方法,  
 \*      开启jdbc的方式进行验证服务  
 \* 66passwordEncoder设置密码的编码器。  
 \*      注意:虽然每一次的密码的编码出来的字符串都不一样,但是数据库里面  
 \*           只要存了一次编码之后的字符串,都可以解密  
 \* 77usersByUsernameQuery通过查询语句返回的user pwd 布尔值,可以对用户进行验证了  
 \*      其中布尔值就是available标明用户是否失效  
 \* 88authoritiesByUsernameQuery通过查询语句知道用户的角色,spring security可以根据  
 \*      查询的结果赋予权限。  
 \* @param auth  
 \* @throws Exception  
 \*/  
@Override  
protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();  
    System.out.println(passwordEncoder.encode("123456"));  
    //虽然每一次的密码的编码出来的字符串都不一样,但是数据库里面只要存了一次编码之后的字符串,都可以解密  
    auth.jdbcAuthentication()  
            .passwordEncoder(passwordEncoder)  
            .dataSource(dataSource)  
            .usersByUsernameQuery(pwdQ)  
            .authoritiesByUsernameQuery(roleQ);  
}

public static void main(String\[\] args) {  
    SpringApplication.run(SpringbootsecurityApplication.class, args);  
}  

}

限制请求:

/**
* 限制请求
* 默认WebSecurityConfigurerAdapte有默认的实现configure(HttpSecurity http)
* 默认只要认证成功,做什么都可以
* @param http
* @throws Exception
*/
protected void configure(HttpSecurity http) throws Exception {
logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");

    //authorizeRequests()限定只对签名成功的用户请求  
    //anyRequest() 限定所有请求  
    //authenticated()对所有签名成功的用户允许方法  
    //.formLogin()代表使用默认登录界面  
    //httpBasic()启动http基础认知  
    http.authorizeRequests()  
            .anyRequest()  
            .authenticated()  
            .and()  
            .formLogin()  
            .and()  
            .httpBasic();  
}

自定义:

@Override
protected void configure(HttpSecurity http) throws Exception {
//authorizeRequests表示设置哪些需要签名的请求,并可以将不同请求权限赋予不同角色
http.authorizeRequests()
//antMatchers配置请求路径,hasAnyRole指定角色(默认加前缀ROLE_),两个觉得哪些角色可以访问哪些路径
.antMatchers("/user/welcome").hasAnyRole("ADMIN","USER")
.antMatchers("/admin/**").hasAnyRole("ADMIN")
//anyRequest没有限制任何请求,permitAll表示没有设置访问权限的路径允许全部访问
.anyRequest().permitAll()
//允许匿名访问
.and().anonymous()

            .and().formLogin()

            .and().httpBasic();  
}

EL

/**
* 使用spring表达式设置, spring EL
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()

            .antMatchers("/user/welcome").access("hasRole('USER') or hasRole('ADMIN')")

            .antMatchers("/admin/w1").access("hasAuthority('ROLE\_ADMIN') && isFullyAuthenticated()")

            .antMatchers("/admin/w1").access("hasAuthority('ROLE\_ADMIN')")  
            .and().rememberMe()

            .and().formLogin()

            .and().httpBasic();  
}

------------恢复内容开始------------

SpringSecurity的简单原理:

一旦启用了Spring Security,Spring IoC容器就会为你创建一个名称为springSecurityFilterChain 的Spring Bean。
它的类型为FilterChainProxy,事实上它也实现了Filter接口, 只是它是一个特殊的拦截器。在Spring Security 操作的
过程中它会提供Servlet 过滤器DelegatingFilterProxy , 这个过滤器会通过Spring Web IoC 容器去获取
Spring Security所自动创建的FilterChainProxy 对象,这个对象上存在一个拦截器列表( List ),列表上存在用户验证
的拦截器、跨站点请求伪造等拦截器,这样它就可以提供多种拦截功能。于是焦点又落到了FilterChainProxy 对象上,通过它
还可以注册Filter ,也就是允许注册自定义的Filter 来实现对应的拦截逻辑,以满足不同的需要。当然,Spring Security
也实现了大部分常用的安全功能,并提供了相应的机制来简化开发者的工作,所以大部分情况下并不需要自定义开发,使用它提供
的机制即可

怎么开启spring security

web工程可以使用@EnableWebSecurity来驱动spring security启动。

非web工程,使用@EnableGlobalAuthentication

实际上,@EnableWebSecurity这个注解上面已经标注了@EnableGlobalAuthentication注解****

WebSecurityConfigurerAdapter中的方法:

/\*\*  
 \* WebSecurityConfigurerAdapter虽然实现了接口WebSecurityConfigurer  
 \* 但是这个实现是空实现来的,不存在任何配置  
 \*  AuthenticationManagerBuilder定义用户,密码,角色。默认不会创建任何用户和  
 \*  密码==有登录页面没有登录用户  
 \*/  
public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigurer<WebSecurity> {

/\*\*  
 \*配置用户签名服务,user-details机制,可以给用户赋予角色  
 \*  
 \* @param auth 签名管理构造器,用于构建用户权限控制  
 \* @throws Exception  
 \*/  
protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
    this.disableLocalConfigureAuthenticationBldr = true;  
}

/\*\*  
 \* 用于配置Filter链  
 \* @param web  
 \* @throws Exception  
 \*/  
public void configure(WebSecurity web) throws Exception {  
}

/\*\*  
 \* 用于配置拦截保护请求,比如什么请求放行,什么请求验证  
 \* HttpSecurity参数方法:指定用户和角色对对应URL的访问权限。  
 \* @param http  
 \* @throws Exception  
 \*/  
protected void configure(HttpSecurity http) throws Exception {  
    this.logger.debug("Using default configure(HttpSecurity). " +  
            "If subclassed this will potentially override subclass configure(HttpSecurity).");  
    ((HttpSecurity)((HttpSecurity)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)  
            http.authorizeRequests().anyRequest()).authenticated().and())  
            .formLogin().and()).httpBasic();  
}

使用内存签名服务

package com.quan.security;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
* springSecurit默认没有任何用户配置,springboot中,如果没有,自动生成一个
* 名称为user,密码通过随机生成,可以在日志中知道。
* 自定义用户签名服务=密码:内存签名服务,数据库签名服务,自定义签名服务
*/
@SpringBootApplication
//@EnableWebSecurity
public class SpringbootsecurityApplication extends WebSecurityConfigurerAdapter {

/\*\*  
 \* spring5后都要求使用密码编码器。  
 \* 11建立密码编码器实例BCryptPasswordEncoder,实现接口PasswordEncoder  
 \*      是单向不可逆的密码加密方式。  
 \* 22inMemoryAuthentication(),这个方法将返回内存保存用户信息的管理配置InMemoryUserDetailsManagerConfigurer  
 \*      启用内存缓存机制保存用户信息  
 \* 33passwordEncoder,设置密码编码器  
 \* 44withUser 返回UserDetailsBuilder用户详情构造器对象  
 \*   用于配置用户信息  
 \* 55password,设置密码,密码设置必须是经过密码编码器加密后的字符串,使用密码登录的时候是用加密前  
 \* 66赋予角色类型。之后通过角色赋予权限  
 \*      备注:role方法是对authorities方法的简写,role给的角色名称实际上还会加上ROLE\_,如下面的源码展示  
 \* 77and方法表示连接,开启另一个用户的注册。  
 \*  
 \* @param auth  
 \* @throws Exception  
 \*/  
@Override  
protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();  
    String p1 = passwordEncoder.encode("hllhll");  
    String p2 = passwordEncoder.encode("HLLHLL");

    //这里是更便捷的方式  

// InMemoryUserDetailsManagerConfigurer userConfig = auth.inMemoryAuthentication().passwordEncoder(passwordEncoder);
// //因为使用了authorities,所以必须加入前缀
// userConfig.withUser("quanadmin")
// .password(p1).authorities("ROLE_USER","ROLE_ADMIN");
//
// userConfig.withUser("quanuser")
// .password(p2).authorities("ROLE_USER");

            auth.inMemoryAuthentication()  
            .passwordEncoder(passwordEncoder)  
            .withUser("quanadmin")  
            .password(p1)  
            .roles("USER","ADMIN")  
            .and()  
            .withUser("quanuser")  
            .password(p2)  
            .roles("USER");  
}

/\*\*InMenoryUserDetailsManagerConfigurer方法  
 \*  public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication() throws Exception {  
 \*         return (InMemoryUserDetailsManagerConfigurer)this.apply(new InMemoryUserDetailsManagerConfigurer());  
 \*     }  
 \*  
 \*/

/\*\*role方法  
 \*   public User.UserBuilder roles(String... roles) {  
 \*             List<GrantedAuthority> authorities = new ArrayList(roles.length);  
 \*             String\[\] var3 = roles;  
 \*             int var4 = roles.length;  
 \*  
 \*             for(int var5 = 0; var5 < var4; ++var5) {  
 \*                 String role = var3\[var5\];  
 \*                 Assert.isTrue(!role.startsWith("ROLE\_"), () -> {  
 \*                     return role + " cannot start with ROLE\_ (it is automatically added)";  
 \*                 });  
 \*                 authorities.add(new SimpleGrantedAuthority("ROLE\_" + role));  
 \*             }  
 \*  
 \*             return this.authorities((Collection)authorities);  
 \*         }  
 \* @param  
 \*/

public static void main(String\[\] args) {  
    SpringApplication.run(SpringbootsecurityApplication.class, args);  
}

}

使用数据库定义用户认证

@SpringBootApplication
//@EnableWebSecurity
public class SpringbootsecurityApplication extends WebSecurityConfigurerAdapter {

@Autowired  
private DataSource dataSource = null;  
String pwdQ = "select user\_name,pwd,available from t\_user where user\_name = ?";  
String roleQ = "select u.user\_name,r.role\_name from t\_user as u, t\_user\_role as ur,t\_role as r " +  
        "where u.id = ur.user\_id and r.id = ur.role\_id  AND u.user\_name = ?";

/\*\*  
 \* 11新建数据库和数据库表以及加入相关数据  
 \* 22通过@Autowire注入数据源,注入数据源之前要加入依赖  
 \*      这里使用jdbc数据源,和mysql-connection-java驱动  
 \* 33重写方法configure(AuthenticationManagerBuilder auth)  
 \* 44准备查询语句 如上面的pwdQ和roleQ  
 \* 55使用AuthenticationManagerBuilder的jdbcAuthentication方法,  
 \*      开启jdbc的方式进行验证服务  
 \* 66passwordEncoder设置密码的编码器。  
 \*      注意:虽然每一次的密码的编码出来的字符串都不一样,但是数据库里面  
 \*           只要存了一次编码之后的字符串,都可以解密  
 \* 77usersByUsernameQuery通过查询语句返回的user pwd 布尔值,可以对用户进行验证了  
 \*      其中布尔值就是available标明用户是否失效  
 \* 88authoritiesByUsernameQuery通过查询语句知道用户的角色,spring security可以根据  
 \*      查询的结果赋予权限。  
 \* @param auth  
 \* @throws Exception  
 \*/  
@Override  
protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();  
    System.out.println(passwordEncoder.encode("123456"));  
    //虽然每一次的密码的编码出来的字符串都不一样,但是数据库里面只要存了一次编码之后的字符串,都可以解密  
    auth.jdbcAuthentication()  
            .passwordEncoder(passwordEncoder)  
            .dataSource(dataSource)  
            .usersByUsernameQuery(pwdQ)  
            .authoritiesByUsernameQuery(roleQ);  
}

public static void main(String\[\] args) {  
    SpringApplication.run(SpringbootsecurityApplication.class, args);  
}  

}

限制请求:

/**
* 限制请求
* 默认WebSecurityConfigurerAdapte有默认的实现configure(HttpSecurity http)
* 默认只要认证成功,做什么都可以
* @param http
* @throws Exception
*/
protected void configure(HttpSecurity http) throws Exception {
logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");

    //authorizeRequests()限定只对签名成功的用户请求  
    //anyRequest() 限定所有请求  
    //authenticated()对所有签名成功的用户允许方法  
    //.formLogin()代表使用默认登录界面  
    //httpBasic()启动http基础认知  
    http.authorizeRequests()  
            .anyRequest()  
            .authenticated()  
            .and()  
            .formLogin()  
            .and()  
            .httpBasic();  
}

自定义:

@Override
protected void configure(HttpSecurity http) throws Exception {
//authorizeRequests表示设置哪些需要签名的请求,并可以将不同请求权限赋予不同角色
http.authorizeRequests()
//antMatchers配置请求路径,hasAnyRole指定角色(默认加前缀ROLE_),两个觉得哪些角色可以访问哪些路径
.antMatchers("/user/welcome").hasAnyRole("ADMIN","USER")
.antMatchers("/admin/**").hasAnyRole("ADMIN")
//anyRequest没有限制任何请求,permitAll表示没有设置访问权限的路径允许全部访问
.anyRequest().permitAll()
//允许匿名访问
.and().anonymous()

            .and().formLogin()

            .and().httpBasic();  
}

EL

/**
* 使用spring表达式设置, spring EL
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()

            .antMatchers("/user/welcome").access("hasRole('USER') or hasRole('ADMIN')")

            .antMatchers("/admin/w1").access("hasAuthority('ROLE\_ADMIN') && isFullyAuthenticated()")

            .antMatchers("/admin/w1").access("hasAuthority('ROLE\_ADMIN')")  
            .and().rememberMe()

            .and().formLogin()

            .and().httpBasic();  
}

强制使用https;

/**
* springSecurit默认没有任何用户配置,springboot中,如果没有,自动生成一个
* 名称为user,密码通过随机生成,可以在日志中知道。
* 自定义用户签名服务=密码:内存签名服务,数据库签名服务,自定义签名服务
*/
@SpringBootApplication
@EnableWebSecurity
public class SpringbootsecurityApplication extends WebSecurityConfigurerAdapter {

/\*\*  
 \* 强制使用https  
 \* 实际环境当中,信息需要谨慎的额进行保护,通过https进行加密。  
 \* requiresChannel方法说明使用通道,requiresSecure表示https请求  
 \* requiresInSecure取消安全请求机制  
 \* @param http  
 \* @throws Exception  
 \*/  
@Override  
protected void configure(HttpSecurity http) throws Exception {  
    //设置/admin/\*\*这个通道使用安全渠道,限定为https请求  
    http.requiresChannel().antMatchers("/admin/\*\*").requiresSecure()  
            //设置/user/\*\*这个通道不使用安全渠道  
            .and().requiresChannel().antMatchers("/user/\*\*").requiresInsecure()  
            .and().authorizeRequests().antMatchers("/admin/\*\*").hasAnyRole("ADMIN")  
            .antMatchers("/user/\*\*").hasAnyRole("USER","ADMIN");  
}

//  
    @Override  
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();  
    String p1 = passwordEncoder.encode("hllhll");  
    String p2 = passwordEncoder.encode("HLLHLL");

    auth.inMemoryAuthentication()  
            .passwordEncoder(passwordEncoder)  
            .withUser("quanadmin")  
            .password(p1)  
            .roles("USER","ADMIN")  
            .and()  
            .withUser("quanuser")  
            .password(p2)  
            .roles("USER");  
}

跨站点访问请

<%@ page contentType="text/html;charset=UTF-8" language="java" %> Title

名;

描述;

<%--隐藏的是JSTL表达式 \_csrf对象是Spring提供的,启动CSRF攻击的安全认知功能后, SpringSecurity机制会生成对应的CSRF参数,他的属性parameterName 代表的是名称,token代表的是token值。都会放在form隐藏域当中。 提交的时候,提交到服务器后端,ss会进行验证这个token参数是否有效 --%>

用户认证功能:

1自定义登录界面;

@SpringBootApplication
@EnableWebSecurity
public class Springbootweb17Application extends WebSecurityConfigurerAdapter {

/\*\*  
 \* 自定义登录页面:登录请求连接+记住我  
 \* @param http  
 \* @throws Exception  
 \*/  
@Override  
protected void configure(HttpSecurity http) throws Exception {  

// 访问/admin下的时候需要ADMIN权限
http.authorizeRequests().antMatchers("/admin/**").access("hasRole('ADMIN')")
//开启remember me功能设置token的有效期间,浏览器会使用cookie remember-me-key保存,MD5加密保存
.and().rememberMe().tokenValiditySeconds(86400).key("remember-me-key")
//开启 HTTP Batic功能
.and().httpBasic()
//一旦签名通过后,所有的都可以访问,注意如果不是admin那就不是全部
.and().authorizeRequests().antMatchers("/**").permitAll()
//登入路径,默认登录成功跳转路径为/admin/welcome 会在webmvc配置类进行对应的登录页面设置
.and().formLogin().loginPage("/login/page").defaultSuccessUrl("/login/welcome")
//登出路径,登出成功默认跳转路径/welcome
.and().logout().logoutUrl("/logout/page").logoutSuccessUrl("/logout/welcome");
http.httpBasic().realmName("my-basic-name");
}

@Override  
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();  
    String p1 = passwordEncoder.encode("hllhll");  
    String p2 = passwordEncoder.encode("HLLHLL");

    auth.inMemoryAuthentication()  
            .passwordEncoder(passwordEncoder)  
            .withUser("quanadmin")  
            .password(p1)  
            .roles("USER","ADMIN")  
            .and()  
            .withUser("quanuser")  
            .password(p2)  
            .roles("USER");  
}

public static void main(String\[\] args) {  
    SpringApplication.run(Springbootweb17Application.class, args);  
}

}

进行URL和jsp的映射关系配置;

@Configuration
public class WebConfig implements WebMvcConfigurer {

/\*\*  
 \* 增加映射关系  
 \* @param registry  
 \*/  
@Override  
public void addViewControllers(ViewControllerRegistry registry) {  
    //访问/login/page 映射为页面login.jsp  
    registry.addViewController("login/page").setViewName("login");  
    //访问/logout 映射为logout.jsp  

// registry.addViewController("/logout").setViewName("logout");
//登录成功会跳转到/login/welcome 这个URL,所以这里做一个映射到logint_welcome.jsp
registry.addViewController("/login/welcome").setViewName("login_welcome");
//选择登出的时候回跳转到/logout/welcome,所以这里映射到logout_welcome.jsp
registry.addViewController("/logout/welcome").setViewName("logout_welcome");
}
}

login.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


欢迎来到傻逼无
<%--注意:表单里面的参数名称必须是username 和password --%>

名称:

密码:

记住我:

<%-- 表单中加入隐藏的对应参数就能避免CSRF攻击了,--%>



login_welcome.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

登录成功

加油,L2

<%--登出的时候,也是需要验证csrf的,如果没有这个是退出错误的。--%>



logout_welcome.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

登出

您已经登出系统