--用户表
CREATE TABLE L_USER (
ID NUMBER NULL ,
USERNAME VARCHAR2(30 BYTE) NULL ,
PASSWORD VARCHAR2(255 BYTE) NULL ,
ENABLED NUMBER NULL ,
LOCKED NUMBER NULL
)
-- 权限表
CREATE TABLE L_ROLE (
ID NUMBER NULL ,
NAME VARCHAR2(50 BYTE) NULL ,
NAMEZH VARCHAR2(50 BYTE) NULL
)
-- 用户权限关联表
CREATE TABLE L_USER_ROLE (
ID NUMBER NULL ,
USERID NUMBER NULL ,
ROLEID NUMBER NULL
)
创建实体类
@ApiModel(value = "用户实体类", description = "用户信息描述类")
public class User implements UserDetails {
@ApiModelProperty(value = "用户名id")
private Integer id ;
@ApiModelProperty(value = "用户名")
private String username ;
@ApiModelProperty(value = "密码")
private String password ;
@ApiModelProperty(value = "是否可用")
private Boolean enabled ;
@ApiModelProperty(value = "是否锁定")
private Boolean locked ;
@ApiModelProperty(value = "角色")
private List<Role> roles ;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
for(Role role : roles){
authorities.add(new SimpleGrantedAuthority(role.getName()));
}
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 !locked;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return enabled;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
// 这个一定要注释掉,会重复
/* public Boolean getEnabled() {
return enabled;
}*/
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public Boolean getLocked() {
return locked;
}
public void setLocked(Boolean locked) {
this.locked = locked;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public User() {
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", enabled=" + enabled +
", locked=" + locked +
", roles=" + roles +
'}';
}
}
public class Role {
private Integer id ;
private String name ;
private String nameZH;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNameZH() {
return nameZH;
}
public void setNameZH(String nameZH) {
this.nameZH = nameZH;
}
@Override
public String toString() {
return "Role{" +
"id=" + id +
", name='" + name + '\'' +
", nameZH='" + nameZH + '\'' +
'}';
}
}
public class Result {
private Integer code ;
private String message ;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Mapper文件(部分代码省去,只有sql语句)
<select id="loadUserByUsername" resultType="com.springtest.model.User">
SELECT * FROM l_user where username = #{username}
</select>
<select id="getUserRolesByUid" resultType="com.springtest.model.Role">
select a.*,b.NAME,b.NAMEZH
from
L_USER_ROLE a LEFT JOIN L_ROLE b
on a.ROLEID = b.ID
where a.USERID = #{id}
</select>
UserService 准备
@Service
public class UserService implements UserDetailsService {
@Autowired
UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = userMapper.loadUserByUsername(s);
if(user == null){
throw new UsernameNotFoundException("用户名不存在");
}
user.setRoles(userMapper.getUserRolesByUid(user.getId()));
return user;
}
}
登录,权限验证
@Configuration
//@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserService userService;
@Autowired
MyAuthenticationFailHandler authenticationFailHandler;
@Autowired
MyAuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
CustomAccessDeniedHandler deniedHandler;
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**","/login_page.html");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
@Override
public <O extends FilterSecurityInterceptor> O postProcess(O o) {
o.setSecurityMetadataSource(cfisms());
o.setAccessDecisionManager(cadm());
return o;
}
})
/*.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/db/**").hasRole("dba")*/
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login_page.html")
.loginProcessingUrl("/login")
//.successForwardUrl("/index.html")
.permitAll()
.failureHandler(authenticationFailHandler)
.successHandler(authenticationSuccessHandler)
.and()
.logout()
.logoutUrl("/logout")
.clearAuthentication(true)
.invalidateHttpSession(true)
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
httpServletResponse.setContentType("application/json; charset=utf-8");
PrintWriter writer = httpServletResponse.getWriter();
Result result = new Result();
result.setCode(1);
result.setMessage("退出成功");
writer.write(new ObjectMapper().writeValueAsString(result));
writer.flush();
writer.close();
}
})
.permitAll()
.and()
.csrf().disable()
.exceptionHandling()
.accessDeniedHandler(deniedHandler)
.and()
.sessionManagement() //session超时管理
.invalidSessionUrl("/login_page.html"); //session超时跳向的url;
}
@Bean
CustomFilterInvocationSecurityMetadataSource cfisms(){
return new CustomFilterInvocationSecurityMetadataSource();
}
@Bean
CustomAccessDecisionManager cadm(){
return new CustomAccessDecisionManager();
}
}
----------------------------------------------------------------
@Component
public class CustomFilterInvocationSecurityMetadataSource
implements FilterInvocationSecurityMetadataSource {
AntPathMatcher antPathMatcher = new AntPathMatcher();
@Autowired
MenuMapper menuMapper;
@Override
public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
String requestUrl = ((FilterInvocation) o).getRequestUrl();
List<Menu> menus = menuMapper.getAllMenus();
for(Menu menu : menus){
if(antPathMatcher.match(menu.getPattern(),requestUrl)){
List<Role> roles = menu.getRoles();
String[] roleArr = new String[roles.size()];
for(int i=0 ;i < roleArr.length ; i++){
roleArr[i] = roles.get(i).getName();
}
return SecurityConfig.createList(roleArr);
}
}
return SecurityConfig.createList("ROLE_LOGIN");
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class<?> aClass) {
return FilterInvocation.class.isAssignableFrom(aClass);
}
}
----------------------------------------------------------------------------------
@Component
public class CustomAccessDecisionManager implements AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (ConfigAttribute configAttribute : collection){
if("ROLE_LOGIN".equals(configAttribute.getAttribute())
&& authentication instanceof UsernamePasswordAuthenticationToken){
return;
}
for (GrantedAuthority authority : authorities){
if(configAttribute.getAttribute().equals(authority.getAuthority())){
return;
}
}
}
throw new AccessDeniedException("权限不足");
}
@Override
public boolean supports(ConfigAttribute configAttribute) {
return true;
}
@Override
public boolean supports(Class<?> aClass) {
return true;
}
}
-------------------------------------------------------------------------------
@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
private String errorPage;
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
httpServletResponse.setContentType("application/json; charset=utf-8");
PrintWriter writer = httpServletResponse.getWriter();
Result result = new Result();
result.setCode(0);
result.setMessage("权限不足");
//httpServletResponse.sendRedirect("/login_page.html");
writer.write(new ObjectMapper().writeValueAsString(result));
writer.flush();
writer.close();
}
}
-------------------------------------------------------------------------------------------
@Component
public class MyAuthenticationFailHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException e) throws IOException {
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
Result result = new Result();
result.setCode(0);
if(e instanceof BadCredentialsException || e instanceof UsernameNotFoundException){
result.setMessage("账户名或者密码不正确");
}else if(e instanceof LockedException){
result.setMessage("账户被锁定,请联系管理员");
}else if(e instanceof CredentialsExpiredException){
result.setMessage("密码过期,请联系管理员");
}else if(e instanceof AccountExpiredException){
result.setMessage("账户过期,请联系管理员");
}else if(e instanceof DisabledException){
result.setMessage("账户被禁,请联系管理员");
}else {
result.setMessage("登陆失败");
}
writer.write(new ObjectMapper().writeValueAsString(result));
writer.flush();
writer.close();
}
}
-------------------------------------------------------------------------------------
@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException {
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
httpServletResponse.setContentType("application/json; charset=utf-8");
PrintWriter writer = httpServletResponse.getWriter();
Result result = new Result();
result.setCode(1);
result.setMessage("登录成功");
writer.write(new ObjectMapper().writeValueAsString(result));
writer.flush();
writer.close();
//httpServletResponse.sendRedirect("/index.html");
}
}