写点什么

SpringSecurity 入门(一)

作者:Java高工P7
  • 2021 年 11 月 11 日
  • 本文字数:3384 字

    阅读完需:约 11 分钟

/**


  • 返回密码编码器


*/


@Bean


public PasswordEncoder passwordEncoder(){


return new BCryptPasswordEncoder();


}


/**


  • 配置用户账号密码以及角色

  • @param auth

  • @throws Exception


*/


@Override


protected void configure(AuthenticationManagerBuilder auth) throws Exception {


//在内存中创建用户


auth.inMemoryAuthentication()


//账号


.withUser("admin")


//密码,需要加密


.password(new BCryptPasswordEncoder().encode("123"))


//添加角色


.roles("ADMIN","USER")


//创建另一个用户


.and()


.withUser("user")


.password(new BCryptPasswordEncoder().encode("123"))


.roles("USER");


}


/**


  • 配置 web 页面的权限

  • @param http

  • @throws Exception


*/


@Override


protected void configure(HttpSecurity http) throws Exception {


//用户请求授权


http.authorizeRequests()


//指定登录相关的请求,permitAll 是不需要验证


.antMatchers("/login").permitAll()


//指定/user/** 需要 USER 角色


.antMatchers("/user/**").hasRole("USER")


.antMatchers("/admin/**").hasRole("ADMIN")


//其它所有 URL 都需要验证


.anyRequest().authenticated()


.and()


//配置登录 URL 为 login,登录成功后跳转 main


.formLogin().loginPage("/login").defaultSuccessUrl("/main")


.and()


//配置注销 url,注销后到登录页面


.logout().logoutUrl("/logout").logoutSuccessUrl("/login");


}


}


  1. 测试 login,输入上面配置的账号和密码



登录成功



账号密码填写错误



密码处理


==================================================================


SpringSecurity 登录验证使用的密码必须要经过加密处理,这里提供了 PasswordEncoder 接口进行密码加密。


PasswordEncoder 接口提供两个主要方法:


  • String encode(CharSequence rawPassword)


将原始密码加密,返回密文


  • boolean matches(CharSequence rawPassword,String password)


将第一个参数原始密码和第二个参数密文进行匹配,返回是否匹配成功


PasswordEncoder 的常用实现类是:BCryptPasswordEncoder


BCryptPasswordEncoder 是基于 hash 算法的单向加密,可以控制密码强度,默认为 10。


在上面的配置类中,配置了该加密器


@Bean


public PasswordEncoder passwordEncoder(){


return new


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


BCryptPasswordEncoder();


}


做下测试


@SpringBootTest


class SpringSecurityDbDemoApplicationTests {


@Autowired


private PasswordEncoder passwordEncoder;


@Test


void contextLoads() {


for (int i = 0; i < 5; i++) {


String encode = passwordEncoder.encode("123456");


System.out.println("encode:"+encode);


System.out.println("matches:"+passwordEncoder.matches("123456",encode));


}}


}



可以看到同样是对"123456"进行加密,每次得到的密文都不相同,但是每次都可以匹配成功。


不同于另一个常用的安全框架:Shiro,SpringSecurity 不需要给密码单独配置盐,盐是随机生成的,这样密码的安全性更高。


授权控制


==================================================================


在创建用户时,除了账号密码外,还可以添加对应的角色和权限,如:


@Override


protected void configure(AuthenticationManagerBuilder auth) throws Exception {


//在内存中创建用户


auth.inMemoryAuthentication()


//账号


.withUser("admin")


//密码,需要加密


.password(new BCryptPasswordEncoder().encode("123"))


//添加角色


.roles("ADMIN","USER")


//创建另一个用户


.and()


.withUser("user")


.password(new BCryptPasswordEncoder().encode("123"))


//也可以通过 authorities 添加权限和角色,如果是角色需要以 ROLE_开头


.authorities("LIST","ROLE_USER");


}


给指定的 URL 配置角色和权限,这样就可以进行访问控制了


@Override


