SpringSecurity

1. SpringSecurity简介

截屏2021-12-24 20.29.01

1.1 相关概念

Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。

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

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

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

1.2 特点

  1. 与Spring无缝整合

  2. 全面的权限控制

  3. 专门为web开发而设计

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

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

  4. 重量级


2. 基于注解的开发

  1. 配置类注入bean

注意此时和xml配置文件的不同

//表示当前类是配置类,作用大致相当于以前的Spring-context.xml文件
@Configuration
public class MyAnnotationConfiguration {
    //@Bean注解相当于做了下面的xml标签的
    //<bean id="emp" class="con.xz.entity.Employee">
    @Bean
    public Employee getEmployee() {
        return new Employee();
    }
}
  1. 读取配置文件并测试

AnnotationConfigApplicationContext是此时的IOC容器

public class SpringTest {
    public static void main(String[] args) {
        //以前使用 new ClassPathXmlApplicationContext("")
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyAnnotationConfiguration.class);
        Employee bean = applicationContext.getBean(Employee.class);
        System.out.println(bean);
        applicationContext.close();
    }
}

3. HelloWorld

3.1 SpringMVC准备工作

3.1.1 pom文件

  1. 打包方式war
<packaging>war</packaging>
  1. 加入SpringMVC环境需要的依赖
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.3.20.RELEASE</version>
    </dependency>
    <!-- 引入 Servlet 容器中相关依赖 -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>
    <!-- JSP 页面使用的依赖 -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.1.3-b06</version>
        <scope>provided</scope>
    </dependency>
</dependencies>
  1. maven打包时报错,提示找不到web.xml文件,下面是解决办法,在pom.xml中加入:
<build>
    <finalName>web-app-name</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <webXml>web\WEB-INF\web.xml</webXml>
            </configuration>
        </plugin>
    </plugins>
</build>

3.1.2 SpringMVC配置文件

截屏2021-12-24 21.26.30

<?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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <context:component-scan
            base-package="com.xz"></context:component-scan>

    <bean
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <mvc:annotation-driven></mvc:annotation-driven>
    <mvc:default-servlet-handler />

</beans>

3.1.3 web.xml配置

配置DispatcherServlet

截屏2021-12-24 21.27.56

<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">
    <!-- The front controller of this Spring Web application, responsible for
        handling all application requests -->
    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Map all requests to the DispatcherServlet for handling -->
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

3.1.4 导入例子文件

  1. 后端Java代码

截屏2021-12-24 21.29.58

  1. 前端jsp代码

截屏2021-12-24 21.30.49


3.2 加入SpringSecurity

  1. SpringSecurity依赖
<!-- SpringSecurity 对 Web 应用进行权限管理 -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>4.2.10.RELEASE</version>
</dependency>
<!-- SpringSecurity 配置 -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>4.2.10.RELEASE</version>
</dependency>
<!-- SpringSecurity 标签库 -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>4.2.10.RELEASE</version>
</dependency>

  1. web.xml中加入filter过滤器

截屏2021-12-24 21.27.56

SpringSecurity 使用的是过滤器 Filter 而不是拦截器 Interceptor,意味着 SpringSecurity

能够管理的不仅仅是 SpringMVC 中的 handler 请求,还包含 Web 应用中所有请求。比如: 项目中的静态资源也会被拦截,从而进行权限控制。

<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 标 签 中 必 须 是 springSecurityFilterChain。因为 springSecurityFilterChain 在 IOC 容器中对应真正执行权限 控制的二十几个 Filter,只有叫这个名字才能够加载到这些 Filter。


  1. 加入配置类
//注意这个类一定要放在自动扫描的包下,不然所有的配置都不会生效
//@Configuration//将当前类标记为配置类
@EnableWebSecurity//启用web环境下权限控制的功能
public class WebAppSecurityConfig extends WebSecurityConfigurerAdapter {
  
}

  1. 显示效果

