<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
@Data
public class User implements UserDetails {
private Integer id;
private String username;
private String password;
private Long gmtCreate;
private Long gmtModified;
private String avatarUrl;
private Integer vipLevel;
private String vipName;
private Boolean status;
private String name;
private Integer sex;
private String description;
private List<Role> roleList = new ArrayList();
@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 Collection<? extends GrantedAuthority> getAuthorities() {
return roleList;
}
}
@Data
public class Role implements GrantedAuthority {
private Integer id;
private String name;
private String description;
@Override
public String getAuthority() {
return name;
}
}
重新写loadUserByUsername方法
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserExample example = new UserExample();
example.createCriteria().andUsernameEqualTo(username);
com.wu.manager.pojo.User user = userMapper.selectByExample(example).get(0);
user.getVipLevel();
UserGrade userGrade = userGradeMapper.selectByPrimaryKey(user.getVipLevel());
user.setVipName(userGrade.getGradeName());
if (user == null) return null;
List<Role> authorities = authorities(user.getId());
user.setRoleList(authorities);
return user;
}
//给当前用户指定角色
private List<Role> authorities(Integer id) {
List<Role> authorities = new ArrayList<>();
UserRoleExample userRoleExample = new UserRoleExample();
userRoleExample.createCriteria().andUserIdEqualTo(id);
List<UserRole> userRoleList = userRoleMapper.selectByExample(userRoleExample);
for (UserRole userRole : userRoleList) {
Role role = roleMapper.selectByPrimaryKey(userRole.getRoleId());
authorities.add(role);
}
return authorities;
}
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true,jsr250Enabled = true,securedEnabled = true) //开权限方法权限注解支持
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Autowired
private DataSource dataSource;
@Bean
public PasswordEncoder createPwdEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl persistentTokenRepository = new JdbcTokenRepositoryImpl();
persistentTokenRepository.setDataSource(dataSource);
return persistentTokenRepository;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll() //对登录请求放行
.antMatchers("/res/**").permitAll()
.antMatchers("/index/**").hasAnyAuthority("VIP")
.antMatchers("/**") //拦截根目录以及根目录下的子目录
.fullyAuthenticated() //对所有的资源进行请求拦截
.and()
.formLogin() //以表单验证的方式对所有的拦截资源进行认证
.loginPage("/login") //自定义登录页面
// .successForwardUrl("/") //登录成功后的跳转页面
.successHandler(new MyAuthenticationSuccessHandler()) //登录成功返回json信息
.failureHandler(new MyAuthenticationFailureHandler()) //登录失败返回json信息
.and()
.rememberMe().tokenValiditySeconds(86400)
.and()
.logout().deleteCookies("remember-me")
.and().headers().frameOptions().sameOrigin()
.and().sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry());
// .csrf().disable() //关闭跨域访问
;
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
}
登陆成功返回json
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.setContentType("application/json;charset=utf-8");
PrintWriter out = httpServletResponse.getWriter();
out.write(JsonUtils.objectToJson(LayUIResult.build(200,"登陆成功")));
out.flush();
out.close();
}
}
登陆失败返回json
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setContentType("application/json;charset=utf-8");
PrintWriter out = httpServletResponse.getWriter();
out.write(JsonUtils.objectToJson(LayUIResult.build(400,"登录失败")));
out.flush();
out.close();
}
}
@RequestMapping("/login")
public String login() {
return "/page/login/login";
}
springboot配置类形式,在SpringSecurity配置类上添加注解
@EnableGlobalMethodSecurity(prePostEnabled = true,jsr250Enabled = true,securedEnabled = true) //开权限方法权限注解支持
在controller或者service上开启权限控制
//@PreAuthorize("hasRole('ROLE_MANAGER')")
@Secured({"ROLE_MANAGER","ROLE_USER"})
@RolesAllowed({"ROLE_USER","ROLE_MANAGER"})
只需要开启一个即可,可以实现对controller等的权限控制
跨域访问保护默认是开启的,这时你的登陆、退出必须为POST方式,以及增删改必须携带CSRF令牌
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
$.ajax({
type: "POST",
url: "/login",
data: $('#loginForm').serialize(),
dataType: "json",
success: function (loginCallback) {
if (loginCallback.code == '200') {
layer.msg("登录成功", {
icon: 6,
time: 1000 //2秒关闭(如果不配置,默认是3秒)
}, function () { //弹框后的操作
window.location.href = "/";
});
} else {
layer.msg("用户名或密码错误,请重新输入", {
icon: 2,
time: 2000 //2秒关闭(如果不配置,默认是3秒)
});
}
},
error: function (jqXHR) {
layer.alert("发生错误:" + jqXHR.status, {
title: 'Error'
});
}
});
<meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}">
//ajax请求时都带上csrf信息
$(function () {
var token = $("meta[name='_csrf']").attr("content")
var header = $("meta[name='_csrf_header']").attr("content")
$(document).ajaxSend(function (e, xhr, options) {
xhr.setRequestHeader(header,token)
})
})