org.springframework.boot
spring-boot-starter-security
**
**
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyFilterSecurityInterceptor myFilterSecurityInterceptor;
@Autowired
private UserService userService;
@Autowired
private AuthenticationAccessDeniedHandler accessDeniedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/user/usercontroller/login_page")
.loginProcessingUrl("/user/usercontroller/login").permitAll()
.and()
.authorizeRequests() // 定义哪些URL需要被保护、哪些不需要被保护
.antMatchers("/user/usercontroller/login_page").permitAll() // 设置所有人都可以访问的路径
.anyRequest() // 任何请求,登录后可以访问
.authenticated()
.and()
.csrf().disable(); // 关闭csrf防护
http.addFilterBefore(myFilterSecurityInterceptor,FilterSecurityInterceptor.class);
//用重写的Filter替换掉原有的UsernamePasswordAuthenticationFilter
http.addFilterAt(customAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
}
//注册自定义的UsernamePasswordAuthenticationFilter
@Bean
CustomAuthenticationFilter customAuthenticationFilter() throws Exception {
CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
filter.setAuthenticationSuccessHandler(new SuccessHandler());
filter.setAuthenticationFailureHandler(new FailureHandler());
filter.setFilterProcessesUrl("/user/usercontroller/login");
//这句很关键,重用WebSecurityConfigurerAdapter配置的AuthenticationManager,不然要自己组装AuthenticationManager
filter.setAuthenticationManager(authenticationManagerBean());
return filter;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(new PasswordEncoder() {
@Override
public String encode(CharSequence rawPassword) {
return Md5Utils.encryptPassword((String) rawPassword, (String) rawPassword);
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encodedPassword.equals(Md5Utils.encryptPassword((String) rawPassword,(String) rawPassword));
}
});
}
}
@Service
public class UserServiceImpl implements UserService,UserDetailsService {
@Autowired
UserMapper userDao;
@Autowired
PermissionMapper permissionDao;
@Override
public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException {
User user = userDao.loadUserByUsername(username);
if (user != null) {
List permissions = permissionDao.getAllowsPermissions(user.getId());
List grantedAuthorities = new ArrayList <>();
for (Permission permission : permissions) {
if (permission != null && permission.getCode()!=null) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getCode());
//1:此处将权限信息添加到 GrantedAuthority 对象中,在后面进行全权限验证时会使用GrantedAuthority 对象。
grantedAuthorities.add(grantedAuthority);
}
}
user.setPermission(grantedAuthorities);
return user;
} else {
throw new ServiceException("admin: " + username + " do not exist!");
}
}
}
/**
*
* 用户
*
* @author liuwei
*
*/
public class User implements Serializable,UserDetails {
private static final long serialVersionUID = 6981667711419946989L;
// '主键' id
private Integer id;
// '用户名'
private String userName;
// '密码'
private String passWord;
// '中文名'
private String chineseName;
// '账号状态 0:正常使用 1:禁用'
private Integer statu;
// '角色类型',
private Integer roleId;
// '办公电话'
private String phoneNumber;
// '手机号'
private String mobilePhone;
// '所属组织机构',
private Integer company;
// '邮箱'
private String email;
// '更新时间',
private Date updateTime;
// '更新人'
private String updateUser;
// '创建时间',
private Timestamp createTime;
// '创建人id',
private String createrPerson;
private Collection extends GrantedAuthority> permission;
public void setPermission(Collection extends GrantedAuthority> permission) {
this.permission = permission;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public String getChineseName() {
return chineseName;
}
public void setChineseName(String chineseName) {
this.chineseName = chineseName;
}
public Integer getStatu() {
return statu;
}
public void setStatu(Integer statu) {
this.statu = statu;
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getMobilePhone() {
return mobilePhone;
}
public void setMobilePhone(String mobilePhone) {
this.mobilePhone = mobilePhone;
}
public Integer getCompany() {
return company;
}
public void setCompany(Integer company) {
this.company = company;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public String getUpdateUser() {
return updateUser;
}
public void setUpdateUser(String updateUser) {
this.updateUser = updateUser;
}
public Timestamp getCreateTime() {
return createTime;
}
public void setCreateTime(Timestamp createTime) {
this.createTime = createTime;
}
public String getCreaterPerson() {
return createrPerson;
}
public void setCreaterPerson(String createrPerson) {
this.createrPerson = createrPerson;
}
@Override
public Collection extends GrantedAuthority> getAuthorities() {
return permission;
}
@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;
}
}
/**
* AuthenticationFilter that supports rest login(json login) and form login.
* @author 刘维
*/
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@SuppressWarnings("finally")
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
String param= null;
//Content-Type is json 自己去实现 json解析
if(request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)
||request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)){
UsernamePasswordAuthenticationToken authRequest=null;
try (InputStream is = request.getInputStream()){
BufferedReader streamReader = new BufferedReader( new InputStreamReader(request.getInputStream(), "UTF-8"));
StringBuilder responseStrBuilder = new StringBuilder();
String inputStr;
while ((inputStr = streamReader.readLine()) != null)
responseStrBuilder.append(inputStr);
JSONObject jsonObject = JSONObject.parseObject(responseStrBuilder.toString());
param= jsonObject.toJSONString();
AuthenticationBean bean=(AuthenticationBean) JSONUtils.jsonToBean(param, new AuthenticationBean());
authRequest=new UsernamePasswordAuthenticationToken(bean.getUserName(),bean.getPassword());
}catch (IOException e) {
e.printStackTrace();
authRequest = new UsernamePasswordAuthenticationToken("", "");
}finally {
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
}
//transmit it to UsernamePasswordAuthenticationFilter
else {
return super.attemptAuthentication(request, response);
}
}
}
public class JSONUtils {
/**
* Bean对象转JSON
*
* @param object
* @param dataFormatString
* @return
*/
public static String beanToJson(Object object, String dataFormatString) {
if (object != null) {
if (StringUtils.isEmpty(dataFormatString)) {
return JSONObject.toJSONString(object);
}
return JSON.toJSONStringWithDateFormat(object, dataFormatString);
} else {
return null;
}
}
/**
* Bean对象转JSON
*
* @param object
* @return
*/
public static String beanToJson(Object object) {
if (object != null) {
return JSON.toJSONString(object);
} else {
return null;
}
}
/**
* String转JSON字符串
*
* @param key
* @param value
* @return
*/
public static String stringToJsonByFastjson(String key, String value) {
if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
return null;
}
Map map = new HashMap();
map.put(key, value);
return beanToJson(map, null);
}
/**
* 将json字符串转换成对象
*
* @param json
* @param clazz
* @return
*/
public static Object jsonToBean(String json, Object clazz) {
if (StringUtils.isEmpty(json) || clazz == null) {
return null;
}
return JSON.parseObject(json, clazz.getClass());
}
/**
* json字符串转map
*
* @param json
* @return
*/
@SuppressWarnings("unchecked")
public static Map jsonToMap(String json) {
if (StringUtils.isEmpty(json)) {
return null;
}
return JSON.parseObject(json, Map.class);
}
}
/**
* Created by 刘维
*/
@Component
public class AuthenticationAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse resp, AccessDeniedException e) throws IOException, ServletException {
resp.setStatus(HttpServletResponse.SC_OK);
resp.setContentType("application/json;charset=UTF-8");
PrintWriter out = resp.getWriter();
out.write("{\"status\":\"200\",\"msg\":\"权限不够,请联系管理员!\"}");
out.flush();
out.close();
}
}
public class AuthenticationBean {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
**
* Created by 刘维.
*/
@Configuration
public class MyInvocationSecurityMetadataSourceService implements
FilterInvocationSecurityMetadataSource {
@Autowired
private PermissionMapper permissionDao;
private HashMap> map = null;
/**
* 加载权限表中所有权限
*/
public void loadResourceDefine() {
map = new HashMap<>();
Collection array;
ConfigAttribute cfg;
List permissions = permissionDao.getAllPermissions();
for (Permission permission : permissions) {
array = new ArrayList<>();
if(permission.getCode()!=null){
cfg = new SecurityConfig(permission.getCode());
// 此处只添加了用户的名字,其实还可以添加更多权限的信息,例如请求方法到ConfigAttribute的集合中去。此处添加的信息将会作为MyAccessDecisionManager类的decide的第三个参数。
array.add(cfg);
// 用权限的getUrl() 作为map的key,用ConfigAttribute的集合作为 value,
map.put(permission.getHref(), array);
}
}
}
// 此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。
@Override
public Collection getAttributes(Object object)throws IllegalArgumentException {
if (map == null)
loadResourceDefine();
// object 中包含用户请求的request 信息
HttpServletRequest request = ((FilterInvocation) object)
.getHttpRequest();
AntPathRequestMatcher matcher;
String resUrl;
for (Iterator iter = map.keySet().iterator(); iter.hasNext();) {
resUrl = iter.next();
matcher = new AntPathRequestMatcher(resUrl);
if (matcher.matches(request)) {
return map.get(resUrl);
}
}
return null;
}
@Override
public Collection getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class> clazz) {
return true;
}
}