网上找了好几个,因为各种原因不太行,下面这个亲测可行
参考:https://blog.csdn.net/u012702547/article/details/54319508
基于SpringBoot + JPA
安全框架:Security5
页面:Thymeleaf + BootStrap
工程目录结构:
引入依赖包
pom.xml
4.0.0 com.zit Hello 0.0.1-SNAPSHOT jar UTF-8 org.springframework.boot spring-boot-starter-parent 2.0.0.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-thymeleaf org.thymeleaf.extras thymeleaf-extras-springsecurity4 mysql mysql-connector-java 5.1.40 spring-snapshots Spring Snapshots https://repo.spring.io/libs-snapshot true
配置文件
application.properties
spring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8spring.datasource.username=rootspring.datasource.password=logging.level.org.springframework.security=infospring.thymeleaf.cache=falsespring.jpa.hibernate.ddl-auto=updatespring.jpa.show-sql=truespring.jackson.serialization.indent_output=truespring.thymeleaf.cache=false
1、实体类
(1)用户
package com.zit;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.userdetails.UserDetails;import javax.persistence.*;import java.util.ArrayList;import java.util.Collection;import java.util.List;/** * */@Entitypublic class SysUser implements UserDetails { @Id @GeneratedValue private Long id; private String username; private String password; @ManyToMany(cascade = {CascadeType.REFRESH},fetch = FetchType.EAGER) private Listroles; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public List getRoles() { return roles; } public void setRoles(List roles) { this.roles = roles; } @Override public Collection getAuthorities() { List auths = new ArrayList<>(); List roles = this.getRoles(); for (SysRole role : roles) { auths.add(new SimpleGrantedAuthority(role.getName())); } return auths; } @Override public String getPassword() { return this.password; } @Override public String getUsername() { return this.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; }}
(2)角色
package com.zit;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;/** * */@Entitypublic class SysRole { @Id @GeneratedValue private Long id; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
2、JPA访问数据库
package com.zit;import org.springframework.data.jpa.repository.JpaRepository;public interface SysUserRepository extends JpaRepository{ SysUser findByUsername(String username);}
3、控制器
(1)控制器给页面传值的对象
package com.zit;/** * 传递在页面上的消息 */public class Msg { private String title; private String content; private String extraInfo; public Msg() { } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getExtraInfo() { return extraInfo; } public void setExtraInfo(String extraInfo) { this.extraInfo = extraInfo; } public Msg(String title, String content, String extraInfo) { this.title = title; this.content = content; this.extraInfo = extraInfo; }}
(2)控制类
package com.zit;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;@Controllerpublic class HomeController { @RequestMapping("/") public String index(Model model) { Msg msg = new Msg("测试标题", "测试内容", "额外信息,只对管理员显示"); model.addAttribute("msg", msg); return "index"; }}
4、自定义UserDetailsService
package com.zit;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;public class CustomUserService implements UserDetailsService { @Autowired SysUserRepository userRepository; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { SysUser user = userRepository.findByUsername(s); if (user == null) { throw new UsernameNotFoundException("用户名不存在"); } System.out.println("s:"+s); System.out.println("username:"+user.getUsername()+";password:"+user.getPassword()); return user; }}
5、SpringMVC配置
package com.zit;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;@Configurationpublic class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); }}
当用户访问login时跳转到login.html页面
6、配置Spring Security
由于Spring Security5必须自定义密码加密,所以建立一个自定义密码加密类
(1)MyPasswordEncoder.java
package com.zit;import org.springframework.security.crypto.password.PasswordEncoder;public class MyPasswordEncoder implements PasswordEncoder { @Override public String encode(CharSequence arg0) { return arg0.toString(); } @Override public boolean matches(CharSequence arg0, String arg1) { return arg1.equals(arg0.toString()); }}
(2)Security配置
package com.zit;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.core.userdetails.UserDetailsService;@Configurationpublic class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean UserDetailsService customUserService() { return new CustomUserService(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserService()) .passwordEncoder(new MyPasswordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //security允许页面加载css文件夹下的静态资源 .antMatchers("/css/**").permitAll() .anyRequest().authenticated() .and().formLogin().loginPage("/login").failureUrl("/login?error").permitAll() .and() .logout() .permitAll(); }}
1.首先当我们要自定义Spring Security的时候我们需要继承自WebSecurityConfigurerAdapter来完成,相关配置重写对应 方法即可。
2.我们在这里注册CustomUserService的Bean,然后通过重写configure方法添加我们自定义的认证方式。 3.在configure(HttpSecurity http)方法中,我们设置了登录页面,而且登录页面任何人都可以访问,然后设置了登录失败地址,也设置了注销请求,注销请求也是任何人都可以访问的。 4.permitAll表示该请求任何人都可以访问,.anyRequest().authenticated()
,表示其他的请求都必须要有权限认证。
7、静态资源
(1)CSS
下载bootstrap包,取其bootstrap.min.css
另,自己写一个signin.css,如下:
body { padding-top: 40px; padding-bottom: 40px; background-color: #eee;}.form-signin { max-width: 330px; padding: 15px; margin: 0 auto;}.form-signin .form-signin-heading,.form-signin .checkbox { margin-bottom: 10px;}.form-signin .checkbox { font-weight: normal;}.form-signin .form-control { position: relative; height: auto; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: 10px; font-size: 16px;}.form-signin .form-control:focus { z-index: 2;}.form-signin input[type="email"] { margin-bottom: -1px; border-bottom-right-radius: 0; border-bottom-left-radius: 0;}.form-signin input[type="password"] { margin-bottom: 10px; border-top-left-radius: 0; border-top-right-radius: 0;}
(2)HTML
login.html
登录 已注销
有错误,请重试
使用账号密码登录
index.html
无更多显示信息