本文只作为spring官方文档的补充,不会解释spring以及hibernate的具体技术细节。
本文默认项目已经具有相关的用户表和DAO,现在我们以此为基础进行基本的用户登陆认证,url权限管理和登出设置。
网上有很多文档描述了如何为项目添加spring security支持。在spring boot中,我们只需要添加了配置类,就可以描述spring security的控制信息:
package edu.nju.web.security;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.context.annotation.Bean;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;
import javax.annotation.Resource;
/**
* Http security config
* @author cuiods
*/
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private UserDetailsService userService;
@Resource
private SuccessHandler successHandler;
@Resource
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{
auth
.userDetailsService(userService)
.passwordEncoder(standardEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.antMatchers("/api/admin/**").access("hasRole('admin')")
.and()
.formLogin()
.loginPage("/login")
.successHandler(successHandler)
.permitAll()
.and()
.logout()
.logoutUrl("/login?logout")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.permitAll()
.and()
.csrf();
}
/**
* standard password encoder: SHA-256
* @return {@link PasswordEncoder}
*/
@Bean
public PasswordEncoder standardEncoder() {
return new StandardPasswordEncoder();
}
}
在这个类中配置了URL对应的权限,登陆和注销对应的页面(spring security自带登陆页面,默认为/login,注销为/login?logout,具体可以查看官方文档)。
以上的代码的UserDetailsService是重点,UserDetailsService是一个接口,实现该接口可以定义从数据库取出的用户名、密码、权限等信息。有了这些信息,spring security可以自动进行密码验证和权限管理。
package edu.nju.bl.serviceImpl;
import edu.nju.data.dao.UserDao;
import edu.nju.data.entity.User;
import org.springframework.security.core.userdetails.UserDetailsService;
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.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* person service impl
*/
@Service
public class UserServiceImpl implements UserDetailsService {
@Resource
private UserDao userDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userDao.findByUsername(username);
if (user==null) {
throw new UsernameNotFoundException("Cannot find user!");
}
Set<GrantedAuthority> authorities = new HashSet<>();
authorities.add(new SimpleGrantedAuthority(user.getType().toString()));
List<GrantedAuthority> grantedAuthorities = new ArrayList<>(authorities);
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
true,true,true,true,grantedAuthorities);
}
}
将用户信息取出并封装成org.springframework.security.core.userdetails.User类(UserDetails的实现类),在上面的配置类中进行配置,spring就会自己管理用户的密码验证,并判断用户所处的角色。
另外,上面还提到了SuccessHandler,该类设置了登陆成功后的跳转界面。
package edu.nju.web.security;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
/**
* login success handler
* @author cuiods
*/
@Component
public class SuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Override
protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException {
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
String targetUrl = "";
if (authorities.contains("admin")) {
targetUrl = "/admin";
} else if (authorities.contains("teacher")) {
targetUrl = "/teacher";
} else {
targetUrl ="/student";
}
redirectStrategy.sendRedirect(request,response,targetUrl);
}
}
目前网上介绍的资料更多以简单的描述性示例为主。本文只是介绍了spring security的一个简单场景的应用,要全面了解spring security的相关内容,可以参见网上的官网文档和其他资料。