本文共 14532 字,大约阅读时间需要 48 分钟。
1)pom.xml文件添加依赖
org.springframework.boot spring-boot-starter-security
2)User类,实现了UserDetails
@lombok.Datapublic class User implements UserDetails { private int id; private String username; private String account; private String password; private String email; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") private Date createDate; private boolean isLockedOut; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") private Date lastLoginDate; private int incorrectLoginAttempt; private String realname; private String empId; private int roleId; private boolean isHintEnabled; private Listauthorities = new ArrayList<>(); @Override public Collection getAuthorities() { return authorities; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; }}
3)UserMapper接口
@Mapperpublic interface UserMapper extends BaseMapper{ public User findUserByUsername(String account); public User findUserByUsernameAndPassword(String account, String password); /**查询当前用户拥有的权限*/ public List findPermissionByUsername(String account); public List findAllMembersOfCorporation(Integer corporationId); public boolean insertOfReturnId(User user);}
4)Mybatis的xml文件
update tb_user_new set name=#{username}, account=#{account}, password=#{password}, email=#{email}, last_login_date=#{lastLoginDate} where id=#{id} insert into tb_user_new (name, account, password, email, create_date, last_login_date) values (#{username}, #{account}, #{password}, #{email}, #{createDate}, #{lastLoginDate}) select LAST_INSERT_ID() delete from tb_user_new where id=#{id}
5)自定义UserDetailsService接口的实现类
@Servicepublic class MyUserDetailService implements UserDetailsService { Logger logger = LoggerFactory.getLogger(getClass()); @Autowired UserMapper userMapper; @Override public UserDetails loadUserByUsername(String account) throws UsernameNotFoundException { System.out.println("loadUserByUsername"); //根据用户名查询用户信息 User user = userMapper.findUserByUsername(account); System.out.println("从数据库中查询出的用户信息:" + user); if(user != null){ //根据用户名查询当前用户所有权限 ListpermissionList = userMapper.findPermissionByUsername(account); //authorities: 存放所有用户权限 List authorities = new ArrayList<>(); for(Permission permission : permissionList){ GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getPermission()); authorities.add(grantedAuthority); } //把所有权限赋值给user user.setAuthorities(authorities); logger.info("当前用户为: "+user); }else{ System.out.println("用户不存在");// throw new UsernameNotFoundException("用户不存在!"); } return user; }}
6)自定义WebSecurityConfigurerAdapter的配置类
@EnableWebSecuritypublic class MySecurityConfig extends WebSecurityConfigurerAdapter { Logger logger = LoggerFactory.getLogger(getClass()); @Autowired MyUserDetailService myUserDetailService; //Control+O 打开重写方法 //定制请求的授权规则 @Override protected void configure(HttpSecurity http) throws Exception { System.out.println("进入到 MySecurityConfig的configure 方法中"); //super.configure(http); /*Spring Security 的默认构造器: 通过调用authorizeRequests()和 anyRequest().authenticated()就会要求所有进入应用的HTTP请求都要进行认证 http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin().and() .httpBasic(); //弹出一个输入用户名、密码的登录框 “/shop/hello” 和 “/shop/order” 这两个路径必须进过认证,并且 “/shop/order” 必须是 post 请求的方式. 对于其他的请求,我们都是 .anyRequest().permitAll() ;都放行. http.authorizeRequests() .antMatchers("/shop/hello").authenticated() .antMatchers(HttpMethod.POST,"/shop/order").authenticated() .anyRequest().permitAll(); antMatchers()方法所使用的路径可能会包括Ant风格的通配符,而regexMatchers()方法则能够接受正则表达式来定义请求路径。 */ // 基于token,所以不需要session http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // /**代表所有的请求 http.authorizeRequests()//方法表示开启了认证规则配置;定义哪些url需要保护,哪些url不需要保护; .antMatchers("/api/**").permitAll()//定义不需要认证就可以访问// .antMatchers("/session/**").permitAll()//定义不需要认证就可以访问// .antMatchers("/component/**").hasAuthority("ROLE_ADMIN") .antMatchers("/home/**").hasAnyAuthority("ROLE_DEV_APPLICATION","ROLE_ADMIN","ROLE_DEV_TERMINAL_IOS") .anyRequest().authenticated();其他的路径都是登录后即可访问// .and().formLogin().loginPage("/")//// //在successHandler中,使用response返回登录成功的json即可,切记不可以使用defaultSuccessUrl,defaultSuccessUrl是只登录成功后重定向的页面,failureHandler也是由于相同的原因不使用failureUrl。// .loginProcessingUrl("/login").successHandler(// new AuthenticationSuccessHandler(){// @Override// public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {// System.out.println(authentication.getDetails());// httpServletResponse.setContentType("application/json;charset=utf-8");// PrintWriter out = httpServletResponse.getWriter();// out.write("{\"status\":\"success\",\"msg\":\"登录成功\"}");// out.flush();// out.close();// }// }).failureHandler(// new 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("{\"status\":\"failed\",\"msg\":\"登录失败\"}");// out.flush();// out.close();// }// }); //http.logout()开启自动配置的注销功能 //1) 访问/logout 表示用户注销,清空session //2) 注销成功会返回/login?logout 页面 //3) logoutSuccessfulUrl 改变2)的设置 http.logout().logoutSuccessUrl("/login"); http.sessionManagement().invalidSessionUrl("/login"); http.rememberMe().rememberMeParameter("remember");// .usernameParameter("username").passwordParameter("password").defaultSuccessUrl("/");定义当需要用户登录时候,转到的登录页面// http.headers().frameOptions().disable();// .antMatchers("/level2/**").hasRole("VIP2")// .antMatchers("/level3/**").hasRole("VIP3"); //开启自动配置的登录功能。如果没有登录,没有权限就会来到登录页面 //1:/login来到登录页 //2:重定向/login?error表示登录失败 //3:更多详细规定 //http.formLogin().defaultSuccessUrl("/user/login.html"); /* iframe */ http.headers().frameOptions().sameOrigin(); // 运行同一个域名中的任何请求 http.csrf().disable(); // 默认是启用的,需要禁用CSRF保护(当不使用cookie时可以禁用csrf) http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); // 禁用缓存 http.headers().cacheControl(); } //定制请求的认证规则 @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { System.out.println("进入到 configureGlobal 方法中"); System.out.println("auth.userDetailsService(myUserDetailService):" + auth.userDetailsService(myUserDetailService)); //1)获取内存中的用户名和密码// auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("1").password(new BCryptPasswordEncoder().encode("1")).roles("USER");// .withUser("1").password(new BCryptPasswordEncoder().encode("1")).authorities("ROLE_TEST");// auth.authenticationProvider(authenticationProvider());// auth.userDetailsService(myUserDetailService).passwordEncoder(passwordEncoder()); //2)获取数据库中的用户名和密码 auth.userDetailsService(myUserDetailService).passwordEncoder(new PasswordEncoder() { @Override public String encode(CharSequence charSequence) { return charSequence.toString(); } @Override public boolean matches(CharSequence charSequence, String s) { return s.equals(charSequence.toString()); } }); } /* 通过AuthenticationProvider方式获取 */ @Bean public DaoAuthenticationProvider authenticationProvider() { System.out.println("进入到 authenticationProvider 方法中"); DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); authProvider.setUserDetailsService(myUserDetailService); authProvider.setPasswordEncoder(passwordEncoder()); return authProvider; } /** * 密码生成策略 * @return */ @Bean public BCryptPasswordEncoder passwordEncoder() { System.out.println("进入到 passwordEncoder 方法中"); return new BCryptPasswordEncoder(); } @Bean public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception { System.out.println("进入到 authenticationTokenFilterBean 方法中"); return new JwtAuthenticationTokenFilter(); }}
7)LoginController
@RestController@RequestMapping(value = "api/umeapiplus/login")public class LoginController { @Autowired MyUserDetailService myUserDetailService; @Autowired JwtTokenUtils jwtTokenUtils; @Autowired BCryptPasswordEncoder bCryptPasswordEncoder; @RequestMapping(value = "/login", method = RequestMethod.POST) public Maplogin(@RequestBody JSONObject requestParam){ System.out.println("前端传递过来的登陆信息参数:" + JSONObject.toJSONString(requestParam)); Map returnMap = new HashMap<>(); String account = requestParam.getString("account"); String password = requestParam.getString("password"); User user = (User) myUserDetailService.loadUserByUsername(account); System.out.println("返回的用户信息:" + user); if(user == null){ System.out.println("账号不存在"); returnMap.put("code", 400); returnMap.put("msg", "账号不存在"); returnMap.put("data", null); returnMap.put("token", null); }else { // 正常应该是从user.getPassword()得到数据库中的加密密码 String encodedPassword = bCryptPasswordEncoder.encode(password); System.out.println("原始密码:" + password + " bcr加密后的密码:" + encodedPassword); boolean compareRes = bCryptPasswordEncoder.matches(password, encodedPassword); System.out.println("compareRes: " + compareRes); if(!compareRes){ System.out.println("密码错误"); returnMap.put("code", 400); returnMap.put("msg", "密码错误"); returnMap.put("data", null); returnMap.put("token", null); }else { String token = jwtTokenUtils.generateToken(user); System.out.println("根据用户名和密码生成的token信息:" + token); returnMap.put("code", 200); returnMap.put("msg", "登录成功"); returnMap.put("data", user); returnMap.put("token", token); } } return returnMap; }}
1)main.js
import Vue from 'vue'import Antd from 'ant-design-vue'import 'ant-design-vue/dist/antd.css'import axios from 'axios'Vue.prototype.axios = axiosimport store from './store'import router from './router'import App from './App.vue'import './css/style.css'Vue.use(Antd);Vue.config.productionTip = falserouter.beforeEach((to, from, next) => { console.log('to.path: ' + to.path); if (to.path === '/') { next(); } else { if (window.sessionStorage.getItem("user")) { next(); } }})new Vue({ store, router, render: h => h(App),}).$mount('#app')
2)vue-router的index.js
import Vue from 'vue'import Router from 'vue-router'import Login from '../components/login/Login.vue'import HomePage from '../components/New/HomePage.vue'Vue.use(Router)export default new Router({ base: '/dist/', //添加的地方 routes: [ { path: '/', name: 'Login', component: Login, hidden: true }, { path: '/home', name: 'Home', component: HomePage, hidden: true, meta: { roles: ['admin', 'user'] } }, { path: '*', redirect: '/home' } ]})
3)Login.vue
系统登录
用户名为邮箱前缀,密码为123456登录
转载地址:http://getii.baihongyu.com/