1、前言
为了方便进行项目开发,自己搭建了一套简单的基于RBAC模型的权限管理系统,其中涉及到的用户、角色、资源(菜单)等模块已经实现了,现在需要引入SpringSecurity来实现认证和授权。
2、引入依赖
这里使用的SpringSecurity的版本是:5.0.8.RELEASE,SpringBoot版本是:2.0.5.RELEASE。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
3、创建UserDetailsService实现类
UserDetailsService实现类,用于加载用户信息。主要实现了UserDetailsService 接口的loadUserByUsername()方法,根据用户名从数据库查询用户信息和用户权限信息,最后封装成了UserDetails 对象。
@Component("userDetailsService")
public class QriverUserDetailsService implements UserDetailsService {
private Logger logger = LoggerFactory.getLogger(QriverUserDetailsService.class);
@Autowired
private UserService userService;
@Autowired
private UserRoleService userRoleService;
@Autowired
private RoleService roleService;
/**
* 根据username加载数据库中的用户,并构建UserDetails对象。
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Collection<GrantedAuthority> authorities = new ArrayList<>();
User param = new User(username);
User user = userService.querySingle(param);
if(user == null) {
logger.info("用户名不存在,用户名:" + username);
throw new UsernameNotFoundException("用户名不存在");
}
UserRole userRole = new UserRole();
userRole.setUserId((String) user.getId());
List<UserRole> userRoles = userRoleService.queryList(userRole);
for(UserRole uRole : userRoles) {//保存Role的ID
authorities.add(new SimpleGrantedAuthority(uRole.getRoleName()));
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),authorities);
}
}
4、创建PasswordEncoder实现类
PasswordEncoder实现类,从5.0版本开始强制要求设置,主要用来配置加密方式,这里使用了明文的方式。
@Component("nonPasswordEncoder")
public class QriverNonPasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
//加密方法可以根据自己的需要修改
return rawPassword.toString();
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encode(rawPassword).equals(encodedPassword);
}
}
5、配置SpringSecurity
首先,定义SpringSecurityConfig 配置类,该类继承了WebSecurityConfigurerAdapter 抽象类。
然后,添加注解@Configuration、@EnableWebSecurity,分别表示配置类和开启 Security 服务。
然后,重写configure(AuthenticationManagerBuilder auth)方法,该方法主要用来配置AuthenticationManager对象相关内容,这里主要配置了自定义的UserDetailsService实现类和PasswordEncoder实现类。
最后,通过重写configure(HttpSecurity http)方法,进行配置HttpSecurity 相关内容,主要配置了那些URL需要鉴权那些不需要鉴权,自定义登录页面、登录成功或失败时跳转路径、异常拦截等内容。
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private QriverUserDetailsService userDetailsService;
@Autowired
private QriverNonPasswordEncoder nonPasswordEncoder;
/**
* 配置AuthenticationManager对象
* @param auth
* @throws Exception
*/
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
//校验用户
auth.userDetailsService( userDetailsService )
.passwordEncoder(nonPasswordEncoder);
}
/**
* 配置 HttpSecurity
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//设置不需要鉴权的地址
.antMatchers("/error","/","index","/login","/login-error","/401","/static/**").permitAll()
//其他请求均需要鉴权
.anyRequest().authenticated()
.and()
//登录成功跳转页面
.formLogin().defaultSuccessUrl("/index/toIndex").
//自定义登录界面
loginPage( "/login" ).
//登录失败跳转页面
failureUrl( "/login-error" )
.and()
.exceptionHandling().accessDeniedPage( "/401" )
.and().csrf().disable()
.headers().frameOptions().disable();
http.logout().logoutSuccessUrl( "/" );
}
}
关于”/login”、”/login-error”、”/index/toIndex”等api接口,这里不再贴出代码了。
6、登录页面
这里就是一个普通的from表单,最重要的就是from表单的action方法,这里使用了“/login”,且method=“post”,“/login”是SpringSecurity默认的地址,可以在HttpSecurity 中进行配置。
这里需要注意的是,之前自己实现的登录验证,需要首先定义一个“/doLogin”方法,然后登录界面通过from表单或AJAX进行请求,而在SpringSecurity中,则不需要再定义该方法,默认已经实现了,只需要通过HttpSecurity的loginProcessingUrl()方法修改默认的请求的路径地址即可。
//部分代码
<body class="gray-bg">
<div class="middle-box text-center loginscreen animated fadeInDown">
<div>
<div style="margin:25% 0 5% 0;">
<img src="${ctxPath}/static/img/logo.png" width="45%;">
</div>
<h3>欢迎使用 综合管理平台</h3>
<form class="m-t" role="form" method="post" action="${ctxPath}/login">
<div class="form-group">
<input type="text" id="username" name="username" class="form-control" placeholder="用户名" value="admin" required="">
</div>
<div class="form-group">
<input type="password" id="password" name="password" class="form-control" placeholder="密码" value="123456" required="">
</div>
<button type="submit" class="btn btn-primary block full-width m-b">登 录</button>
</form>
</div>
</div>
</body>
7、其他
通过上述步骤,我们基本上已经实现了SpringSecurity的集成,这个时候我们的用户鉴权就会通过SpringSecurity被保护起来了。后续,我们会继续细化一些细节,比如用户名密码错误时,如何更加友好提示?如何登录后,还回到当前页面等功能。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/68741.html