同个人网站 https://www.serendipper-x.cn/,欢迎访问 !
SpringBoot集成Spring Security(二)注册 、密码加密、修改密码
写在前面
Spring Security是一种基于 Spring AOP 和 Servlet 过滤器的安全框架。它提供全面的安全性解决方案,同时在 Web 请求级和方法调用级处理身份确认和授权。
由于最近写的项目用到了这方面知识,这里做一些总结。下面直接看代码
一、创建项目
这里以多模块项目
为例。
多模块项目优点:
帮助项目划分模块,鼓励重用,防止POM变得过于庞大,方便各个模块的构建,而不用每次都构建整个项目,使得针对某个模块的特殊控制更为方便。
二、引入pom依赖
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-test</artifactId><scope>test</scope></dependency>
三、web层
项目最核心的代码
SecurityConfig.java
/*** @author xiao* 使用springsecurity对用户登录、注销以及权限进行控制*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate StudentService studentService;@Autowiredprivate ObjectMapper objectMapper;@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(studentService).passwordEncoder(new BCryptPasswordEncoder());}@Overrideprotected void configure(HttpSecurity http) throws Exception {http
// .authenticationProvider(authenticationProvider()).httpBasic()//未登录时.authenticationEntryPoint((request,response,authException) -> {response.setContentType("application/json;charset=utf-8");response.setStatus(HttpServletResponse.SC_FORBIDDEN);PrintWriter out = response.getWriter();RespBean error = RespBean.error("未登录");String s = new ObjectMapper().writeValueAsString(error);out.write(s);out.flush();out.close();}).and().authorizeRequests().anyRequest().authenticated() //必须授权才能范围.and().formLogin() //使用自带的登录.usernameParameter("username").passwordParameter("password").permitAll()//登录失败,返回json.failureHandler(new AuthenticationFailureHandler() {@Overridepublic void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException exception) throws IOException, ServletException {resp.setContentType("application/json;charset=utf-8");resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);PrintWriter out = resp.getWriter();RespBean respBean = RespBean.error("登录失败!");if (exception instanceof UsernameNotFoundException || exception instanceof BadCredentialsException) {respBean.setMsg("用户名或者密码输入错误,请重新输入!");} else if (exception instanceof DisabledException) {respBean.setMsg("账户被禁用");} else {respBean.setMsg("未知错误");}out.write(objectMapper.writeValueAsString(respBean));out.flush();out.close();}})//登录成功,返回json.successHandler(new AuthenticationSuccessHandler() {@Overridepublic void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.getWriter();Student student = (Student) authentication.getPrincipal();student.setPassword(null);RespBean ok = RespBean.ok("登录成功!", student);String s = new ObjectMapper().writeValueAsString(ok);out.write(s);out.flush();out.close();}}).and().exceptionHandling()//没有权限,返回json.accessDeniedHandler((request,response,ex) -> {response.setContentType("application/json;charset=utf-8");response.setStatus(HttpServletResponse.SC_FORBIDDEN);PrintWriter out = response.getWriter();out.write(new ObjectMapper().writeValueAsString(RespBean.error("权限不足")));out.flush();out.close();}).and().logout()//退出成功,返回json.logoutSuccessHandler(new LogoutSuccessHandler() {@Overridepublic void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.getWriter();out.write(new ObjectMapper().writeValueAsString(RespBean.ok("注销成功!")));out.flush();out.close();}}).permitAll();//开启跨域访问http.cors().disable();//开启模拟请求,比如API POST测试工具的测试,不开启时,API POST为报403错误http.csrf().disable();}@Overridepublic void configure(WebSecurity web) {//对于在header里面增加token等类似情况,放行所有OPTIONS请求。web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");}
}
四、mapper层
mapper下的StudentMapper.java
/*** @author xiao*/
public interface StudentMapper {Student loadUserBySno(String sno);
}
resource下的StudentMapper.xml**
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.jxnu.os.mapper.StudentMapper"><resultMap id="BaseResultMap" type="com.jxnu.os.model.Student"><id column="id" property="id" jdbcType="INTEGER"/><result column="username" property="username" jdbcType="VARCHAR"/><result column="sno" property="sno" jdbcType="VARCHAR"/><result column="s_sex" property="s_sex" jdbcType="CHAR"/><result column="t_id" property="t_id" jdbcType="INTEGER"/><result column="password" property="password" jdbcType="VARCHAR"/></resultMap><select id="loadUserByUsername" resultMap="BaseResultMap">select * from student where username=#{username}</select></mapper>
五、model层
model下的Student.java
注意一定要implements UserDetails
/*** @author xiao* 学生实体类*/
public class Student implements UserDetails {
////学生主键IDprivate Integer id;//学生姓名private String username;//登录密码private String password;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}private Collection<? extends GrantedAuthority> authorities;public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {this.authorities = authorities;}@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return this.authorities;}@Overridepublic String getPassword() {return this.password;}@Overridepublic String getUsername() {return this.username;}@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return true;}
}
六、service层
service下的StudentService.java
/*** @author xiao*/
@Service
public class StudentService implements UserDetailsService {@AutowiredStudentMapper studentMapper;/*** 登录* @param username* @return* @throws UsernameNotFoundException*/@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {Student student = studentMapper.loadUserBySno(username);if (student == null) {throw new UsernameNotFoundException("用户不存在");}return student;}
}