Spring Security form login 权限认证模式的实例
主要思路
这篇文章算是接着我很早一篇的关于Spring Security的一篇文章写的。算是我对于这个认证机制的个人理解。
Spring Security其核心就是一组过滤器链,项目启动后将会自动配置。在这次的实例中所用的是Usernamepassword的认证模式,
具体认证流程如下

这个图片中详细的描述了为了验证用户身份所进行的一系列调用,需要用户自己实现的接口便是UserDetailService中的loadUserByName()函数,这个函数需要根据传入的参数Username返回一个UserDetail对象,里面包含着用户名密码权限等诸多信息,而这些信息一般都存储在数据库中,因此我们需要构建实体类User以及数据库操作接口UserService,以及其实现类UserServiceImpl,有了这三个类,我们就可以在userServiceimpl中建立一个可以根据username搜索并返回user对象的函数,而之前说过的UserDetailService中的loadUserByName()函数可以通过调用这个函数将userdetail信息进行返回,从而使得认证过程顺利进行,此外,为了能够对于认证之后的资源开放对象进行管理,我们还需要对于一个配置类进行编辑,即 继承于WebSecurityConfigurerAdapter 的SecurityConfig ,这些都可以算是后端的一些文件,如果想要测试,可以做一些简单的前端测试页面,并设置controller类对页面和路径进行映射。
总结一下上面的全部流程,可以发现需要我们实现的类大致有以下几个:1UserDetailsService,对其loaduserbyusername函数进行编写
2User实体类,实现数据库的映射
3UserService接口,定义数据库操作函数
4 UserServiceImpl实现类,实现上文所述接口的函数
5 Security Config类,用来控制相关资源路径对于不同角色的权限
6contrloller类,用来控制访问路径与实际网页的映射。
注 以上提到的类名并不一定与下文中的完全相同,理解意思即可
详细文件
UserDetailsServiceImp
@Service
public class UserDetailsServiceImp implements UserDetailsService {
@Autowired
private UserDAO userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.findById(username).get();
if (user == null) {
throw new UsernameNotFoundException("用户ID" + username + "未找到");
}
JwtUser jwtUser=new JwtUser(user);
return jwtUser;
}
}
User
@Entity
@Table(name="user")
public class User {
@Id
@Column(name = "username")
private String username;
@Column(name = "password")
private String password;
@Column(name = "role")
private String role;
public void setRole(String role) {
this.role = role;
}
public void setPassword(String password) {
this.password = password;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return this.password;
}
public String getRole() {
return this.role;
}
public String getUsername() {
return this.username;
}
}
将User类进行包装变为UserDetail类的中间类
public class JwtUser implements UserDetails {
private String username;
private String password;
private Collection<? extends GrantedAuthority> authorities;
// 写一个能直接使用user创建jwtUser的构造器
public JwtUser(User user) {
username = user.getUsername();
password = user.getPassword();
authorities = Collections.singleton(new SimpleGrantedAuthority(user.getRole()));
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public String toString() {
return "JwtUser{" +
", username='" + username + '/'' +
", password='" + password + '/'' +
", authorities=" + authorities +
'}';
}
}
UserDAO
public interface UserDAO extends JpaRepository<User,String> {
}
这里我并没有自定义其他方法因此并没有写该类的实现类
SecurityConfig
@Configuration
@EnableWebSecurity(debug=false)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private MyAuthenticationSuccessHandler successHandler;
@Resource
private MyAuthenticationFailureHandler failureHandler;
@Resource
private UserDetailsService myUserDetailsService;
@Resource
private JwtAuthTokenFilter jwtAuthTokenFilter;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity)throws Exception{
httpSecurity.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login")
.usernameParameter("username")
.passwordParameter("password")
//.defaultSuccessUrl("/index")
//.failureUrl("/login")
.successHandler(successHandler)
.failureHandler(failureHandler)
.and()
.authorizeRequests()
.antMatchers("/login","/login.html")
.permitAll()
.antMatchers("/system/order","/system/menu")
.hasAnyAuthority("admin")
.antMatchers("/system/role")
.hasAnyAuthority("admin","user")
//.hasAnyAuthority("ROLE_admin")
.anyRequest().authenticated()
.and()
.csrf().disable();
httpSecurity.logout().logoutUrl("/logout");
httpSecurity.addFilterBefore(jwtAuthTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth)throws Exception{
auth.userDetailsService(myUserDetailsService)
.passwordEncoder(bCryptPasswordEncoder());
}
public BCryptPasswordEncoder bCryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
}
homeController
@Controller
public class HomeController {
@GetMapping("/index")
public String index(){
return "index";
}
@GetMapping("/system/user")
public String userList(){
return "user";
}
@GetMapping("/system/role")
public String roleList(){
return "role";
}
@GetMapping("/system/menu")
public String menuList(){
return "menu";
}
@GetMapping("/system/order")
public String orderList(){
return "order";
}
}
相关的网页
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登陆首页</title>
<script src="https://cdn.staticfile.org/jquery/1.12.3/jquery.min.js"></script>
</head>
<body>
<h1>实训管理系统</h1>
<form action="/login" method="post">
<span>用户账号</span><input type="txt" name="username" id="username"/><br>
<span>用户密码</span><input type="password" name="password" id="password"/><br>
<!--- <input type="submit" value="登录">-->
<input type="button" onclick="login()" value="登录">
<a href="/regist.html">注册</a>
</form>
</body>
<script>
function login(){
$.ajax(
{
type:"POST",
url:"/login",
data:{
"username":$("#username").val(),
"password":$("#password").val()
},
success:function(data){
if(data.code==200){
location.href="/index";
}else{
alert(data.msg);
}
}
}
);
}
</script>
</html>
index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body><head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>
用户登录
</h1>
<br>
<a href="/system/user">
用户管理
</a>
<br>
<a href="/system/menu">
目录管理
</a>
<br>
<a href="/system/role">
角色管理
</a>
<br>
<a href="/system/order">
订单管理
</a>
<a href="/logout">
退出
</a>
</body>
</html>
menu.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>menu</title>
</head>
<body>
<h1>目录页面</h1>
</body>
</html>
剩下的角色页面订单页面也都是只有四个字显示,和这个文件没有什么不同,不在赘述了
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/17784.html