springboot-security
一、添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
二、添加启动configuration 启动SpringSecurity过滤链
import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import javax.annotation.Resource; /** * @Autor zhangjiawen * @Date: 2020/4/27 15:34 */ @Configuration @EnableWebSecurity //启动SpringSecurity过滤链 public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { @Resource private AuthUserDetailService authUserDetailService; //该方法的作用是代替之前的配置:<security:authentication-manager> @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("eric").password(new BCryptPasswordEncoder().encode("abc")).authorities("PRO_ADD"); //相当于<security:authentication-provider user-service-ref="authUserDetailService"> auth.userDetailsService(authUserDetailService).passwordEncoder(new BCryptPasswordEncoder()); } //该方法的作用是代替之前的配置:<security:http> @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/manager/pro/del").hasAnyAuthority("Role_Del") .antMatchers("/manager/login").permitAll() .antMatchers("/manager/**") .fullyAuthenticated() .and() .formLogin().loginPage("/manager/login").failureHandler( new MyAuthenticationFailureHandler()) .successHandler(new MyAuthenticationSuccessHandler()) .and() .csrf().disable(); } }
同一错误页面转发
import org.springframework.boot.web.server.ConfigurableWebServerFactory; import org.springframework.boot.web.server.ErrorPage; import org.springframework.boot.web.server.WebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.EmbeddedValueResolverAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; /** * @Autor zhangjiawen * @Date: 2020/4/27 16:41 */ @Configuration public class ErrorPageConfig { @Bean public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){ return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>(){ //ErrorPage:定义错误页面 //参数一 错误状态码 //参数二 交给哪个请求处理 @Override public void customize(ConfigurableWebServerFactory factory) { factory.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN,"/403")); } }; } }
用户权限赋予类
import cn.net.topnet.topfs.dynamicdb.MongodbTemplateContextHolder; import cn.net.topnet.topfs.entities.Permissions; import cn.net.topnet.topfs.entities.Users; import cn.net.topnet.topfs.service.UserService; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; import java.util.Set; /** * @Autor zhangjiawen * @Date: 2020/4/28 10:03 @Description: 实现了UserDetailsService接口中的loadUserByUsername方法 * 执行登录,构建Authentication对象必须的信息, * 如果用户不存在,则抛出UsernameNotFoundException异常 * @Param: [s] * @return: org.springframework.security.core.userdetails.UserDetails */ @Service public class AuthUserDetailService implements UserDetailsService { @Resource private UserService userService; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { /** * @Author: Galen * @Description: 查询数据库,获取登录的用户信息 **/ MongodbTemplateContextHolder.setMongoDBTemplate("metadata"); Users user = userService.findOneByUserName(s); if(user==null){ throw new UsernameNotFoundException("用户名错误!"); } MongodbTemplateContextHolder.setMongoDBTemplate("metadata"); Set<Permissions> allPermissions = userService.findAllPermissionsByName(s); List<GrantedAuthority> authorities=new ArrayList<GrantedAuthority>(); allPermissions.forEach(permissions -> { GrantedAuthority grantedAuthority=new SimpleGrantedAuthority(permissions.getSymbol()); authorities.add(grantedAuthority); }); user.setAuthorities(authorities); return user; } }
验证失败拦截器
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.security.authentication.*; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * @Autor zhangjiawen * @Date: 2020/4/28 14:02 */ public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { response.setContentType("application/json;charset=utf-8"); Map result=new HashMap(); if (exception instanceof BadCredentialsException || exception instanceof UsernameNotFoundException) { result.put("error","账户名或者密码输入错误!"); } else if (exception instanceof LockedException) { result.put("error","账户被锁定,请联系管理员!"); } else if (exception instanceof CredentialsExpiredException) { result.put("error","密码过期,请联系管理员!"); } else if (exception instanceof AccountExpiredException) { result.put("error","账户过期,请联系管理员!"); } else if (exception instanceof DisabledException) { result.put("error","账户被禁用,请联系管理员!"); } else { result.put("error","登录失败!"); } ObjectMapper objectMapper=new ObjectMapper(); response.setContentType("Text/json;charset=utf-8"); response.getWriter().write(objectMapper.writeValueAsString(result)); } }
验证成功拦截器
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * @Autor zhangjiawen * @Date: 2020/4/28 14:37 */ public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { Map result=new HashMap(); result.put("success",true); ObjectMapper objectMapper=new ObjectMapper(); response.getWriter().write(objectMapper.writeValueAsString(result)); } }
用户实体类
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; /** * @Autor zhangjiawen * @Date: 2020/4/27 17:26 */ public class Users implements UserDetails { private String id; private String username; private String realName; private String password; private Date creatDate; private Date lastLoginTime; private boolean enabled; private boolean accountNonExpired; private boolean accountNonLocked; private boolean credentialsNonExpired; private List<GrantedAuthority> authorities=new ArrayList<>(); public String getId() { return id; } public void setAuthorities(List<GrantedAuthority> authorities) { this.authorities = authorities; } public void setId(String id) { this.id = id; } @Override public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getRealName() { return realName; } public void setRealName(String realName) { this.realName = realName; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return this.authorities; } @Override public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Date getCreatDate() { return creatDate; } public void setCreatDate(Date creatDate) { this.creatDate = creatDate; } public Date getLastLoginTime() { return lastLoginTime; } public void setLastLoginTime(Date lastLoginTime) { this.lastLoginTime = lastLoginTime; } @Override public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } @Override public boolean isAccountNonExpired() { return accountNonExpired; } public void setAccountNonExpired(boolean accountNonExpired) { this.accountNonExpired = accountNonExpired; } @Override public boolean isAccountNonLocked() { return accountNonLocked; } public void setAccountNonLocked(boolean accountNonLocked) { this.accountNonLocked = accountNonLocked; } @Override public boolean isCredentialsNonExpired() { return credentialsNonExpired; } public void setCredentialsNonExpired(boolean credentialsNonExpired) { this.credentialsNonExpired = credentialsNonExpired; } }
controller
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @Autor zhangjiawen * @Date: 2020/4/27 15:45 */ @Controller @RequestMapping("/manager") public class SecurityController { @GetMapping("/index") public String index(){ return "index"; } @GetMapping("/pro/add") public String add(){ return "add"; } @GetMapping("/pro/update") public String update(){ return "update"; } @GetMapping("/pro/del") public String del(){ return "del"; } @GetMapping("/403") public String forbidden(){ return "403"; } @GetMapping("/login") public String login(){ return "login"; } }
login.html
<!DOCTYPE html > <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/api/v1/manager/login" method="post"> 账号:<input type="text" name="username"/> 密码:<input type="text" name="password"> <input type="submit" value="登录" /> <span th:text="${error}"></span> </form> </body> </html>
密码加密代码块
@Override public Users insert(Users entity) { PasswordEncoder passwordEncoder=new BCryptPasswordEncoder(); entity.setPassword(passwordEncoder.encode(entity.getPassword())); return mongoTemplate.insert(entity); }