赞
踩
引入SpringSecurity依赖
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-security</artifactId>
- </dependency>
启动SpringBoot项目后
控制台 会打印
Using generated security password: 30abfb1f-36e1-446a-a79b-f70024f589ab
这就是 Spring Security 为默认用户 user 生成的临时密码,是一个 UUID 字符串。
接下来我们去访问任何接口,就可以看到自动重定向到登录页面了:
在 Spring Security 中,默认的登录页面和登录接口,都是
/login
,只不过一个是 get 请求(登录页面),另一个是 post 请求(登录接口)。
密码为什么说是一个UUID呢?
在 自动化配置类 UserDetailsServiceAutoConfiguration 类中
- private String getOrDeducePassword(User user, PasswordEncoder encoder) {
- String password = user.getPassword();
- if (user.isPasswordGenerated()) {
- logger.info(String.format("%n%nUsing generated security password: %s%n", user.getPassword()));
- }
-
- return encoder == null && !PASSWORD_ALGORITHM_PATTERN.matcher(password).matches() ? "{noop}" + password : password;
- }
控制台中UUID密码的打印条件为 user.isPasswordGenerated() 为true 时
- //
- // Source code recreated from a .class file by IntelliJ IDEA
- // (powered by Fernflower decompiler)
- //
-
- package org.springframework.boot.autoconfigure.security;
-
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Set;
- import java.util.UUID;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.boot.web.servlet.DispatcherType;
- import org.springframework.util.StringUtils;
-
- @ConfigurationProperties(
- prefix = "spring.security"
- )
- public class SecurityProperties {
- public static final int BASIC_AUTH_ORDER = 2147483642;
- public static final int IGNORED_ORDER = -2147483648;
- public static final int DEFAULT_FILTER_ORDER = -100;
- private final SecurityProperties.Filter filter = new SecurityProperties.Filter();
- private final SecurityProperties.User user = new SecurityProperties.User();
-
- public SecurityProperties() {
- }
-
- public SecurityProperties.User getUser() {
- return this.user;
- }
-
- public SecurityProperties.Filter getFilter() {
- return this.filter;
- }
-
- public static class User {
- private String name = "user";
- private String password = UUID.randomUUID().toString();
- private List<String> roles = new ArrayList();
- private boolean passwordGenerated = true;
-
- public User() {
- }
-
- public String getName() {
- return this.name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getPassword() {
- return this.password;
- }
-
- public void setPassword(String password) {
- if (StringUtils.hasLength(password)) {
- this.passwordGenerated = false;
- this.password = password;
- }
- }
-
- public List<String> getRoles() {
- return this.roles;
- }
-
- public void setRoles(List<String> roles) {
- this.roles = new ArrayList(roles);
- }
-
- public boolean isPasswordGenerated() {
- return this.passwordGenerated;
- }
- }
-
- public static class Filter {
- private int order = -100;
- private Set<DispatcherType> dispatcherTypes;
-
- public Filter() {
- this.dispatcherTypes = new HashSet(Arrays.asList(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST));
- }
-
- public int getOrder() {
- return this.order;
- }
-
- public void setOrder(int order) {
- this.order = order;
- }
-
- public Set<DispatcherType> getDispatcherTypes() {
- return this.dispatcherTypes;
- }
-
- public void setDispatcherTypes(Set<DispatcherType> dispatcherTypes) {
- this.dispatcherTypes = dispatcherTypes;
- }
- }
- }
从 SecurityProperties 中我们可以看出默认用户名为user ,密码为每次启动都不一致的UUID。 同时 passwordGenerated = true 说明密码默认是在控制台打印的。
由于每次启动我们都要有一个新的 UUID密码 因此需要我们自己进行用户名密码配置,去覆盖默认配置。两种方法如下。
第一种方法 :下面是配置的两个步骤。
第一步 创建 SecurityProperties 类
- /**
- * @author ShawnWang
- * @create 2021-07-05 20:38
- *
- * 进行Spring Boot配置文件部署时,发出警告Spring Boot Configuration Annotation Processor not configured,但是不影响运行。
- *
- * 解决办法 引入下面依赖
- * <dependency>
- * <groupId>org.springframework.boot</groupId>
- * <artifactId>spring-boot-configuration-processor</artifactId>
- * <optional>true</optional>
- * </dependency>
- *
- */
- @ConfigurationProperties(prefix = "spring.security")
- public class SecurityProperties {
-
- }
第二步 在 application.yml 中配置
- spring:
- security:
- user:
- name: shawnwang
- password: 123
在 yml 中定义的用户名密码最终是通过 set 方法注入到属性中。 重启项目即可使用自定义用户名和密码进行授权登录了。
第二种方法:
在配置类中配置,我们就要指定 PasswordEncoder 。
Spring Security 提供了多种密码加密方案,官方推荐使用 BCryptPasswordEncoder,BCryptPasswordEncoder 使用 BCrypt 强哈希函数,开发者在使用时可以选择提供 strength 和 SecureRandom 实例。strength 越大,密钥的迭代次数越多,密钥迭代次数为 2^strength。strength 取值在 4~31 之间,默认为 10。
不同于 Shiro 中需要自己处理密码加盐,在 Spring Security 中,BCryptPasswordEncoder 就自带了盐,处理起来非常方便。
而 BCryptPasswordEncoder 就是 PasswordEncoder 接口的实现类。
- //
- // Source code recreated from a .class file by IntelliJ IDEA
- // (powered by Fernflower decompiler)
- //
-
- package org.springframework.security.crypto.password;
-
- public interface PasswordEncoder {
- String encode(CharSequence var1);
-
- boolean matches(CharSequence var1, String var2);
-
- default boolean upgradeEncoding(String encodedPassword) {
- return false;
- }
- }
具体配置
创建 SecurityConfig 继承 WebSecurityConfigurerAdapter 重写里边的 configure 方法。
- /**
- * @author ShawnWang
- * @create 2021-07-06 8:59
- */
- @Configuration
- public class SecurityConfig extends WebSecurityConfigurerAdapter {
-
- @Bean
- PasswordEncoder passwordEncoder(){
- // return NoOpPasswordEncoder.getInstance();
- return new BCryptPasswordEncoder();
- }
-
- @Override
- protected void configure(AuthenticationManagerBuilder auth) throws Exception {
- auth.inMemoryAuthentication()
- .withUser("shawn")
- .password("123").roles("admin");
- }
-
- @Override
- public void configure(WebSecurity web) {
- //用来配置忽略的url地址 一般为静态文件
- web.ignoring().antMatchers("/js/**", "/css/**","/images/**");
- }
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http.authorizeRequests()
- .anyRequest().authenticated()
- .and()
- .formLogin()
- //自定义登录页 不用自带的登录页
- .loginPage("/login.html")
- //指定登录接口地址
- .loginProcessingUrl("/doLogin")
- //和successForwardUrl 两者只能存在其一 .defaultSuccessUrl("/index",true)同.successForwardUrl("/index")作用一致
- //两种情况 一、你在浏览器输入登录地址 登录成功后跳转到/index,输入其他如http://localhost/hello 登录成功后就跳转到/hello
- .defaultSuccessUrl("/index")
- //successForwardUrl 无论输入什么地址 登陆成功后都会跳转到/index
- .successForwardUrl("/index")
- //表示登录相关的页面/接口不要被拦截
- .permitAll()
- .and()
- //默认注销登录URL是/logout 可以通过logoutUrl方法来修改默认的注销URL
- .logout()
- .logoutUrl("/logout2")
-
- .and()
- .csrf().disable();
- }
-
-
- }
重写它的 configure(WebSecurity web) 和 configure(HttpSecurity http) 方法 代码段在上面
<http>
,HttpSecurity 提供的配置方法 都对应了该标签。<intercept-url>
。<formlogin>
。只需将login.html放到 resources -> static 下即可
html中
<!-- action="/doLogin" 时请求自定义的接口 为/login.html时为自定义的页面 --> <!-- <form action="/doLogin" method="post">-->
在登录成功之后,我们就要分情况处理了,大体上来说,无非就是分为两种情况:
两种情况的处理方式不一样。
(前后端不分登录 如下)
在 Spring Security 中,和登录成功重定向 URL 相关的方法有两个:
这两个咋看没什么区别,实际上内藏乾坤。
首先我们在配置的时候,defaultSuccessUrl 和 successForwardUrl 只需要配置一个即可,具体配置哪个,则要看你的需求,两个的区别如下:
/index
,此时分两种情况,如果你是直接在浏览器中输入的登录地址,登录成功后,就直接跳转到 /index
,如果你是在浏览器中输入了其他地址,例如 http://xxxx/hello
,结果因为没有登录,又重定向到登录页面,此时登录成功后,就不会来到 /index
,而是来到 /hello
页面。/index
,你在浏览器地址栏输入 http://xxxx/hello,结果因为没有登录,重定向到登录页面,当你登录成功之后,就会服务端跳转到 /index
页面;或者你直接就在浏览器输入了登录页面地址,登录成功后也是来到 /index
。与登录成功相似,登录失败也是有两个方法:
这两个方法在设置的时候也是设置一个即可。failureForwardUrl 是登录失败之后会发生服务端跳转,failureUrl 则在登录失败之后,会发生重定向。
- .and()
- //默认注销登录URL是/logout 可以通过logoutUrl方法来修改默认的注销URL
- .logout()
- .logoutUrl("/logout2")
- .logoutRequestMatcher(new AntPathRequestMatcher("/logout2","POST"))
- .logoutSuccessUrl("/successIndex")
- .deleteCookies()
- .clearAuthentication(true)
- .invalidateHttpSession(true)
- .permitAll()
- .and()
注销登录的配置:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。