码云地址:https://gitee.com/huatao1994/springSecuritycss
/* Navicat MySQL Data Transfer Source Server : localhost Source Server Version : 50529 Source Host : localhost:3306 Source Database : security Target Server Type : MYSQL Target Server Version : 50529 File Encoding : 65001 Date: 2019-12-21 14:04:04 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `authority_menu` -- ---------------------------- DROP TABLE IF EXISTS `authority_menu`; CREATE TABLE `authority_menu` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `url` varchar(255) DEFAULT NULL COMMENT '请求路径', `menu_name` varchar(255) DEFAULT NULL COMMENT '菜单名称', `parent_id` int(11) DEFAULT NULL COMMENT '父菜单id', `update_time` varchar(255) DEFAULT NULL COMMENT '更新时间', `remark` varchar(255) DEFAULT NULL COMMENT '备注', `url_pre` varchar(255) DEFAULT NULL COMMENT '路由(前端本身匹配用)', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of authority_menu -- ---------------------------- -- ---------------------------- -- Table structure for `authority_role` -- ---------------------------- DROP TABLE IF EXISTS `authority_role`; CREATE TABLE `authority_role` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `role_name` varchar(255) DEFAULT NULL COMMENT '角色名称(必须以ROLE_起始命名)', `role_name_CN` varchar(255) DEFAULT NULL COMMENT '角色名称中文', `update_time` varchar(255) DEFAULT NULL COMMENT '更新时间', `remark` varchar(255) DEFAULT NULL COMMENT '备注', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of authority_role -- ---------------------------- -- ---------------------------- -- Table structure for `authority_role_menu` -- ---------------------------- DROP TABLE IF EXISTS `authority_role_menu`; CREATE TABLE `authority_role_menu` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `role_id` int(11) DEFAULT NULL, `menu_id` int(11) DEFAULT NULL, `update_time` varchar(255) DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of authority_role_menu -- ---------------------------- -- ---------------------------- -- Table structure for `authority_user` -- ---------------------------- DROP TABLE IF EXISTS `authority_user`; CREATE TABLE `authority_user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `username` varchar(255) DEFAULT NULL COMMENT '用户名', `password` varchar(255) DEFAULT NULL COMMENT '密码', `email` varchar(255) DEFAULT NULL COMMENT '邮箱', `phone` varchar(255) DEFAULT NULL COMMENT '手机号', `valid_time` varchar(255) DEFAULT NULL COMMENT '有效截止时间', `update_time` varchar(255) DEFAULT NULL COMMENT '更新时间', `remark` mediumtext COMMENT '备注', `nickname` varchar(255) DEFAULT NULL COMMENT '昵称', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of authority_user -- ---------------------------- -- ---------------------------- -- Table structure for `authority_user_role` -- ---------------------------- DROP TABLE IF EXISTS `authority_user_role`; CREATE TABLE `authority_user_role` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `user_id` int(11) DEFAULT NULL, `role_id` int(11) DEFAULT NULL, `update_time` varchar(255) DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=74 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of authority_user_role -- ---------------------------- -- ---------------------------- -- Table structure for `persistent_logins` -- ---------------------------- DROP TABLE IF EXISTS `persistent_logins`; CREATE TABLE `persistent_logins` ( `username` varchar(64) NOT NULL, `series` varchar(64) NOT NULL, `token` varchar(64) NOT NULL, `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`series`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of persistent_logins -- ----------------------------
package cn.**.controller; import cn.**.dao.UserDao; import cn.**.service.UserService1; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.controller * @Author: huat * @Date: 2019/12/12 14:56 * @Version: 1.0 */ @RestController public class UserController { @Autowired UserService1 userService1; //@Secured("ROLE_ADMIN")//security权限注解 //@RolesAllowed("ROLE_ADMIN") //jsr250注解 //@PreAuthorize("hasRole('ROLE_ADMIN')")//spring的注解 @RequestMapping("/login") public String login(String username,String password){ //获取登录的用户名 String username1= SecurityContextHolder.getContext().getAuthentication().getName(); System.out.println(username); return "index"; } @RequestMapping("test") public String test(){ return "hello test"; } }
package cn.**.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.controller * @Author: huat * @Date: 2019/12/16 15:16 * @Version: 1.0 */ @Controller public class IntoController { @RequestMapping("intoTest") public String intoTest(){ return "/test"; } @RequestMapping("intoIndex") public String intoIndex(){ return "index"; } @RequestMapping("intoFail") public String intoFail(){ return "fail"; } @RequestMapping("intoLogin") public String intoLogin(){ return "login"; } @RequestMapping("dologin") public String dologin(){ return "index"; } }
package cn.**.entity; import com.fasterxml.jackson.annotation.JsonIgnore; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; import java.util.List; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.entity * @Author: huat * @Date: 2019/12/12 15:12 * @Version: 1.0 * 建立实体类第一种方式 */ public class AuthorityUser implements UserDetails { private int id; private String username; private String password; private List<AuthorityRole> authorityRoles; public int getId() { return id; } public void setId(int 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 List<AuthorityRole> getAuthorityRoles() { return authorityRoles; } public void setAuthorityRoles(List<AuthorityRole> authorityRoles) { this.authorityRoles = authorityRoles; } @Override @JsonIgnore//忽略此属性 转成json字符串时不进行转换 public Collection<? extends GrantedAuthority> getAuthorities() { return authorityRoles; } @Override @JsonIgnore//忽略此属性 转成json字符串时不进行转换 public boolean isAccountNonExpired() { return true; } @Override @JsonIgnore//忽略此属性 转成json字符串时不进行转换 public boolean isAccountNonLocked() { return true; } @Override @JsonIgnore//忽略此属性 转成json字符串时不进行转换 public boolean isCredentialsNonExpired() { return true; } @Override @JsonIgnore//忽略此属性 转成json字符串时不进行转换 public boolean isEnabled() { return true; } }
package cn.**.entity; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonAppend; import org.springframework.security.core.GrantedAuthority; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.entity * @Author: huat * @Date: 2019/12/12 16:14 * @Version: 1.0 */ public class AuthorityRole implements GrantedAuthority { private int rid; private String roleName; private String roleNameCN; public int getRid() { return rid; } public void setRid(int rid) { this.rid = rid; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public String getRoleNameCN() { return roleNameCN; } public void setRoleNameCN(String roleNameCN) { this.roleNameCN = roleNameCN; } @JsonIgnore//忽略此属性 转成json字符串时不进行转换 @Override public String getAuthority() { return roleName; } }
package cn.**.entity; /** * @ProjectName: springbootSecurity * @Package: cn.*.security.entity * @Author: huat * @Date: 2019/12/16 18:45 * @Version: 1.0 */ public class AuthorityMenu { private int id; private String url; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
package cn.**.service; import org.springframework.security.core.userdetails.UserDetailsService; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.service * @Author: huat * @Date: 2019/12/12 17:35 * @Version: 1.0 */ //UserDetailsService 是security中的类 public interface UserService extends UserDetailsService { }
package cn.**.service; import cn.**.dao.UserDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; /** * @ProjectName: springbootSecurity * @Package: cn.**.utile * @Author: huat * @Date: 2019/12/12 14:48 * @Version: 1.0 */ @Service//将这个类注入到spring容器中 public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { return userDao.getUser(s); } public static void main(String[] args) { BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder(); //passwordEncoder.encode("123456")加密方法 //执行屡次加密后的结果均不同 //执行第一次:$2a$10$RSlzzO4xAubBLZMB8jPL8eMFX17gM61JfrgINpzOiaEsBdtKBuSDe //执行第二次:$2a$10$2uQWdP9qAXGK4H0um0gtG.o1QzbGhBlbxx8YjX526jIrVBNKyziFe //执行第三次:$2a$10$8CWttAISfamloSErsqEAPemALyZvj8VWaUCBJKcm2GE1dhFR.7oYG //security加密方式是动态加盐 System.out.println(passwordEncoder.encode("123456")); //比较明文和密文是否一致 System.out.println(passwordEncoder.matches("123456","$2a$10$lstWyJ6NlbdZ2uVr8ncsHOUKsG0VAT4FzDdy0gqy6gbaOqpp6ouDq")); } }
package cn.**.dao; import cn.**.entity.AuthorityUser; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.dao * @Author: huat * @Date: 2019/12/12 15:04 * @Version: 1.0 */ @Mapper public interface UserDao { /** * 根据用户名查询角色 * @param username 用户名 * @return */ AuthorityUser getUser(@Param("username") String username); /** * 添加用户 * @param username 用户名 * @param password 密码 * @return */ int saveUser(@Param("username") String username, @Param("password") String password); }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.**.dao.UserDao"> <resultMap id="userRole" type="authorityUser"> <id column="id" property="id"></id> <result column="username" property="username"></result> <result column="password" property="password"></result> <collection property="authorityRoles" ofType="authorityRole"> <id column="rid" property="rid"></id> <result property="roleName" column="role_name"></result> <result property="roleNameCN" column="role_name_CN"></result> </collection> </resultMap> <select id="getUser" resultMap="userRole"> select u.*,r.id rid,r.role_name,r.role_name_CN from authority_user u left join authority_user_role ur on ur.user_id=u.id left join authority_role r on ur.role_id=r.id where username=#{username} </select> <insert id="saveUser"> insert into authority_user(username,password) values(#{username},#{password}) </insert> </mapper>
package cn.**.util; import cn.**.service.UserService; import cn.**.service.UserService1; import org.springframework.beans.factory.annotation.Autowired; 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; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.util * @Author: huat * @Date: 2019/12/14 8:06 * @Version: 1.0 */ /** * 开启security注解支持 * @EnableWebSecurity * (securedEnabled=true) 开启@Secured 注解过滤权限 * (jsr250Enabled=true)开启@RolesAllowed 注解过滤权限 * (prePostEnabled=true) 使用表达式时间方法级别的安全性 4个注解可用 * @EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled=true,jsr250Enabled=true) */ @Configuration @EnableWebSecurity //@EnableGlobalMethodSecurity(prePostEnabled = true) @EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled=true,jsr250Enabled=true) public class SpringSercurityConfig extends WebSecurityConfigurerAdapter { /* @Autowired UserService1 userService;*/ @Autowired UserService userService; @Autowired AuthenticationSuccessHandler authenticationSuccessHandler;//ajax登录成功使用 @Autowired AuthenticationFailureHandler authenticationFailureHandler;//ajax登录失败使用 /** * 将security中加密方式注入到spring容器中 * @return */ @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } /** * 将帐号密码设置在数据库当中 * @param auth * @throws Exception */ @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth //将UserDetailsService放到容器中 .userDetailsService(userService) //加密方式放入 .passwordEncoder(passwordEncoder()); } @Override public void configure(HttpSecurity http) throws Exception { //释放静态资源,指定资源拦截规则, // 指定自定义认证页面,指定退出认证配置,csrf(跨域伪造请求)配置 http.authorizeRequests() .antMatchers("intoLogin","login.jsp","/css/**","fail.jsp","/intoIndex","/index.jsp").permitAll()//释放这些资源,容许匿名访问 .antMatchers("/**").hasAnyRole("ADMIN","USER") .anyRequest().authenticated()//其余资源须要认证 .and() .formLogin() .loginPage("/intoLogin")//登录页请求的接口 .loginProcessingUrl("/dologin")//登录地址,由springSecurity提供 .successForwardUrl("/intoTest")//登录成功 .failureForwardUrl("/intoFail")//登陆失败 .permitAll()//指定全部资源释放 .and() .logout()//登出 .logoutUrl("/logout")//指定登出路径 .logoutSuccessUrl("/login.jsp")//登出成功后跳转的url .invalidateHttpSession(true)//是否清空session .permitAll() .and() .csrf() .disable();//关闭csrf(跨域伪造请求) } /* *//** * ajax 登录 * @param http * @throws Exception *//* @Override public void configure(HttpSecurity http) throws Exception { //释放静态资源,指定资源拦截规则, // 指定自定义认证页面,指定退出认证配置,csrf(跨域伪造请求)配置 http.authorizeRequests() .antMatchers("intoLogin","login.jsp","/css/**","fail.jsp","/intoIndex","/index.jsp").permitAll()//释放这些资源,容许匿名访问 .antMatchers("/**").hasAnyRole("ADMIN","USER") .antMatchers("/test").hasRole("USER") .anyRequest().authenticated()//其余资源须要认证 .and() .formLogin() .loginPage("/intoLogin")//登录页请求的接口 .successHandler(authenticationSuccessHandler)//登录成功后返回的数据 .failureHandler(authenticationFailureHandler) .loginProcessingUrl("/login")//登录地址,由springSecurity提供 .usernameParameter("name") .passwordParameter("pwd") .permitAll()//指定全部资源释放 .and() .logout()//登出 .logoutUrl("/logout")//指定登出路径 .logoutSuccessUrl("/login.jsp")//登出成功后跳转的url .invalidateHttpSession(true)//是否清空session .permitAll() .and() .cors() .and() .csrf() .disable() ;//关闭csrf(跨域伪造请求) }*/ }
package cn.**.controller; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @ProjectName: springSecurity * @Package: cn.**.controller * @Author: huat * @Date: 2019/12/23 9:43 * @Version: 1.0 * * 处理异常页面 */ @Controller public class MyException implements ErrorController { private static Logger log = LoggerFactory.getLogger(MyException.class); @RequestMapping("/error") public String handleError(HttpServletRequest request) { log.info("进入异常跳转"); Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code"); switch (statusCode) { case 404: log.info("404异常跳转"); return "fail"; case 403: log.info("403异常跳转"); return "403"; case 500: log.info("500异常跳转"); return "/error/500"; default: log.info("默认异常跳转"); return "/error/404"; } } @Override public String getErrorPath() { return "/error"; } }
package cn.**.util; import com.alibaba.fastjson.JSON; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.stereotype.Component; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; /** * @ProjectName: securityAjax * @Package: cn.**.util * @Author: huat * @Date: 2019/12/26 9:50 * @Version: 1.0 * 登录成功返回 */ @Component public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { Map<String,Object> map=new HashMap<String,Object>(); map.put("code",500); map.put("msg","登录失败"); map.put("data",""); /* httpServletResponse.setContentType("application/json;charset=utf-8");*/ PrintWriter out = httpServletResponse.getWriter(); out.write(JSON.toJSONString(map)); out.flush(); out.close(); } }
package cn.**.util; import com.alibaba.fastjson.JSON; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Component; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; /** * @ProjectName: securityAjax * @Package: cn.**.util * @Author: huat * @Date: 2019/12/26 9:41 * @Version: 1.0 */ @Component public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { System.out.println(httpServletRequest.getParameter("name")); Map<String,Object> map=new HashMap<String,Object>(); map.put("code",200); map.put("msg","登录成功"); map.put("data",""); /* httpServletResponse.setContentType("application/json;charset=utf-8");*/ PrintWriter out = httpServletResponse.getWriter(); out.write(JSON.toJSONString(map)); out.flush(); out.close(); } }