SpringSecurity自定义登录接口的实现
作者:奔跑的大猪蹄子
本文介绍了使用Spring Security实现自定义登录接口,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
1.pom依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>2.7.10</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> <!--<dependency>--> <!--<groupId>org.springframework.session</groupId>--> <!--<artifactId>spring-session-data-redis</artifactId>--> <!--</dependency>--> <!--<dependency>--> <!--<groupId>redis.clients</groupId>--> <!--<artifactId>jedis</artifactId>--> <!--<version>3.6.3</version>--> <!--</dependency>--> <!--<dependency>--> <!--<groupId>org.springframework.boot</groupId>--> <!--<artifactId>spring-boot-starter-data-redis</artifactId>--> <!--<exclusions>--> <!--<exclusion>--> <!--<groupId>io.lettuce</groupId>--> <!--<artifactId>lettuce-core</artifactId>--> <!--</exclusion>--> <!--</exclusions>--> <!--</dependency>--> </dependencies>
2.配置类
package com.example.springsecuritytest.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 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.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity//开启Spring Security的功能 @EnableGlobalMethodSecurity(prePostEnabled=true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { //链式编程 @Override protected void configure(HttpSecurity http) throws Exception{ //请求授权的规则 http.authorizeRequests() //未登录可以直接访问 .antMatchers("/loginUser/**").permitAll() //admin权限可以访问(此处可以指定不同的权限访问不同的路径) .antMatchers("/**").hasAnyAuthority("admin") .anyRequest().authenticated();// 其他都需要登录认证; //注销,开启了注销功能,跳到首页 //http.logout().logoutSuccessUrl("/"); //定制登录页(没有登录默认跳转的路径) http.formLogin().loginPage("/loginUser/noLogin"); http.logout().logoutUrl("/signOut").logoutSuccessUrl("/loginUser/signOutSuccess"); http.exceptionHandling().accessDeniedPage("/loginUser/fail"); // 允许跨域请求 http.csrf(csrf -> csrf.disable()); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { super.configure(auth); } /** * 指定加密方式 */ @Bean public PasswordEncoder passwordEncoder(){ // 使用BCrypt加密密码 return new BCryptPasswordEncoder(); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }
3.controller层
3.1用户controller
package com.example.springsecuritytest.controller; import com.example.springsecuritytest.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/loginUser") public class LoginController { @Autowired private UserService userService; @RequestMapping("/login") public String login(String username,String pwd){ return userService.login(username,pwd); } @RequestMapping("/noLogin") public String noLogin(){ return "没有登录认证"; } @RequestMapping("/signOutSuccess") public String signOut(){ return "登出成功"; } @RequestMapping("/fail") public String fail(){ return "您无权进行此操作"; } }
3.2测试controller
package com.example.springsecuritytest.controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 下两个方法需要登录认证后,才能访问 */ @RestController public class TestController { @RequestMapping("/test") public String test(){ return "success"; } @PostMapping("/select") public String select(){ return "查询成功"; } }
4.entity层
4.1用户类
package com.example.springsecuritytest.entity; public class User { private String username; private String pwd; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }
4.2 用户认证信息类
package com.example.springsecuritytest.entity; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; import java.util.List; /** * UserDetails是一个核心接口,它代表了一个认证用户的详细信息。 * UserDetails接口定义了一些基本的方法,用于获取用户的基本信息和授权信息。 * 当一个用户进行身份验证时(比如通过用户名和密码登录),Spring Security会创建一个UserDetails的实例, * 这个实例会包含用户的认证信息,并可以用于后续的授权决策。UserDetails接口的主要方法包括: * * getUsername(): 返回用户的用户名。 * getPassword(): 返回用户的密码。注意,密码通常会被加密或哈希处理。 * getAuthorities(): 返回一个Collection,其中包含GrantedAuthority对象,这些对象表示用户被授予的权限。 * isAccountNonExpired(): 返回一个布尔值,指示用户的账户是否未过期。 * isAccountNonLocked(): 返回一个布尔值,指示用户的账户是否被锁定。 * isCredentialsNonExpired(): 返回一个布尔值,指示用户的凭证(如密码)是否未过期。 * isEnabled(): 返回一个布尔值,指示用户账户是否启用。 */ public class UserDetail implements UserDetails { private List<GrantedAuthority> authorities; private User user; @Override public Collection<? extends GrantedAuthority> getAuthorities() { return this.authorities; } @Override public String getPassword() { return user.getPwd(); } @Override public String getUsername() { return user.getUsername(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } public void setAuthorities(List<GrantedAuthority> authorities) { this.authorities = authorities; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
5.service层
5.1用户登录service
package com.example.springsecuritytest.service; public interface UserService { public String login(String username,String pwd); }
5.2用户登录service实现
package com.example.springsecuritytest.service; import com.alibaba.fastjson.JSON; import com.example.springsecuritytest.entity.UserDetail; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import java.util.Objects; @Service public class UserServiceImpl implements UserService { @Autowired private AuthenticationManager authenticationManager; @Override public String login(String username, String pwd) { // 用户认证 //进行用户认证 UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,pwd); Authentication authenticate = authenticationManager.authenticate(authenticationToken); //认证未通过,给出提示 if(Objects.isNull(authenticate)){ throw new RuntimeException("登陆失败!"); } // 认证成功将用户信息设置进Security上下文 SecurityContextHolder.getContext().setAuthentication(authenticate); UserDetail userDetail = (UserDetail)authenticate.getPrincipal(); return JSON.toJSONString(userDetail.getUser()); } }
5.3 用户认证service
package com.example.springsecuritytest.service; import com.example.springsecuritytest.entity.User; import com.example.springsecuritytest.entity.UserDetail; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * UserDetailsService定义了根据用户名加载用户特定数据的服务。 * 当Spring Security进行身份验证时,它会使用UserDetailsService来获取用户的详细信息, * 这些详细信息将被封装在一个UserDetails对象中。 * * UserDetailsService接口中只有一个方法:loadUserByUsername * * 这个方法接受一个用户名作为参数,并返回一个UserDetails对象, * 该对象包含了用户的详细信息,如用户名、密码、授权信息等。 * 如果找不到与给定用户名对应的用户,该方法应该抛出UsernameNotFoundException异常。 * * 在Spring Security的配置中,需要提供一个实现了UserDetailsService接口的bean。 * 这个bean将负责根据用户名从数据库或其他用户存储中检索用户信息,并将其转换为UserDetails对象。 * */ @Service public class UserDetailServiceImpl implements UserDetailsService { @Autowired private PasswordEncoder passwordEncoder; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 模拟根据用户名去数据库查询 User user = getUserByUsername(username); if(user == null){ throw new UsernameNotFoundException("用户名不存在"); } // 密码需要加密,否则密码对比不一致会认证失败 user.setPwd(passwordEncoder.encode(user.getPwd())); UserDetail userDetail = new UserDetail(); List<GrantedAuthority> authorities = new ArrayList<>(); // 设置对应权限 authorities.add(()-> "admin"); userDetail.setAuthorities(authorities); userDetail.setUser(user); return userDetail; } private User getUserByUsername(String username){ if("ttz".equals(username)){ User user = new User(); user.setUsername("ttz"); user.setPwd("980422"); return user; } return null; } }
到此这篇关于SpringSecurity自定义登录接口的实现的文章就介绍到这了,更多相关SpringSecurity自定义登录接口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!