根据其他博客以及查询资料,整理实现security安全框架!为此做个记录!
记录一 了解Security
使用SpringSecurity其实刚开始很简单,
1.只需要在pom.xml中引入依赖
//配置SpringSecurity ,使其生效
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2.刚开始我们不需要写一个SecurityConfig 配置类,只需要随便写一个Controller就行
@RestController
public class SecurityController {
@GetMapping("/hello")
public String request(){
return "Hello world,welcome earth!use spring-security success!";
}
}
3..启动SpringBoot项目,我们发现日志里面有这样一段内容
4.此时表示Security生效,默认对项目进行了保护,我们访问该Controller中的接口(http://localhost:8080/hello),会见到如下登录界面(此界面为security框架自带的默认登录界面)
5.我们在这里思考用户名和密码是什么,其实用户名在这里默认为user,密码则是6356ad9a-6e63-4eb9-9def-ba47fdee4cfe(这里的密码是日志里面所提示的Security-password,这里的密码每次在项目启动后都会自动刷新),成功登陆会显示
6.如果我们想要Spring-Security失效,可以在SpringBoot启动类中添加@SpringBootApplication(exclude= {SecurityAutoConfiguration.class})(关闭Security登录验证功能),然后启动项目,就不用通过输入密码和用户名去登录了
@SpringBootApplication(exclude= {SecurityAutoConfiguration.class})
public class SecuritydemoApplication {
public static void main(String[] args) {
SpringApplication.run(SecuritydemoApplication.class, args);
}
}
记录二
1.配置基于内存的角色授权和认证信息
1.1设置SecurityConfig配置类
@Configuration //指明是配置类
@EnableWebSecurity//开启Spring Security的功能
@EnableGlobalMethodSecurity(prePostEnabled=true)
//prePostEnabled属性决定Spring Security在接口前注解是否可用@PreAuthorize,@PostAuthorize等注解,设置为true,会拦截加了这些注解的接口
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/**
* 基于内存的方式,创建三个用户admin/5201314,user/985211,joker/123456789
* */
auth.inMemoryAuthentication()
.withUser("admin")//用户名
.password(passwordEncoder().encode("5201314"))//密码
.roles("ADMIN");//角色
auth.inMemoryAuthentication()
.withUser("user")//用户名
.password(passwordEncoder().encode("985211"))//密码
.roles("USER");//角色
auth.inMemoryAuthentication()
.withUser("joker")//用户名
.password(passwordEncoder().encode("123456789"))//密码
.roles("JOKER");//角色
}
/**
* 指定加密方式
*/
@Bean
public PasswordEncoder passwordEncoder(){
// 使用BCrypt加密密码,通过它我们就能自己设置属于自己想要的密码
return new BCryptPasswordEncoder();
}
}
重新运行项目,这样我们就能通过我所给的任意三个用户中的相应的用户名和密码输入直接登陆
针对指定加密,我们在测试中来演示一下他的作用
@SpringBootTest
class SecuritydemoApplicationTests {
@Test
void contextLoads() {
BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder();
System.out.println( passwordEncoder.encode("5201314"));
System.out.println(passwordEncoder.matches("5201314","$2a$10$rumTk53N1USDuEph86wwCeh3nSEE9coN6RvBRPQ8Nq97Tiy88vO2W"));
System.out.println(passwordEncoder.encode("985211"));
System.out.println(passwordEncoder.matches("985211","$2a$10$a4DkR0NxEQiOO.JxSHSA9.zQfixzULp/qncKcNdXSjXiBaZREn/Oi"));
System.out.println(passwordEncoder.encode("123456789"));
System.out.println(passwordEncoder.matches("123456789","$2a$10$yl/AZ5/SLWcUNAj/u9j8AuvaDJ/OQsTvVr942.IfGTbqgKZpaTFQG"));
System.out.println(passwordEncoder.encode("123456789"));
System.out.println(passwordEncoder.matches("123456789","$2a$10$CJTm7U9iHj3kHguWrnDq3ucNwD6/AVL/n37.q0V6hpzXJQkzLWeD2"));
}
}
从结果中看出,不同的密码,加密不一样,同种密码,字符串加密也不一样,但是通过matchs方法检验匹配,又能够匹配上
1.2在application.properties 中设置用户名和密码
这两种方式设置要分开,只能一方存在,这只是个人理解(可能有错)
2.配置基于数据库的认证信息和角色授权
我们需要:
编写用户实体类
@Data
public class User {
private int id;
private String username;
private String password;
private int age;
private String address;
}
编写userMapper接口确定sql语句通过用户名来查询用户信息
创建 UserDetailsService 的实现类,编写自定义认证逻辑
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//自定义认证逻辑
QueryWrapper<User> queryWrapper = new QueryWrapper<>.eq("username", username);
//查询用户
User user = userMapper.selectOne(queryWrapper);
// 判断用户是否存在
if (user == null) {
throw new UsernameNotFoundException("用户名不存在");
}
return new UserDetailsImpl(user);
}
}
再实现一个UserDetailsImpl
类,实现UserDetails
里面的方法,并且重写
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDetailsImpl implements UserDetails {
private User user;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// 返回拥有的权限
return null;
}
@Override
public String getPassword() {
// 返回密码
return user.getPassword();
}
@Override
public String getUsername() {
// 返回用户名
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
// 返回账户是否未过期
return true;
}
@Override
public boolean isAccountNonLocked() {
// 返回账户是否未锁定
return true;
}
@Override
public boolean isCredentialsNonExpired() {
// 返回凭据是否未过期
return true;
}
@Override
public boolean isEnabled() {
// 返回账户是否可用
return true;
}
}
上述完成后,就可以通过连接数据库来实现认证
根据你在数据库中设定的用户名和密码来进行登录
3自定义表单认证登录
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain t(HttpSecurity httpSecurity) throws Exception {
HttpSecurity and = httpSecurity
//禁用跨站csrf攻击防御
//配置跨站攻击
.csrf()
//禁用跨站攻击
.disable()
//session管理
//配置session
.sessionManagement()
//关闭session
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
//结束session配置
.and()
//配置用户权限
.authorizeRequests()
//通过URL 匹配权限路径, 配置权限
//URL 匹配了 /user/login 这个请求, 则放心
.mvcMatchers("/user/login").permitAll()
//其他请求,必须全部登录,才能访问
.anyRequest().authenticated()
//结束权限配置
.and();
//登录配置表单认证方式
httpSecurity.formLogin()
.loginPage("/login")//自定义登录页面的url
.usernameParameter("username")//设置登录账号参数,与表单参数一致
.passwordParameter("password")//设置登录密码参数,与表单参数一致
// 告诉Spring Security在发送指定路径时处理提交的凭证,默认情况下,将用户重定向回用户来自的页面。登录表单form中action的地址,也就是处理认证请求的路径,
// 只要保持表单中action和HttpSecurity里配置的loginProcessingUrl一致就可以了,也不用自己去处理,它不会将请求传递给Spring MVC和您的控制器,所以我们就不需要自己再去写一个/user/login的控制器接口了
.loginProcessingUrl("/user/login")//配置默认登录入口
.defaultSuccessUrl("/index")//登录成功后默认的跳转页面路径
.and();
//返回鉴权对象
return and.build();
}
遇到不同的情况要随机应变,根据实际情况来进行Security的配置