截屏2021-12-25 10.03.14

所有请求都被SpringSecurity拦截,要求登录才可以访问。

静态资源也都被拦截,要求登录。

登录失败有错误提示。

4. SpringSecurity操作实验

4.1 放行首页和静态资源

放行首页和静态资源

在配置类中重写父类的 configure(HttpSecurity security)方法。

原方法:

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)((AuthorizedUrl)http
                    .authorizeRequests().anyRequest())//所有请求都需要认证
                    .authenticated()
                    .and())
                    .formLogin().and())//跳转到表单页面
                    .httpBasic();
}

重写后

@Override
protected void configure(HttpSecurity http) throws Exception {
    //super.configure(http);注释掉将取消父类方法中的默认规则
    //对请求进行授权
    http.authorizeRequests()
            //使用 ANT 风格设置要授权的 URL
            .antMatchers("/layui/**","/index.jsp")
            //允许上面使用 ANT 风格设置的全部请求
            .permitAll()
            .and()
            .authorizeRequests()
            //其他未设置的全部请求
            .anyRequest()
            //需要认证
            .authenticated();
}

总结

第一个是表示需要认真请求。

第二个表示匹配的路径。

第三个表示该路径通行的条件。

如果还有其他需要设置的,加个and()然后再三个步骤走起

效果:未认证的请求会跳转到 403 错误页面。

截屏2021-12-25 10.54.07

4.2 未认证请求跳转到登录页

未认证请求跳转到登录页

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .......
            .and()
            //设置未授权请求跳转到登录页面
            .formLogin()
            //指定登录页
            .loginPage("/index.jsp")
            // 指定提交登录表单的地址,覆盖默认地址
            .loginPage("/do/login.html")
            ;
}

指定登录页前后 SpringSecurity 登录地址变化:

指定前:

/login GET - the login form

/login POST - process the credentials and if valid authenticate the user

/login?error GET - redirect here for failed authentication attempts

/login?logout GET - redirect here after successfully logging out

指定后

/index.jsp GET - the login form

/index.jsp POST - process the credentials and if valid authenticate the user

/index.jsp?error GET - redirect here for failed authentication attempts

/index.jsp?logout GET - redirect here after successfully logging out

4.3 设置登录系统的账号密码

设置登录系统的账号、密码

截屏2021-12-25 11.49.58

4.3.1 页面设置

  1. index.jsp页面设置表单
<form action="${pageContext.request.contextPath }/do/login.html" method="post">
	<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>

_csrf:Cross-site request forgery 跨站请求伪造

/do/login.html:是指定提交登录表单的地址,覆盖loginPage()方法中设置的默认值/index.jsp POST

  1. 账号密码请求参数名

SpringSecurity 默认账号的请求参数名:username

SpringSecurity 默认密码的请求参数名:password

.usernameParameter("loginAcct")       // 定制登录账号的请求参数名
.passwordParameter("userPswd")         // 定制登录密码的请求参数名

4.3.2 后端代码

  1. 设置登录成功后默认前往的页面、定制登录账号密码的请求参数名
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .....
            // loginProcessingUrl()方法指定了登录地址,就会覆盖loginPage()方法中设置的默认值/index.jsp POST
            .loginProcessingUrl("/do/login.html")
            // 定制登录账号的请求参数名
            .usernameParameter("loginAcct")
            // 定制登录密码的请求参数名
            .passwordParameter("userPswd")
            // 登录成功后前往的地址
            .defaultSuccessUrl("/main.html")
            ;
}
  1. 重写另外一个父类的方法,来设置登录系统的账号密码
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    //super.configure(auth);
    auth.inMemoryAuthentication()
            .withUser("admin")
            .password("123123")
            .roles("ADMIN")
            .and()
            .withUser("Zelda")
            .password("Zelda")
            .authorities("SAVE","EDIT")
    ;
}

4.4 退出登录

4.4.1 禁用csrf

