1:添加依赖:
<dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
2:创建验证service集成UserDetailService
package com.qingwenwei.security; import java.util.ArrayList; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import com.qingwenwei.persistence.model.User; import com.qingwenwei.service.UserService; import org.springframework.stereotype.Service;
//授权认证
@Service public class MyUserDetailsService implements UserDetailsService{ Logger logger = LogManager.getLogger(MyUserDetailsService.class); @Autowired private UserService userService; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { logger.debug("得到用户"); User user = this.userService.findByUsername(username); //加密之后的密码。才能进行下面的授权认证。 logger.debug(user.getUsername()+"密码"+user.getPassword()); //加密之后的密码。 if(null == user) { throw new UsernameNotFoundException("Can't find user by username: " + username); } List<SimpleGrantedAuthority> grantedAuthorities = new ArrayList<>(); // grant roles to user for (String role : user.getRolesSet()) { logger.debug(role); grantedAuthorities.add(new SimpleGrantedAuthority(role)); } // user.setGrantedAuthorities(authorities); //用于登录时 @AuthenticationPrincipal 标签取值 return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities); } }
3:进行配置
package com.qingwenwei.security; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; 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.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled=true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean public BCryptPasswordEncoder bCryptPasswordEncoder() { return new BCryptPasswordEncoder(); } @Autowired MyUserDetailsService myUserDetailsService; // @Bean // UserDetailsService myUserDetailsService() { // register userDetailsService // return new MyUserDetailsService(); // } @Bean public AuthenticationProvider authenticationProvider() { DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); // authenticationProvider.setUserDetailsService(this.myUserDetailsService()); authenticationProvider.setUserDetailsService(myUserDetailsService); authenticationProvider.setPasswordEncoder(this.bCryptPasswordEncoder()); return authenticationProvider; } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { //全局配置 // auth.inMemoryAuthentication() //內存中存在的验证 // .withUser("t").password("t").roles("USER") // .and() // .withUser("admin").password("admin").roles("ADMIN"); auth.userDetailsService(myUserDetailsService).passwordEncoder(this.bCryptPasswordEncoder()); // auth.userDetailsService(myUserDetailsService).passwordEncoder(new BCryptPasswordEncoder()); // auth.authenticationProvider(this.authenticationProvider()); // different approach } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/user/settings").authenticated() // order matters .antMatchers("/", "/js/**", "/css/**","/avatar/**", "/images/**", "/fonts/**", "/bootstrap-select/**", "/bootstrap-datetimepicker/**", "/custom/**", "/daterangepicker/**", "/chartjs/**").permitAll() // these paths are configure not to require any authentication .antMatchers("/post/**").permitAll() // all posts are allowed to be viewed without authentication .antMatchers("/user/**").permitAll() // all user profiles are allowed to be viewed without authentication .antMatchers("/category/**").permitAll() // all categories are allowed to be viewed without authentication .antMatchers("/user/registration").permitAll() .antMatchers("/avatar/**").permitAll() // temp .antMatchers("/avatar1/**").permitAll() // temp .anyRequest().authenticated() // every request requires the user to be authenticated .and() .formLogin() .loginPage("/user/login") .permitAll() // login URL can be accessed by anyone .and() .logout() .invalidateHttpSession(true) .clearAuthentication(true) .logoutSuccessUrl("/?logout") .permitAll(); } }
4:userController.java
package com.qingwenwei.web.controller; import com.qingwenwei.exception.BadRequestException; import com.qingwenwei.exception.ResourceNotFoundException; import com.qingwenwei.persistence.model.User; import com.qingwenwei.service.UserService; import com.qingwenwei.util.NewUserFormValidator; import com.qingwenwei.web.dto.UserRegistrationDto; import com.qingwenwei.web.dto.UserSettingsDto; import org.apache.catalina.servlet4preview.http.HttpServletRequest; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.Map; @Controller public class UserController { Logger logger = LogManager.getLogger(UserController.class); // private static final Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired private UserService userService; @Autowired private NewUserFormValidator userValidator; @RequestMapping(value = "/user/{userId}", method = RequestMethod.GET) public String showUserProfilePage(@RequestParam(value = "tab", required = false) String tabType, @PathVariable Long userId, Model model) { if (null == userId) { throw new BadRequestException("Path variable userId cound not be null."); } Map<String, Object> attributes = this.userService.getUserProfileAndPostsByUserIdByTabType(userId, tabType); if (null == attributes) { throw new ResourceNotFoundException("attributes not found."); } model.addAllAttributes(attributes); return "forum/user-profile"; } @RequestMapping(value = "/user/registration", method = RequestMethod.GET) public String showRegistrationPage(Model model) { model.addAttribute("userDto", new UserRegistrationDto()); return "forum/user-registration"; //注册页面 } @RequestMapping(value = "/user/registration", method = RequestMethod.POST) //提交注册 public String registerNewUser(@Valid @ModelAttribute("userDto") UserRegistrationDto userDto, BindingResult bindingResult, Model model, HttpServletRequest request) { /* * form validation, check username and email uniqueness */ this.userValidator.validate(userDto, bindingResult); if (bindingResult.hasErrors()) { logger.info("BindingResult has errors >> " + bindingResult.getFieldError()); return "forum/user-registration"; } logger.debug("注册"+userDto.getMatchingPassword()); Map<String, Object> attributes = this.userService.registerUserAccount(userDto, request); if (null == attributes) { throw new ResourceNotFoundException("attributes not found."); } model.addAllAttributes(attributes); return "forum/user-registration-result"; } @RequestMapping(value = "/user/login", method = RequestMethod.GET) public String displayLoginPage(Model model) { logger.debug("user/login登录"); model.addAttribute("title", "用户登陆"); return "forum/user-login"; //登录界面,验证没通过。 } @RequestMapping(value = "/user/login-success", method = RequestMethod.GET) public String showAdminPage() { logger.debug("登录成功"); return "forum/user-login"; // return "/"; } @RequestMapping(value = "/confirm", method = RequestMethod.GET) public String confirmRegistration(@RequestParam("token") String token) { return "forum/confirmation"; } @RequestMapping(value = "/confirm", method = RequestMethod.POST) public String processConfirmation() { return "forum/confirmation"; } @RequestMapping(value = "/user/settings", method = RequestMethod.GET) public String showUserSettingsPage(Model model) { Map<String, Object> attributes = this.userService.getUserSettingPage(); if (null == attributes) { throw new ResourceNotFoundException("attributes not found."); } model.addAllAttributes(attributes); return "forum/user-settings"; } @RequestMapping(value = "/user/settings", method = RequestMethod.POST) public String handleFileUpload(@ModelAttribute("userSettingsDto") UserSettingsDto userSettingsDto, Model model) { // User byConfirmationToken = userService.findByConfirmationToken(userSettingsDto.getPasswordConfirmation()); // logger.debug(byConfirmationToken.getPassword()); // logger.debug(userSettingsDto.getPassword()); if (null == userSettingsDto) { throw new BadRequestException("UserSettingsDto cound not be null."); } Map<String, Object> attributes = this.userService.updateUserProfile(userSettingsDto); if (null == attributes) { throw new ResourceNotFoundException("attributes not found."); } model.addAllAttributes(attributes); return "forum/user-settings"; } }
5:UserService.java UserServiceImpl.java
package com.qingwenwei.service; import com.qingwenwei.persistence.model.User; import com.qingwenwei.web.dto.UserRegistrationDto; import com.qingwenwei.web.dto.UserSettingsDto; import javax.servlet.http.HttpServletRequest; import java.util.Map; public interface UserService { int save(User user); User findById(Long id); User findByUsername(String username); User findByEmail(String email); User findByConfirmationToken(String confirmationToken); User findAuthenticatedUser(); Map<String, Object> getUserProfileAndPostsByUserIdByTabType(Long userId, String tabType); Map<String, Object> updateUserProfile(UserSettingsDto newUserSettingsForm); Map<String, Object> getUserSettingPage(); Map<String, Object> registerUserAccount(UserRegistrationDto userDto, HttpServletRequest request); }
package com.qingwenwei.service.impl; import com.qingwenwei.event.OnRegistrationCompleteEvent; import com.qingwenwei.persistence.dao.CommentMapper; import com.qingwenwei.persistence.dao.PostMapper; import com.qingwenwei.persistence.dao.UserMapper; import com.qingwenwei.persistence.model.Comment; import com.qingwenwei.persistence.model.Post; import com.qingwenwei.persistence.model.User; import com.qingwenwei.service.StorageService; import com.qingwenwei.service.UserService; import com.qingwenwei.web.dto.UserRegistrationDto; import com.qingwenwei.web.dto.UserSettingsDto; import org.apache.logging.log4j.LogManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.sql.Timestamp; import java.util.*; @Service("userService") public class UserServiceImpl implements UserService { // private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class); org.apache.logging.log4j.Logger logger = LogManager.getLogger(UserServiceImpl.class); @Autowired private UserMapper userMapper; @Autowired private PostMapper postMapper; @Autowired private CommentMapper commentMapper; // @Autowired // private VerificationTokenMapper verificationTokenMapper; @Autowired private StorageService storageService; @Autowired private BCryptPasswordEncoder bCryptPasswordEncoder; @Autowired private ApplicationEventPublisher evenPublisher; @Override public User findById(Long id) { return userMapper.findById(id); } @Override public User findByEmail(String email) { return userMapper.findByEmail(email); } @Override public User findByConfirmationToken(String confirmationToken) { return userMapper.findByConfirmationToken(confirmationToken); } @Override public User findByUsername(String username) { return userMapper.findByUsername(username); } @Override //重置密码 public int save(User user) { user.setPassword(bCryptPasswordEncoder.encode(user.getPassword())); //保存时应该将密码编码 return userMapper.save(user); } // @Override // public int save(User user) { // user.setPassword(user.getPassword()); // return userMapper.save(user); // } @Override public Map<String, Object> getUserProfileAndPostsByUserIdByTabType(Long userId, String tabType) { if (null == userId) { return null; } User user = this.userMapper.findById(userId); if (null == user) { return null; } Map<String, Object> attributes = new HashMap<>(); attributes.put("user", user); String activeTab = tabType == null ? "posts" : tabType; if ("posts".equalsIgnoreCase(activeTab)) { List<Post> posts = this.postMapper.findPostsByUserId(userId); attributes.put("posts", posts); } else if ("comments".equalsIgnoreCase(activeTab)) { List<Comment> comments = this.commentMapper.findCommentsByUserId(userId); attributes.put("comments", comments); } attributes.put("activeTab", activeTab); return attributes; } @Override public User findAuthenticatedUser() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); String username = auth.getName(); return this.userMapper.findByUsername(username); } /** * 更新用户profile * @param userSettingsDto * @return */ @Override public Map<String, Object> updateUserProfile(UserSettingsDto userSettingsDto) { Map<String, Object> attributes = new HashMap<>(); // String authenticatedUsername = this.findAuthenticatedUser().getUsername(); User authenticatedUser = this.findAuthenticatedUser(); String authenticatedUsername = authenticatedUser.getUsername(); String password = authenticatedUser.getPassword(); logger.debug("passward"+password); if (null == authenticatedUsername || authenticatedUsername.equalsIgnoreCase("") || null == userSettingsDto || userSettingsDto.getEmail().isEmpty() || userSettingsDto.getEmail().equals("")) { attributes.put("uploadResultMessage", "uploadFailure"); return attributes; } // update user profile User user = this.storageService.store(userSettingsDto.getAvatar(), authenticatedUsername); if (null == user) { attributes.put("uploadResultMessage", "uploadFailure"); user = this.findAuthenticatedUser(); // find authenticated user if no user found } user.setPassword(password); user.setEmail(userSettingsDto.getEmail()); user.setBio(userSettingsDto.getBio()); this.userMapper.update(user); // return attributes attributes.put("user", user); attributes.put("uploadResultMessage", "uploadSuccess"); return attributes; } @Override public Map<String, Object> getUserSettingPage() { User user = this.findAuthenticatedUser(); UserSettingsDto newUserSettingsForm = new UserSettingsDto(); newUserSettingsForm.setBio(user.getBio()); newUserSettingsForm.setEmail(user.getEmail()); Map<String, Object> attributes = new HashMap<>(); attributes.put("user", user); attributes.put("userSettingsDto", newUserSettingsForm); return attributes; } @Override public Map<String, Object> registerUserAccount(UserRegistrationDto userDto, HttpServletRequest request) { Map<String, Object> attributes = new HashMap<>(); // save newly registered user User user = new User(); user.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword())); //保存时应该将密码编码 // user.setPassword(userDto.getPassword()); user.setUsername(userDto.getUsername()); user.setEmail(userDto.getEmail()); user.setDateCreated(new Timestamp(System.currentTimeMillis())); user.activated(true); user.setRoles(User.USER); user.setConfirmationToken(UUID.randomUUID().toString()); // save new user and get number of affected row logger.debug("用户注册"); int affectedRow = userMapper.save(user); logger.debug("用户注册成功"); // publish registration event String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort(); Locale locale = request.getLocale(); OnRegistrationCompleteEvent event = new OnRegistrationCompleteEvent(user.getUsername(), appUrl, locale); this.evenPublisher.publishEvent(event); // populate attributes String registrationResult = affectedRow == 1 ? "success" : "failure"; attributes.put("userRegistrationResult", registrationResult); return attributes; } }
6:UserMapper.java
package com.qingwenwei.persistence.dao; import com.qingwenwei.persistence.model.User; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper public interface UserMapper { int save(@Param("user") User user); int update(@Param("user") User user); List<User> findAll(); User findById(Long id); User findByUsername(String username); User findByEmail(String email); User findByConfirmationToken(String confirmationToken); }
7;UserMapper.xml
<?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="com.qingwenwei.persistence.dao.UserMapper"> <resultMap id="UserResultMap" type="com.qingwenwei.persistence.model.User"> <id property="id" column="id"/> <result property="username" column="username"/> <result property="password" column="password"/> <result property="email" column="email"/> <result property="confirmationToken" column="confirmation_token"/> <result property="activated" column="activated"/> <result property="dateCreated" column="date_created"/> <result property="avatarLocation" column="avatar_location"/> <result property="bio" column="bio"/> </resultMap> <sql id="baseColumns" > id, username, password, email, activated, date_created, avatar_location, bio,roles </sql> <insert id="save" parameterType="com.qingwenwei.persistence.model.User"> INSERT INTO `T_USER` ( username, password, email, confirmation_token, activated, date_created, avatar_location, bio, roles ) VALUES ( #{user.username}, #{user.password}, #{user.email}, #{user.confirmationToken}, #{user.activated}, #{user.dateCreated}, #{user.avatarLocation}, #{user.bio}, #{user.roles} ) </insert> <select id="findById" parameterType="Long" resultMap="UserResultMap"> SELECT id, username, password, email, activated, date_created, avatar_location, bio, roles FROM T_USER WHERE id = #{id} </select> <select id="findByUsername" parameterType="String" resultMap="UserResultMap"> SELECT id, username, password, email, activated, date_created, avatar_location, bio, roles FROM T_USER WHERE username = #{username} </select> <select id="findByEmail" parameterType="String" resultMap="UserResultMap"> SELECT id, username, password, email, activated, date_created, avatar_location, bio, roles FROM T_USER WHERE email = #{email} </select> <select id="findByConfirmationToken" parameterType="String" resultMap="UserResultMap"> SELECT id, username, password, email, activated, date_created, avatar_location, bio, confirmation_token, roles FROM T_USER WHERE confirmation_token = #{confirmationToken} </select> <select id="findAll" resultMap="UserResultMap"> SELECT id, username, password, email, activated, date_created, avatar_location, bio, confirmation_token, roles FROM T_USER </select> <update id="update" parameterType="com.qingwenwei.persistence.model.User"> UPDATE T_USER SET password = #{user.password}, email = #{user.email}, date_created = #{user.dateCreated}, avatar_location = #{user.avatarLocation}, bio = #{user.bio} WHERE id = #{user.id} </update> </mapper>
8;User.java
package com.qingwenwei.persistence.model; import java.io.Serializable; import java.sql.Timestamp; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; public class User implements Serializable { private static final long serialVersionUID = 1L; // constants public static String USER = "USER"; //两种用户 public static String ADMIN = "ADMIN"; private Long id; private String username; private String password; private String email; private String confirmationToken; private Long activated; private Timestamp dateCreated; private String avatarLocation; private String bio; private String roles; public User() { } public Long getId() { return id; } public void setId(Long 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 getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getConfirmationToken() { return confirmationToken; } public void setConfirmationToken(String confirmationToken) { this.confirmationToken = confirmationToken; } public Long getActivated() { return activated; } public void setActivated(Long activated) { this.activated = activated; } public static void setUSER(String USER) { User.USER = USER; } public static void setADMIN(String ADMIN) { User.ADMIN = ADMIN; } public static long getSerialVersionUID() { return serialVersionUID; } public static String getUSER() { return USER; } public static String getADMIN() { return ADMIN; } public Timestamp getDateCreated() { return dateCreated; } public void setDateCreated(Timestamp dateCreated) { this.dateCreated = dateCreated; } public String getAvatarLocation() { return avatarLocation; } public void setAvatarLocation(String avatarLocation) { this.avatarLocation = avatarLocation; } public String getBio() { return bio; } public void setBio(String bio) { this.bio = bio; } public String getRoles() { return roles; } public void setRoles(String roles) { this.roles = roles; } //赋予该用户的角色 public Set<String> getRolesSet() { if (null == roles) { return null; } return Collections.unmodifiableSet( new HashSet<String>(Arrays.asList(getRoles().split(",")))); } public void addRole(String role) { String currRoles = this.getRoles(); if (null == currRoles || this.getRoles().contains(role)) { return; } this.setRoles(currRoles + "," + role); } public void activated(boolean activated) { this.setActivated(activated == true ? 1L : 0L); } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", password=" + password + ", email=" + email + ", confirmationToken=" + confirmationToken + ", activated=" + activated + ", dateCreated=" + dateCreated + ", avatarLocation=" + avatarLocation + ", bio=" + bio + ", roles=" + roles + "]"; } }
9:配置成功。