【shop-2】使用shiro实现登录
引入依赖
引入shiro
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.3</version>
</dependency>
或者
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.11.0</version>
</dependency>
增加MyBatis配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 使用驼峰命名法转换字段。 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<typeAlias alias="Integer" type="java.lang.Integer"/>
<typeAlias alias="Long" type="java.lang.Long"/>
<typeAlias alias="HashMap" type="java.util.HashMap"/>
<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap"/>
<typeAlias alias="ArrayList" type="java.util.ArrayList"/>
<typeAlias alias="LinkedList" type="java.util.LinkedList"/>
</typeAliases>
<mappers>
<mapper resource="db/mybatis/UserMapper.xml"/>
</mappers>
</configuration>
配置application.properties
这里我们改为application.yml
。
spring:
datasource:
url: jdbc:mysql://localhost:port/databasename?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
username: yourusername
password: yourpassword
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
config-location: classpath:db/mybatis/config.xml
配置Shiro
Realm
@Service
public class ShiroRealm extends AuthorizingRealm {
private VerificationCodeCheckService verificationCodeCheckService;
@Autowired
public ShiroRealm(VerificationCodeCheckService verificationCodeCheckService) {
this.verificationCodeCheckService = verificationCodeCheckService;
this.setCredentialsMatcher(new CredentialsMatcher() {
@Override
public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
return new String((char[]) authenticationToken.getCredentials()).equals(authenticationInfo.getCredentials());
}
});
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String tel = (String) authenticationToken.getPrincipal();
String correctCode = verificationCodeCheckService.getCorrectCode(tel);
return new SimpleAuthenticationInfo(tel, correctCode, getName());
}
}
ShiroConfig
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
Map<String, String> map = new HashMap<>();
map.put("/api/code", "anon");
map.put("/api/login", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
@Bean
public DefaultWebSecurityManager securityManager(ShiroRealm realm) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(realm);
manager.setCacheManager(new MemoryConstrainedCacheManager());
manager.setSessionManager(new DefaultSessionManager());
SecurityUtils.setSecurityManager(manager);
return manager;
}
}
Controller
@RestController
@RequestMapping("/api")
public class AuthController {
private AuthService authService;
@Autowired
public AuthController(AuthService authService) {
this.authService = authService;
}
@GetMapping("/code")
public User sendCode(@RequestParam String tel) {
return authService.sendVerificationCode(tel);
}
@PostMapping("/login")
public User login(@RequestBody TelAndCode telAndCode) {
// https://shiro.apache.org/authentication.html
UsernamePasswordToken token = new UsernamePasswordToken(telAndCode.getTel(), telAndCode.getCode());
token.setRememberMe(true);
Subject currentUser = SecurityUtils.getSubject();
currentUser.login(token);
return null;
}
}
小插曲
- Spring6 使用了java17,在此之前你如果安装了java8,那么环境变量中的
C:\ProgramData\Oracle\Java\javapath
会让你的新配置不生效,删掉即可。 - 运行时
javax.servlet.filter
找不到
引入依赖解决。
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
- 报错
Result Maps collection already contains value for xxx.yyyResultMap
原因是在application.yml
mybatis:
mapper-locations: classpath:db/mybatis/UserMapper.xml
和mybatis的config.xml
<mappers>
<mapper resource="db/mybatis/UserMapper.xml"/>
</mappers>
重复配置了UserMapper.xml
,删除其一。