如果 CSRF 功能没有禁用,那么退出请求必须是 POST 方式。如果禁用了 CSRF 功能则任何请求方式都可以。

  1. 后端
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            ......
            //禁用csrf
            .csrf()
            .disable()
            //开启退出功能
            .logout()
            //指定退出请求的URL地址
            .logoutUrl("/do/logout.html")
            //退出成功后前往的地址
            .logoutSuccessUrl("/index.jsp")
            ;
}
  1. 前端
<a id="logoutAnchor" href="${pageContext.request.contextPath}/do/logout.html">退出</a>

4.4.2 启用csrf

  1. 前端利用post表单提交,给超链接的DOM对象绑定单击响应函数
<form id="logoutForm" action="${pageContext.request.contextPath }/do/logout.html" method="post">
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
<a id="logoutAnchor" href="">退出</a>
<script type="text/javascript">
    window.onload = function () {
        //给超链接的DOM对象绑定单击响应函数
        document.getElementById("logoutAnchor").onclick = function () {
            // 提交包含csrf参数的表单
            document.getElementById("logoutForm").submit();
            //取消超链接的默认行为
            return false;
        };
    };
</script>
  1. 后端:基本同上,取消禁用csrf
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            ......
            //禁用csrf
            //.csrf()
            //.disable()
            //开启退出功能
            .logout()
            //指定退出请求的URL地址
            .logoutUrl("/do/logout.html")
            //退出成功后前往的地址
            .logoutSuccessUrl("/index.jsp")
            ;
}

4.5 角色权限的访问控制

  1. 给不同的user设定不同的角色roles和权限authorities

.roles(“ADMIN”,“学徒”):设定admin角色为“ADMIN”和“大师”

