一、介绍
BCrypt算法是目前使用比较多的加密、解密算法。SpringSecurity中提供了BCryptPasswordEncoder类
优点:
自己写的加密算法或使用MD5,同一密码生成的Hash值一样。而BCrypt算法每次加密生成的Hash值不同。
二、具体使用
1)在SpringSecurity的配置类中,使用@Configuration和@Bean的组合来创建BCryptPasswordEncoder Bean
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
MyUserDetailService myUserDetailService;
//Control+O 打开重写方法
//定制请求的授权规则
@Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("进入到 MySecurityConfig的configure 方法中");
//super.configure(http);
/*Spring Security 的默认构造器:
通过调用authorizeRequests()和 anyRequest().authenticated()就会要求所有进入应用的HTTP请求都要进行认证
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().and()
.httpBasic(); //弹出一个输入用户名、密码的登录框
“/shop/hello” 和 “/shop/order” 这两个路径必须进过认证,并且 “/shop/order” 必须是 post 请求的方式.
对于其他的请求,我们都是 .anyRequest().permitAll() ;都放行.
http.authorizeRequests()
.antMatchers("/shop/hello").authenticated()
.antMatchers(HttpMethod.POST,"/shop/order").authenticated()
.anyRequest().permitAll();
antMatchers()方法所使用的路径可能会包括Ant风格的通配符,而regexMatchers()方法则能够接受正则表达式来定义请求路径。
*/
// 基于token,所以不需要session
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// /**代表所有的请求
http.authorizeRequests()//方法表示开启了认证规则配置;定义哪些url需要保护,哪些url不需要保护;
.antMatchers("/api/**").permitAll()//定义不需要认证就可以访问
// .antMatchers("/session/**").permitAll()//定义不需要认证就可以访问
// .antMatchers("/component/**").hasAuthority("ROLE_ADMIN")
.antMatchers("/home/**").hasAnyAuthority("ROLE_DEV_APPLICATION","ROLE_ADMIN","ROLE_DEV_TERMINAL_IOS")
.anyRequest().authenticated();其他的路径都是登录后即可访问
// .and().formLogin().loginPage("/")
//
// //在successHandler中,使用response返回登录成功的json即可,切记不可以使用defaultSuccessUrl,defaultSuccessUrl是只登录成功后重定向的页面,failureHandler也是由于相同的原因不使用failureUrl。
// .loginProcessingUrl("/login").successHandler(
// new AuthenticationSuccessHandler(){
// @Override
// public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
// System.out.println(authentication.getDetails());
// httpServletResponse.setContentType("application/json;charset=utf-8");
// PrintWriter out = httpServletResponse.getWriter();
// out.write("{\"status\":\"success\",\"msg\":\"登录成功\"}");
// out.flush();
// out.close();
// }
// }).failureHandler(
// new AuthenticationFailureHandler() {
// @Override
// public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
// httpServletResponse.setContentType("application/json;charset=utf-8");
// PrintWriter out = httpServletResponse.getWriter();
// out.write("{\"status\":\"failed\",\"msg\":\"登录失败\"}");
// out.flush();
// out.close();
// }
// });
//http.logout()开启自动配置的注销功能
//1) 访问/logout 表示用户注销,清空session
//2) 注销成功会返回/login?logout 页面
//3) logoutSuccessfulUrl 改变2)的设置
http.logout().logoutSuccessUrl("/login");
http.sessionManagement().invalidSessionUrl("/login");
http.rememberMe().rememberMeParameter("remember");
// .usernameParameter("username").passwordParameter("password").defaultSuccessUrl("/");定义当需要用户登录时候,转到的登录页面
// http.headers().frameOptions().disable();
// .antMatchers("/level2/**").hasRole("VIP2")
// .antMatchers("/level3/**").hasRole("VIP3");
//开启自动配置的登录功能。如果没有登录,没有权限就会来到登录页面
//1:/login来到登录页
//2:重定向/login?error表示登录失败
//3:更多详细规定
//http.formLogin().defaultSuccessUrl("/user/login.html");
/* iframe */
http.headers().frameOptions().sameOrigin(); // 运行同一个域名中的任何请求
http.csrf().disable(); // 默认是启用的,需要禁用CSRF保护(当不使用cookie时可以禁用csrf)
http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
// 禁用缓存
http.headers().cacheControl();
}
//定制请求的认证规则
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
System.out.println("进入到 configureGlobal 方法中");
System.out.println("auth.userDetailsService(myUserDetailService):" + auth.userDetailsService(myUserDetailService));
//1)获取内存中的用户名和密码
// auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("1").password(new BCryptPasswordEncoder().encode("1")).roles("USER");
// .withUser("1").password(new BCryptPasswordEncoder().encode("1")).authorities("ROLE_TEST");
// auth.authenticationProvider(authenticationProvider());
// auth.userDetailsService(myUserDetailService).passwordEncoder(passwordEncoder());
//2)获取数据库中的用户名和密码
auth.userDetailsService(myUserDetailService).passwordEncoder(new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(charSequence.toString());
}
});
}
/*
通过AuthenticationProvider方式获取
*/
@Bean
public DaoAuthenticationProvider authenticationProvider() {
System.out.println("进入到 authenticationProvider 方法中");
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(myUserDetailService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
/**
* 密码生成策略
* @return
*/
@Bean
public BCryptPasswordEncoder passwordEncoder() {
System.out.println("进入到 passwordEncoder 方法中");
return new BCryptPasswordEncoder();
}
@Bean
public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
System.out.println("进入到 authenticationTokenFilterBean 方法中");
return new JwtAuthenticationTokenFilter();
}
}
2)添加新成员信息时使用encode()进行密码加密
@RestController
@RequestMapping(value = "api/umeapiplus/user")
public class UserController {
private static final Gson gson = new Gson();
@Autowired
public UserService userService;
@Autowired
public BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
public RoleAndUserService roleAndUserService;
@Autowired
public RoleService roleService;
@Autowired
CorporationAndUserService corporationAndUserService;
@RequestMapping(value = "/updateMemberInfos", method = RequestMethod.POST)
public boolean updateMemberInfos(@RequestBody JSONObject jsonObject){
User userOfWeb = gson.fromJson(JSONObject.toJSONString(jsonObject.getJSONObject("user")), User.class);
String permission = jsonObject.getString("permission");
String encodedPassword = bCryptPasswordEncoder.encode(userOfWeb.getPassword());
userOfWeb.setPassword(encodedPassword);
userOfWeb.setLastLoginDate(new Date());//??
boolean userResult = userService.update(userOfWeb);
// 更新权限信息
RoleAndUser roleAndUser = roleAndUserService.findByUserId(userOfWeb.getId());
Integer roleId = roleService.findByRoleName(permission);
roleAndUser.setRoleId(roleId);
boolean roleAndUserResult = roleAndUserService.update(roleAndUser);
return userResult && roleAndUserResult;
}
@RequestMapping(value = "/addNewMember", method = RequestMethod.POST)
public boolean addNewMember(@RequestBody JSONObject jsonObject){
User userOfWeb = gson.fromJson(JSONObject.toJSONString(jsonObject.getJSONObject("user")), User.class);
String permission = jsonObject.getString("permission");
Integer corporationId = jsonObject.getInteger("corporationId");
String encodedPassword = bCryptPasswordEncoder.encode(userOfWeb.getPassword());
userOfWeb.setPassword(encodedPassword);
userOfWeb.setCreateDate(new Date());
userOfWeb.setLastLoginDate(new Date());
boolean userResult = userService.insertOfReturnId(userOfWeb);
//插入tb_role_and_user_new一条新记录
RoleAndUser roleAndUser = new RoleAndUser();
roleAndUser.setUserId(userOfWeb.getId());
Integer roleId = roleService.findByRoleName(permission);
roleAndUser.setRoleId(roleId);
boolean roleAndUserResult = roleAndUserService.insert(roleAndUser);
//插入tb_corporation_and_user一条新记录
CorporationAndUser corporationAndUser = new CorporationAndUser();
corporationAndUser.setUserId(userOfWeb.getId());
corporationAndUser.setCorporationId(corporationId);
corporationAndUser.setRoleId(roleId);
boolean corporationAndUserResult = corporationAndUserService.insert(corporationAndUser);
return userResult && roleAndUserResult && corporationAndUserResult;
}
@RequestMapping(value = "/deleteMember", method = RequestMethod.GET)
public boolean deleteMember(@RequestParam(value = "userId") Integer userId, @RequestParam(value = "corporationId") Integer corporationId){
boolean userResult = userService.deleteByPrimaryKey(userId);
boolean roleAndUserResult = roleAndUserService.deleteByUserId(userId);
boolean corporationAndUserResult = corporationAndUserService.deleteByUserId(userId);
return userResult && roleAndUserResult && corporationAndUserResult;
}
}
3)解密
使用bCryptPasswordEncoder.matches(原密码,加密后的密码),返回值时boolean类型