springboot整合spring security的使用
文章目录
- 1.项目准备
- 2.实现自定义登录
- 失败跳转
- 前后端分离的问题
1.项目准备
pom
这里使用的是springboot2.2.11.RELEASE
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.实现自定义登录
由于他自带了拦截页面 我们想要实现自己的登录表单
这时候 需要有一个继承了WebSecurityConfigurerAdapter
的类
来实现带http参数的configure()
方法
这里要说明一点 如果 写了loginPage()
则不用再写controller里的请求方法了 直接跳转
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//表单提交
http.formLogin()
//提交表单跳转的页面请求 与表单里的action对应
.loginProcessingUrl("/login")
//表单所在的页面
.loginPage("/login.html")
;
}
}
login页面表单
<form action="/login" method="post">
用户名<input type="text" name="username"><br>
密码<input type="text" name="password"><br>
<input type="button" value="登录">
</form>
丑是丑好歹效果有了
我们再新增点内容 实现登录 具体的功能看注释 这个是最精简版的了
最终跳转的方法tomain也要是post请求 这点需要注意
@Override
protected void configure(HttpSecurity http) throws Exception {
//表单提交
http.formLogin()
//提交表单跳转的页面请求 与表单里的action对应
.loginProcessingUrl("/login")
//表单所在的页面
.loginPage("/login.html")
//成功后跳转的地址 传入的不能是网址和是方法请求 且该方法必须是post请求
.successForwardUrl("/tomain");
//授权认证
http.authorizeRequests()
//放行login页面 没有权限下 只能有这个页面被访问
.antMatchers("/login.html").permitAll()
//所以请求都要被验证
.anyRequest().authenticated();
//关闭csrf才能正常被访问
http.csrf().disable();
}
需要一个UserDetailsService
的实现类 里面定义登录名密码
@Service
public class UserServiceImpl implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(!username.equals("bb")){
throw new RuntimeException("用户名不存在");
}
String password=passwordEncoder.encode("123");
return new User(username,password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
首先说一下他的流程
SpringSecruity 会根据前端传过来的用户名 从数据库查询对应加密过的密码
然后再进行解码 与前端查询的密码进行比较 如果相等 则通过
这里为了简化 就不弄数据库了 要明白 password是加密过的 所以还需要用到一个接口实现类
就是 PasswordEncoder
是接口 官方推荐用他的实现类BCryptPasswordEncoder
他主要是提供一些加密解密的功能的
示例
@Test
void contextLoads() {
PasswordEncoder pe=new BCryptPasswordEncoder();
String encode = pe.encode("123");
System.out.println(encode);
//matches 比较方法 第一个参数为原密码 第二个为加密后的密码
System.out.println(pe.matches("123", encode));
}
打印
$2a$10$7eLI1RdHYzVS6OqDBNdSyu4Sm2PBLfqx3jfkVjsUr/NPhDEE1A58e
true
注入的这个类就是起这个作用的
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
最终要返回的User对象 就是前两个参数很明了 第三个参数要传入一个权限
AuthorityUtils.commaSeparatedStringToAuthorityList("admin")
这是自定义的 除了admin 其他名字也是随意
最终用的时候与数据库里的权限统一就好了
所以如果要通过 只有用户名为bb 密码为123才能够跳转到主页面
如图
失败跳转
只需要多一个error页面 和两个配置
失败跳转的请求 注意是post请求 要在controller里写 这里就不上代码了http.formLogin().failureForwardUrl("/toerror");
错误页面也是要有权限访问的http.authorizeRequests().antMatchers("/error.html").permitAll()
前后端分离的问题
对于前后端分离 直接传请求是不行的 需要具体的网址
只需要两个接口实现类就能完成了
AuthenticationSuccessHandler
和 AuthenticationFailureHandler
上代码
//成功跳转 传具体的url就行了
public class MySuccessHandle implements AuthenticationSuccessHandler {
private String url;
public MySuccessHandle(String url) {
this.url = url;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
User user = (User) authentication.getPrincipal();
response.sendRedirect(url);
}
}
//失败跳转
public class MyFailureHandle implements AuthenticationFailureHandler {
private String url;
public MyFailureHandle(String url) {
this.url = url;
}
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
response.sendRedirect(url);
//打印下错误信息
System.out.println(e.getMessage());
}
}
在前面的表单提交后面加 直接用这两个实现类就可以了 当然自动注入更好些
//成功跳转的页面
.successHandler(new MySuccessHandle("/main.html"))
//失败跳转的页面
.failureHandler(new MyFailureHandle("/error.html"));
未完待续…
还没有评论,来说两句吧...