.authorities(“外门弟子”):设定admin权限为"外门弟子")

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
            .withUser("admin")
            .password("123123")
            .roles("ADMIN","学徒")
            .authorities("外门弟子")
            .and()
            .withUser("Zelda")
            .password("Zelda")
            .authorities("SAVE", "EDIT")
            .roles("大师")
    ;
}
  1. 对不同的页面的权限进行设置
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/layui/**", "/index.jsp")
            .permitAll()
            .antMatchers("/level1/**")
            .hasRole("大师")
            .antMatchers("/level2/**")
            .hasAuthority("外门弟子")
}

对"/level1/**"文件下的读取权限只有role为“大师”才可以访问

注意:SpringSecurity 会在角色字符串前面加“ROLE_”前缀

截屏2021-12-25 17.39.43

之所以要强调这个事情,是因为将来从数据库查询得到的用户信息、角色信息、权限信息需要我们自己手动组装。手动组装时需要我们自己给角色字符串前面加“ROLE_” 前缀。

4.6 自定义403错误页面

403错误页面用no_auth.jsp代替,主要代码如下:

<!-- 内容主体区域 -->
<div style="padding: 15px;">
   <h1>非常抱歉!您没有访问这个功能的权限!(回家照照镜子)</h1>
   <h2>${message }</h2>
</div>

4.6.1 方式一

  1. configure类
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          			......
                .and()
                .exceptionHandling()
                .accessDeniedPage("/to/no/auth/page.html")
    }
  1. controller层
@RequestMapping("/to/no/auth/page.html")
public String toNoAuthPage() {
   return "no_auth";
}

4.6.2 方式二

configure类:利用原生的servlet进行页面跳转

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          			......
                .exceptionHandling()
        .accessDeniedHandler(new AccessDeniedHandler() {
            public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
                httpServletRequest.setAttribute("message",e.getMessage());
                httpServletRequest.getRequestDispatcher("/WEB-INF/views/no_auth.jsp").forward(httpServletRequest,httpServletResponse);
            }
        })
        ;
    }

4.7 remember-me

4.7.1 内存版

configure类:HttpSecurity 对象调用 rememberMe()方法。

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                ......
                //开启remember-me功能
                .rememberMe()
                //定制remember-me名称
								//.rememberMeParameter("rememberMeParam")
                ;
    }

登录表单携带名为 remember-me 的请求参数。具体做法是将登录表单中的checkbox 的 name 设置为 remember-me

<div class="layui-form-item">
   <input type="checkbox" name="remember-me"
      title="记住我"> <a href="forget.html">忘记密码?</a>
</div>

如果不能使用“ remember-me ”作为请求参数名称,可以使用**rememberMeParameter()**方法定制。

原理:

截屏2021-12-26 13.49.50

通过开发者工具看到浏览器端存储了名为 remember-me 的 Cookie。根据这个 Cookie 的 value 在服务器端找到以前登录的 User。而且这个 Cookie 被设置为存储 2 个星期的时间。

截屏2021-12-26 13.56.20

4.7.2 数据库版

为了让服务器重启也不影响记住登录状态,换浏览器访问时,也可以记住用户名和密码,将用户登录状态信息存入数据库。

  1. 连接数据库

加入数据库相关依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.12</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.26</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>4.3.20.RELEASE</version>
</dependency>

配置数据源,这里只用了Spring的jdbcTemplate作为演示

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="username" value="root"></property>
    <property name="password" value="123123123"></property>
    <property name="url"
              value="jdbc:mysql://localhost:3306/security?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=false"></property>
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
</bean>
<!-- jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"></property>
</bean>

创建数据库

CREATE DATABASE `security` CHARACTER SET utf8;
  1. 在 WebAppSecurityConfig 类中注入数据源
@Autowired
private DataSource dataSource;
  1. 启用令牌仓库功能

configure类:

  1. 创建JdbcTokenRepositoryImpl对象,并加入数据源
  2. http.authorizeRequests()中开启remember-me功能,并加入JdbcTokenRepositoryImpl对象
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        http.authorizeRequests()
               .......
                //开启remember-me功能
                .rememberMe()
                //定制remember-me名称
                //.rememberMeParameter("rememberMeParam")
                .tokenRepository(jdbcTokenRepository)
        ;
    }

注意:需要进入 JdbcTokenRepositoryImpl 类中找到创建 persistent_logins 表的 SQL 语句创建

这里的表名和表内容必须如下:

CREATE TABLE persistent_logins ( 
    username VARCHAR (64) NOT NULL, 
    series VARCHAR (64) PRIMARY KEY, 
    token VARCHAR (64) NOT NULL, 
    last_used TIMESTAMP NOT NULL
);

在登陆后会将用户储存在这个表中,进行持久化操作。此后在其他浏览器或重启服务器后就会remember-me

4.8 查询数据库完成认证

  1. 实现接口UserDetailsService的loadUserByUsername方法
@Service
public class MyUserDetailsService implements UserDetailsService {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        //1.使用 SQL 语句根据用户名查询用户对象
        String sql ="SELECT id,loginacct,userpswd,username,email FROM t_admin WHERE loginacct=?;";
        Map<String, Object> resultMap = jdbcTemplate.queryForMap(sql, s);
        String loginacct = resultMap.get("loginacct").toString();
        String userpswd = resultMap.get("userpswd").toString();
        //2.给Admin设置角色权限信息:方式一
        List<GrantedAuthority> list = AuthorityUtils.createAuthorityList("ADMIN", "ROLE_学徒");
        // 2.给Admin设置角色权限信息:方式二
//        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
//        authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
//        authorities.add(new SimpleGrantedAuthority("UPDATE"));

        // 3.把admin对象和authorities封装到UserDetails中
        User user = new User(loginacct, userpswd, list);
        return user;
    }
}

这里分成三个步骤:查询用户和密码、用list设定权限信息、将把admin对象和authorities封装到UserDetails中并返回

  1. 使用自定义UserDetailsService完成登录
    @Autowired
    private MyUserDetailsService myUserDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService);
    }

“ROLE_”前缀问题

截屏2021-12-26 20.22.04

在自定义的UserDetailsService 中 , 使org.springframework.security.core.authority.AuthorityUtils.createAuthorityList(String…) 工具方法获取创建 SimpleGrantedAuthority 对象添加角色时需要手动在角色名称前 加“ROLE_”前缀。

4.9 应用自定义密码加密规则

4.9.1 MD5加密

  1. 自定义类实现 org.springframework.security.crypto.password.PasswordEncoder(使用没有过时的)接口。

encode()方法对明文进行加密。

matches()方法对明文加密后和密文进行比较。

@Component
public class MyPasswordEncoder implements PasswordEncoder {

    public String encode(CharSequence charSequence) {
        return md5(charSequence.toString());
    }

    public boolean matches(CharSequence charSequence, String s) {
        return Objects.equals(encode(charSequence),s);
    }

    /*
     *对明文字符串进行md5加密
     * */
    private String md5(String source) {
        // 1.判断source是否有效
        if (source == null || source.length() == 0) {
            // 2.如果不是有效字符串抛出异常
            throw new RuntimeException();
        }
        try {
            // 3.获取MessageDigest对象
            String algorithm = "md5";
            MessageDigest messageDisgest = MessageDigest.getInstance(algorithm);
            // 4.获取明文字符串对应的字节数组
            byte[] input = source.getBytes();
            // 5.执行加密
            byte[] output = messageDisgest.digest(input);
            // 6.创建BigInteger对象
            int signum = 1;
            BigInteger bigInteger = new BigInteger(signum, output);
            // 7.按照16进制将BigInteger的值转换为字符串
            int radix = 16;
            String encoded = bigInteger.toString(radix).toUpperCase();
            return encoded;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
}
  1. 注入并调用密码加密规则

在WebAppSecurityConfig extends WebSecurityConfigurerAdapter类中

    @Autowired
    private MyPasswordEncoder myPasswordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService).passwordEncoder(myPasswordEncoder);
    }

