zeromemos
最好的学习方法就是输出所学的知识SpringSecurity前后端分离登录认证
主要通过上图中的AuthenticationManager手动委托框架进行认证。
首先Maven中要加入依赖
<!-- SpringSecurity权限管理依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
加入配置类WebSecurityConfigurer
@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) //开启注解权限认证 public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
//将AuthenticationManager暴露出去,以便于后面在其他类里能直接注入 @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } //访问权限配置 @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeHttpRequests() //放行的请求 .mvcMatchers("/", "/user/login") .permitAll() //其他全部拦截 .anyRequest().authenticated(); //关闭csrf跨站请求伪造 http.csrf().disable(); //不通过session来存储和获取会话 http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); } }
因为要前后端分离,我们要将会话数据存在Redis里,所以这边要关闭session存储会话的功能,并且放行登录接口/user/login
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
并且暴露了AuthenticationManager,以便于后面在其他类里能直接注入。
创建一个实现了UserDetails接口的MySecurityUser,方便后面存取需要的用户信息。
public class MySecurityUser extends User { //自己的User实体类,方便后面存取需要的用户信息 private SysUser sysUser;
//分别将用户、密码和权限集合传到父类的构造函数里 public MySecurityUser(SysUser sysUser, Collection<? extends GrantedAuthority> authorities) { super(sysUser.getUsername(), sysUser.getPassword(), authorities); this.sysUser = sysUser; } public SysUser getSysUser() { return sysUser; } public void setSysUser(SysUser sysUser) { this.sysUser = sysUser; } }
创建一个实现了UserDetailsService接口的MyUserDetailsService类,用于自定义从数据库获取用户信息功能。下面的sysUserService.getByUsername("admin")就是根据用户名从数据库获取用户对象。
@Component
public class MyUserDetailsService implements UserDetailsService {
private final SysUserService sysUserService;
public MyUserDetailsService(SysUserService sysUserService) {
this.sysUserService = sysUserService;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//查询用户
SysUser sysUser = sysUserService.getByUsername("admin");
return new MySecurityUser(sysUser, new ArrayList<GrantedAuthority>());
}
}
创建登录接口方法,这边返回的是jwt生成的token。
@RestController
@RequestMapping("/user")
public class SysUserController {
private final SysUserService sysUserService;
public SysUserController(SysUserService sysUserService) {
this.sysUserService = sysUserService;
}
@PostMapping("login")
public Map<String, String> login(String username, String password) {
String token = sysUserService.doLogin(username, password);
Map<String, String> map = new HashMap<>();
map.put("token", token);
return map;
}
}
service里的实现方法如下
/**
* 进行登录
*
* @param username 用户名
* @param password 密码
* @return 登录成功返回token 登录失败直接交给异常处理
*/
@Override
public String doLogin(String username, String password) {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
Authentication authenticate = null;
try {
authenticate = authenticationManager.authenticate(authenticationToken);
} catch (AuthenticationException e) {
System.out.println("认证失败");
e.printStackTrace();
}
if (authenticate == null) {
throw new RuntimeException("登录失败");
}
MySecurityUser mySecurityUser = (MySecurityUser)authenticate.getPrincipal();
Map<String, String> map = new HashMap<>();
map.put("username", mySecurityUser.getUsername());
String token = JWTUitls.getToken(map);
return token;
}
这里将前端传来的用户名和密码手动创建UsernamePasswordAuthenticationToken对象,然后交给authenticationManager.authenticate()方法进行认证,认证失败会抛出异常,进行捕获处理即可。认证成功就使用jwt工具类生成token返回给用户。
评论区
关于我们
本站主要用于记录个人学习笔记,网站开发中,如需以前站内资料请加QQ群272473835索取。注册账号仅提供回帖功能,可不注册!
