开始
1,只要导入maven坐标就自动起效
2,他会自动的保护你所有的接口
3,登录账户(user)密码(后台生成的那一串东西)
一,自定义登录密码(认证)
第一种方式 : yml
spring:
security:
user:
name: jies
password: 123456
第二种方式:config
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())//BCryptPasswordEncoder--密码加密
.withUser("jies").password(new BCryptPasswordEncoder().encode("123456")).roles("admin")
.and()
.withUser("jies2").password(new BCryptPasswordEncoder().encode("123456")).roles("user");
}
}
还可以
//设置加密格式
@Bean
PasswordEncoder passwordEncoder() {
// return NoOpPasswordEncoder.getInstance();
return new BCryptPasswordEncoder();
}
//存在内存中
@Bean
@Override
protected UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("jies").password(new BCryptPasswordEncoder().encode("123456")).roles("admin").build());
manager.createUser(User.withUsername("jies2").password(new BCryptPasswordEncoder().encode("123456")).roles("user").build());
return manager;
}
二,自定义登录页
还是在SecurityConfig 中配置,注意:不同参数的 configure方法的作用
- 自定义登录
- 失败或成功的跳转
- 注销
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("jies").password(new BCryptPasswordEncoder().encode("123456")).roles("admin")
.and()
.withUser("jies2").password(new BCryptPasswordEncoder().encode("12345")).roles("admin");
}
//web资源
@Override
public void configure(WebSecurity web) throws Exception {
//忽略路径
web.ignoring().antMatchers("/js/**", "/css/**", "/images/**");
}
//自定义登录界面
@Override
protected void configure(HttpSecurity http) throws Exception {
//开启配置
http.authorizeRequests()
//所有请求都要认证才能访问
.anyRequest().authenticated()
.and()
//表单配置
.formLogin()
//登录页面 默认情况下 登录接口和登录页面一样
.loginPage("/login.html")
//配置登录接口
.loginProcessingUrl("/login.html")
//定制login.html的参数名
.usernameParameter("username")
.passwordParameter("password")
//登录成功时跳转
//无论从哪里来都跳转到success --请求转发
// .successForwardUrl("/success")
//默认跳转 第二个参数默认为false。--重定向 如果为true时跟successForwardUrl效果一样
.defaultSuccessUrl("/success")
//失败时跳转
//请求转发
.failureForwardUrl("/failure")
//重定向跳转
// .failureUrl("/failure")
//只放行login,
.permitAll()
//注销
.and()
//注销
.logout()
//更改注销的请求方式
.logoutRequestMatcher(new AntPathRequestMatcher("/logout","POST"))
//注销成功跳转到那个页面
.logoutSuccessUrl("/login.html")
//清除session,默认为true
.invalidateHttpSession(true)
//清除认证信息,默认为true
.clearAuthentication(true)
.and()
.csrf().disable();
}
}
- login.html的method是post,还要有submit
三,前后端分离 JSON交互
首先:
- 有状态登录
典型的设计如 Tomcat 中的 Session。
对外提供的都使用 RESTful 风格的接口
- 服务端不保存任何客户端请求者信息
- 客户端的每次请求必须具备自描述信息,通过这些信息识别客户端身份
简单来说就是完成相应的操作后给前端一个响应
登录成功的回调
//登录成功的回调
//successHandler 的功能十分强大,甚至已经囊括了 defaultSuccessUrl 和 successForwardUrl 的功能
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write(new ObjectMapper().writeValueAsString(authentication));
writer.flush();
writer.close();
}
})
登录失败的回调
//登录失败的回调
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write(new ObjectMapper().writeValueAsString(e.getMessage()));
writer.flush();
writer.close();
}
})
注销成功的回调
//注销成功的回调
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write(new ObjectMapper().writeValueAsString("注销成功"));
writer.flush();
writer.close();
}
})
没有认证时回调
//没有认证时回调
.exceptionHandling()
.authenticationEntryPoint(new AuthenticationEntryPoint() {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write(new ObjectMapper().writeValueAsString("用户还没登录!"));
writer.flush();
writer.close();
}
})
四,授权
权限
- 该方式上级不具备下级的权限,
//自定义登录界面
@Override
protected void configure(HttpSecurity http) throws Exception {
//开启配置
http.authorizeRequests()
//授权,注意顺序
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/user/**").hasRole("user")
//所有请求都要认证才能访问
.anyRequest().authenticated()
角色继承
- 如果需要角色继承,要在配置类中添加
//角色继承
@Bean
RoleHierarchy roleHierarchy() {
RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
hierarchy.setHierarchy("ROLE_admin > ROLE_user");
return hierarchy;
}
更换数据来源
-
用户数据存入数据库
前面的认证第三种方式UserDetailsService有两个实现类
-
接下来看一下存数据进数据库的那个
-
需要将里面的SQL改一下
-
代码如下
@Autowired
DataSource dataSource;
@Bean
@Override
protected UserDetailsService userDetailsService() {
JdbcUserDetailsManager manager = new JdbcUserDetailsManager(dataSource);
if(!manager.userExists("jies")){
manager.createUser(User.withUsername("jies").password(new BCryptPasswordEncoder().encode("123456")).roles("admin").build());
}
if (!manager.userExists("jies2")){
manager.createUser(User.withUsername("jies2").password(new BCryptPasswordEncoder().encode("123456")).roles("user").build());
}
return manager;
}
数据库成功插入数据