4.9.2 带盐值的加密

SpringSecurity 提供的 BCryptPasswordEncoder 加密规则。

BCryptPasswordEncoder 创建对象后代替自定义 passwordEncoder 对象即可。 BCryptPasswordEncoder 在加密时通过加入随机盐值让每一次的加密结果都不同。能够 避免密码的明文被猜到。

而在对明文和密文进行比较时,BCryptPasswordEncoder 会在密文的固定位置取出 盐值,重新进行加密。

截屏2021-12-26 22.12.38

如下是BCryptPasswordEncoder测试:

public static void main(String[] args) {
    BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
    String encode = bCryptPasswordEncoder.encode("123");
    System.out.println(encode);
    //"123"加密后的密码
    //$2a$10$PQgV9JqgvSnV/lqoyl/lJ.W6kKoZ47r3RI4gCUqOy/zztsrWRvksq
    //$2a$10$CYeHPjoyBQ3.KGe0RlpQPeezMRxg8T8.0iSfojrLjw2j7oRe7ueoq
    //$2a$10$2IU5rcg72ntviPnscApVXubNdlwI6dwq.cJ.2pOYCSvXuO96a3MOe
    //$2a$10$hFDJx7G3IiqzqpvKTxmLQug82HHWY3WdX6CO84sbylFgr2R9WapWK
    boolean matches = bCryptPasswordEncoder.matches("123", "$2a$10$CYeHPjoyBQ3.KGe0RlpQPeezMRxg8T8.0iSfojrLjw2j7oRe7ueoq");
    System.out.println(matches);
}

加入到SpringSecurity:

  1. 为了能在IOC容器中自动注入BCryptPasswordEncoder,需要Import
@Import(org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder.class)
  1. 同4.9.1注入BCryptPasswordEncoder,并将自己写的加密方法换成bCryptPasswordEncoder
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService).passwordEncoder(bCryptPasswordEncoder);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值