总体项目结构
数据库的设计
1. 首先在pom.xml中添加对应的依赖
<!-->spring-boot 整合security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2.新建一个security的package
2.1新建一个DatabaseUserDetailService.java,这个代码主要是实现自定义登录的权限控制和登录细节实现。
import com.travellerManager.sys.mapper.UserMapper;
import com.travellerManager.sys.pojo.Permission;
import com.travellerManager.sys.pojo.Role;
import com.travellerManager.sys.pojo.User;
import netscape.security.Privilege;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/*继承security提供的UserDetailsService接口*/
public class DatabaseUserDetailService implements UserDetailsService {
@Autowired
private UserMapper userMapper; /*登录对应的数据访问层*/
/*重新实现方法loadUserByUsername(String username)*/
public UserDetails loadUserByUsername(String username) {
User user ;
/*由于返回的是UserDetails对象,所以需要对我们的简单类进行转换*/
org.springframework.security.core.userdetails.User _user = null;
try {
/*对应的数据层方法*/
user = userMapper.findUserByUsername(username);
// 将自己的user对象封装为UserDetails,对应的User构造方法中需要的一些相关的参数-可以自己baidu,最后一参数是对应的权限
_user = new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), user.getStatus() == 0 ? false : true, true, true, true, getAuthority(user.getRoles()));
} catch (Exception e) {
e.printStackTrace();
}
/*返回包装好的user*/
return _user;
}
//作用就是返回一个List集合,集合中装入的是角色描述
//注意返回的权限必须是GrantedAuthority的子类
private final List<? extends GrantedAuthority> getAuthority(final List<Role> roles) {
return getGrantedAuthorities(getPrivileges(roles));
}
//具体获取权限的方法
private final List<String> getPrivileges(final Collection<Role> roles) {
final List<String> privileges = new ArrayList<>();
final List<Permission> collection = new ArrayList<>();
//将所有的权限放到collection中
for (final Role role : roles) {
collection.addAll(role.getPermissions());
}
for (final Permission item : collection) {
privileges.add(item.getPermissionName());
}
return privileges;
}
//将自己的权限通过SimpleGrantedAuthority包装
private final List<GrantedAuthority> getGrantedAuthorities(final List<String> privileges) {
final List<GrantedAuthority> authorities = new ArrayList<>();
for (final String privilege : privileges) {
authorities.add(new SimpleGrantedAuthority(privilege));
}
return authorities;
}
}
2.2 添加spring security的配置类
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.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;
//这两个注解缺一不可
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//配置spring的类装载实例化
@Bean
DatabaseUserDetailService userDetailService() {
return new DatabaseUserDetailService();
}
/**
* 5.1.2自动加密!!!!!!!!!
*/
// @Bean
// public BCryptPasswordEncoder passwordEncoder() {
// return new BCryptPasswordEncoder();
// }
//重写参数为HttpSecurity的configure方法,配置拦截策略
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//自定义登陆页面
.formLogin()
// 前端所访问的登录页面
.loginPage("/login")
// 提交登录信息交由处理的路径--交由security处理,自己不实现
.loginProcessingUrl("/doLogin")
//登陆成功后跳转的页面
.defaultSuccessUrl("/index").permitAll()
//登陆失败或无权限跳转页面
.failureUrl("/failure")
//其他所有页面必须验证后才可以访问
.and().authorizeRequests().antMatchers("/login", "/plugins/**").permitAll()
.anyRequest().authenticated()
.and().csrf().disable();
// 默认注销/logout
http.logout()
// 成功跳转地址
.logoutSuccessUrl("/login");
}
/*对权限进行配置*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService());
}
}
对应的/login的controller
@RequestMapping("/login")
public String goIndex() {
//返回登录界面
return "login";
}
对应的前端登录,注意用户名name必须是username,密码的name必须是password
<form action="/doLogin" method="post">
<div class="form-group has-feedback">
<input type="text" name="username" class="form-control"
placeholder="用户名"> <span
class="glyphicon glyphicon-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input type="password" name="password" class="form-control"
placeholder="密码"> <span
class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-8">
<div class="checkbox icheck">
<label><input type="checkbox"> 记住 下次自动登录</label>
</div>
</div>
<!-- /.col -->
<div class="col-xs-4">
<button type="submit" class="btn btn-primary btn-block btn-flat">登录</button>
</div>
<!-- /.col -->
</div>
</form>
3.错误处理页面
配置相应的403\404\500错误处理页面
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
@Component
public class ErrorPageConfig implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
ErrorPage e404 = new ErrorPage(HttpStatus.NOT_FOUND, "/404");
// TODO Auto-generated method stub
ErrorPage e500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500");
ErrorPage e403 = new ErrorPage(HttpStatus.FORBIDDEN, "/403");
registry.addErrorPages(e404, e500, e403);
}
}
在controller包下新建一个ErrorController.java
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ErrorController {
@RequestMapping("/404")
public String error_404() {
return "404";
}
@RequestMapping("/500")
public String error_500() {
return "500";
}
@RequestMapping("/403")
public String error_403() {
return "403";
}
}