- ? 定义了UserDetails之后,当然还远远不够,哪个方法查询数据库来获取我们的用户信息呢?就是Security中的
UserDetailsService
接口
文章插图
- ? 它肯定也有默认实现类的,但是我们需要查询数据库对应的用户数据,所以我们还是采用
自定义
的方式去完成 。
@Servicepublic class UserService implements UserDetailsService {@Resourceprivate UserMapper userMapper;// 根据用户名去查询用户数据public User findUserByName(String username) {return userMapper.selectByName(username);}@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {return this.findUserByName(username);}}
- 完成到这里,对于用户信息的功能已经实现,但是我们还没有配置我们的登陆界面 。
- ? 在
config
目录下创建SecurityConfig
@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Resourceprivate UserService userService;}
- ? 正常项目中,肯定会有许多的静态资源,这些都可以在不登录的情况下访问,如css、js等
@Overridepublic void configure(WebSecurity web) throws Exception {// 忽略静态资源web.ignoring().antMatchers("/resources/**");}
- ? 当然我们上面的
UserService
只实现了认证的查询,并没有配置在何时去调用这个类 。
【👍SpringSecurity单体项目最佳实践】认证规则二选其一即可
// AuthenticationManager: 认证的核心接口// AuthenticationManagerBuilder: 用户构建AuthenticationManager对象的工厂类// ProviderManager: AuthenticationManager默认使用的实现类@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {//内置的认证规则//auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());// 自定义认证规则// AuthenticationProvider: ProviderManager持有一组AuthenticationProvider,每个AuthenticationProvider负责一种认证// 委托模式:// AuthenticationProvider: 就好比登陆方式,不仅有密码登录,且还有微信,等其他登陆方式,每一种登陆方式对应一个AuthenticationProviderauth.authenticationProvider(new AuthenticationProvider() {// Authentication: 用于封装认证信息的接口,不同实现类代表不同类型的认证信息@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {String username = authentication.getName();String password = authentication.getCredentials().toString();User user = userService.findUserByName(username);if (user == null) {throw new UsernameNotFoundException("账号或密码错误!");}password = CommunityUtil.md5(password + user.getSalt());if (!user.getPassword().equals(password)) {throw new BadCredentialsException("账号或密码错误!");}// principal:认证的主要信息 credentials:代表用户 authorities:权限信息return new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());}// 当前的AuthenticationProvider 支持哪种类型的认证 。@Overridepublic boolean supports(Class<?> aClass) {// UsernamePasswordAuthenticationToken: Authentication接口常用的实现类// 这样配置,我们当前项目只支持UsernamePasswordAuthenticationToken的认证return UsernamePasswordAuthenticationToken.class.equals(aClass);}});}
- ? 配置了以上步骤,是不是觉得Security挺麻烦的,别急马上到头了 。
@Overrideprotected void configure(HttpSecurity http) throws Exception {// 登陆相关配置http.formLogin().loginPage("/loginpage") // 登陆页面.loginProcessingUrl("/login") // 处理登陆请求的路径.successHandler(new AuthenticationSuccessHandler() { // 认证成功处理器@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {// 重定向到主页面response.sendRedirect(request.getContextPath() + "/index");}}).failureHandler(new AuthenticationFailureHandler() { // 认证失败处理器@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {// 请求转发到登陆页面// 因为在项目中,登陆失败后,往往需要携带错误信息到页面展示,所有采用请求转发的方式request.setAttribute("error", e.getMessage());request.getRequestDispatcher("/loginpage").forward(request, response);}});// 退出相关配置http.logout().logoutUrl("/logout").logoutSuccessUrl("/index"); // 退出后重定向到的接口// 授权配置 配置什么路径只能什么权限访问http.authorizeRequests().antMatchers("/letter").hasAnyAuthority("USER", "ADMIN").antMatchers("/admin").hasAnyAuthority("ADMIN").and().exceptionHandling().accessDeniedPage("/denied"); //无权限时,重回定向到的页面}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- .NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>
- PGL Paddle Graph Learning 关于图计算&图学习的基础知识概览:前置知识点学习
- 持续更新~ Arch Linux + KDE 配置&美化
- <一>类,对象,this指针
- "xxx cannot be cast to jakarta.servlet.Servlet "报错解决方式
- LAPM概述及配置
- 【lwip】10-ICMP协议&源码分析
- Unreal NetMode&NetRole 解析
- 【lwip】09-IPv4协议&超全源码实现分析
- 38 全球名校AI课程库| 马萨诸塞大学 · 自然语言处理进阶课程『Advanced Natural Language Processing』