protected void configure(HttpSecurity http) throws Exception {


//用户请求授权


http.authorizeRequests()


//指定 toLogin 请求,permitAll 不需要验证


.antMatchers("/login").permitAll()


//指定/user/** 需要 USER 角色


.antMatchers("/user/**").hasRole("USER")


.antMatchers("/admin/**").hasRole("ADMIN")


//需要 LIST 权限


.antMatchers("/admin/**").hasAuthority("LIST")


//其它所有 URL 都需要验证


.anyRequest().authenticated()


.and()


//配置登录页面为 login,登录成功后跳转 main


.formLogin().loginPage("/login").defaultSuccessUrl("/main")


.and()


//配置注销 url,注销后到登录页面


.logout().logoutUrl("/logout").logoutSuccessUrl("/login");


}


修改控制器的/main 方法


@RequestMapping("/main")


public String main(Model model){


//读取验证对象


Authentication authentication = SecurityContextHolder.getContext().getAuthentication();


//读取用户


Object principal = authentication.getPrincipal();


//如果是登录用户,则为 org.springframework.security.core.userdetails.User


if(principal instanceof User){


User user = (User) principal;


//读取用户名


model.addAttribute("username",user.getUsername());


//读取所有权限


model.addAttribute("authorities",user.getAuthorities());


}else {


model.addAttribute("username", principal);


}


return "main";


}


修改 main.html


<!DOCTYPE html>


<html lang="en" xmlns:th="http://www.thymeleaf.org">


<head>


<meta charset="UTF-8">


<title>Main</title>


</head>


<body>


<h1 th:text="|Welcome!${username}|">Welcome!</h1>


你的权限有:


<span th:each="auth:${authorities}">


[[${auth}]]


</span>


<p><a href="/admin/admin">管理员页面</a> </p>


<p><a href="/user/user">用户页面</a> </p>


<p><a href="/login">登录页面</a> </p>


<p>


<form th:action="@{/logout}" method="post">


<input type="submit" value="注销">


</form>


</p>


</body>


</html>


用 admin 登录,看到的权限是两个角色:ROLE_ADMIN 和 ROLE_USER,ROLE_是自动添加到角色上的。



用 user 登录



再试一下访问不同的 URL


添加目录和文件:admin/admin.html


<!DOCTYPE html>


<html lang="en" xmlns:th="http://www.thymeleaf.org">


<head>


<meta charset="UTF-8">


<title>Admin</title>


</head>


<body>


<h1 th:text="|Hello!${username},欢迎进入管理员页面|">Admin</h1>


</body>


</html>


user/user.html


<!DOCTYPE html>


<html lang="en" xmlns:th="http://www.thymeleaf.org">


<head>


<meta charset="UTF-8">


<title>User</title>


</head>


<body>


<h1 th:text="|Hello!${username},欢迎进入用户页面|">User</h1>


</body>


</html>


错误页面:error/403.html,这里/error 是 Security 默认的错误地址,添加/error/错误代码.html 后,出现对应错误时会自动跳转到对应页面,403 是权限不足。


<!DOCTYPE html>


<html lang="en" xmlns:th="http://www.thymeleaf.org">


<head>


<meta charset="UTF-8">


<title>403</title>


</head>


<body>


Sorry!!你的权限不足


</body>


</html>


控制器添加方法:


@RequestMapping("/user/user")


public String user(Model model){


Authentication authentication = SecurityContextHolder.getContext().getAuthentication();


Object principal = authentication.getPrincipal();


if(principal instanceof User){


User user = (User) principal;


model.addAttribute("username",user.getUsername());


model.addAttribute("authorities",user.getAuthorities());


}else {


model.addAttribute("username", principal);


}


return "user/user";


}


@RequestMapping("/admin/admin")


public String admin( Model model){


Authentication authentication = SecurityContextHolder.getContext().getAuthentication();


Object principal = authentication.getPrincipal();


if(principal instanceof User){


User user = (User) principal;


model.addAttribute("username",user.getUsername());


model.addAttribute("authorities",user.getAuthorities());


}else {


model.addAttribute("username", principal);


}


return "admin/admin";


}


用 admin 登录后,访问管理员的超链接,出现了权限不足



访问用户超链接正常



admin 登录后只有 ADMIN 和 USER 角色,没有 LIST 权限,所以不能访问/admin/admin,可以修改创建 admin 用户时的授权配置,就可以访问了


//添加角色


// .roles("ADMIN","USER")


//添加 ADMIN、USER 角色和 LIST 权限,如果是角色需要以 ROLE_开头

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
SpringSecurity入门(一)